Home | History | Annotate | Download | only in Objects
      1 #define PY_SSIZE_T_CLEAN
      2 #include "Python.h"
      3 #include "bytes_methods.h"
      4 
      5 PyDoc_STRVAR_shared(_Py_isspace__doc__,
      6 "B.isspace() -> bool\n\
      7 \n\
      8 Return True if all characters in B are whitespace\n\
      9 and there is at least one character in B, False otherwise.");
     10 
     11 PyObject*
     12 _Py_bytes_isspace(const char *cptr, Py_ssize_t len)
     13 {
     14     const unsigned char *p
     15         = (unsigned char *) cptr;
     16     const unsigned char *e;
     17 
     18     /* Shortcut for single character strings */
     19     if (len == 1 && Py_ISSPACE(*p))
     20         Py_RETURN_TRUE;
     21 
     22     /* Special case for empty strings */
     23     if (len == 0)
     24         Py_RETURN_FALSE;
     25 
     26     e = p + len;
     27     for (; p < e; p++) {
     28         if (!Py_ISSPACE(*p))
     29             Py_RETURN_FALSE;
     30     }
     31     Py_RETURN_TRUE;
     32 }
     33 
     34 
     35 PyDoc_STRVAR_shared(_Py_isalpha__doc__,
     36 "B.isalpha() -> bool\n\
     37 \n\
     38 Return True if all characters in B are alphabetic\n\
     39 and there is at least one character in B, False otherwise.");
     40 
     41 PyObject*
     42 _Py_bytes_isalpha(const char *cptr, Py_ssize_t len)
     43 {
     44     const unsigned char *p
     45         = (unsigned char *) cptr;
     46     const unsigned char *e;
     47 
     48     /* Shortcut for single character strings */
     49     if (len == 1 && Py_ISALPHA(*p))
     50         Py_RETURN_TRUE;
     51 
     52     /* Special case for empty strings */
     53     if (len == 0)
     54         Py_RETURN_FALSE;
     55 
     56     e = p + len;
     57     for (; p < e; p++) {
     58         if (!Py_ISALPHA(*p))
     59             Py_RETURN_FALSE;
     60     }
     61     Py_RETURN_TRUE;
     62 }
     63 
     64 
     65 PyDoc_STRVAR_shared(_Py_isalnum__doc__,
     66 "B.isalnum() -> bool\n\
     67 \n\
     68 Return True if all characters in B are alphanumeric\n\
     69 and there is at least one character in B, False otherwise.");
     70 
     71 PyObject*
     72 _Py_bytes_isalnum(const char *cptr, Py_ssize_t len)
     73 {
     74     const unsigned char *p
     75         = (unsigned char *) cptr;
     76     const unsigned char *e;
     77 
     78     /* Shortcut for single character strings */
     79     if (len == 1 && Py_ISALNUM(*p))
     80         Py_RETURN_TRUE;
     81 
     82     /* Special case for empty strings */
     83     if (len == 0)
     84         Py_RETURN_FALSE;
     85 
     86     e = p + len;
     87     for (; p < e; p++) {
     88         if (!Py_ISALNUM(*p))
     89             Py_RETURN_FALSE;
     90     }
     91     Py_RETURN_TRUE;
     92 }
     93 
     94 
     95 PyDoc_STRVAR_shared(_Py_isdigit__doc__,
     96 "B.isdigit() -> bool\n\
     97 \n\
     98 Return True if all characters in B are digits\n\
     99 and there is at least one character in B, False otherwise.");
    100 
    101 PyObject*
    102 _Py_bytes_isdigit(const char *cptr, Py_ssize_t len)
    103 {
    104     const unsigned char *p
    105         = (unsigned char *) cptr;
    106     const unsigned char *e;
    107 
    108     /* Shortcut for single character strings */
    109     if (len == 1 && Py_ISDIGIT(*p))
    110         Py_RETURN_TRUE;
    111 
    112     /* Special case for empty strings */
    113     if (len == 0)
    114         Py_RETURN_FALSE;
    115 
    116     e = p + len;
    117     for (; p < e; p++) {
    118         if (!Py_ISDIGIT(*p))
    119             Py_RETURN_FALSE;
    120     }
    121     Py_RETURN_TRUE;
    122 }
    123 
    124 
    125 PyDoc_STRVAR_shared(_Py_islower__doc__,
    126 "B.islower() -> bool\n\
    127 \n\
    128 Return True if all cased characters in B are lowercase and there is\n\
    129 at least one cased character in B, False otherwise.");
    130 
    131 PyObject*
    132 _Py_bytes_islower(const char *cptr, Py_ssize_t len)
    133 {
    134     const unsigned char *p
    135         = (unsigned char *) cptr;
    136     const unsigned char *e;
    137     int cased;
    138 
    139     /* Shortcut for single character strings */
    140     if (len == 1)
    141         return PyBool_FromLong(Py_ISLOWER(*p));
    142 
    143     /* Special case for empty strings */
    144     if (len == 0)
    145         Py_RETURN_FALSE;
    146 
    147     e = p + len;
    148     cased = 0;
    149     for (; p < e; p++) {
    150         if (Py_ISUPPER(*p))
    151             Py_RETURN_FALSE;
    152         else if (!cased && Py_ISLOWER(*p))
    153             cased = 1;
    154     }
    155     return PyBool_FromLong(cased);
    156 }
    157 
    158 
    159 PyDoc_STRVAR_shared(_Py_isupper__doc__,
    160 "B.isupper() -> bool\n\
    161 \n\
    162 Return True if all cased characters in B are uppercase and there is\n\
    163 at least one cased character in B, False otherwise.");
    164 
    165 PyObject*
    166 _Py_bytes_isupper(const char *cptr, Py_ssize_t len)
    167 {
    168     const unsigned char *p
    169         = (unsigned char *) cptr;
    170     const unsigned char *e;
    171     int cased;
    172 
    173     /* Shortcut for single character strings */
    174     if (len == 1)
    175         return PyBool_FromLong(Py_ISUPPER(*p));
    176 
    177     /* Special case for empty strings */
    178     if (len == 0)
    179         Py_RETURN_FALSE;
    180 
    181     e = p + len;
    182     cased = 0;
    183     for (; p < e; p++) {
    184         if (Py_ISLOWER(*p))
    185             Py_RETURN_FALSE;
    186         else if (!cased && Py_ISUPPER(*p))
    187             cased = 1;
    188     }
    189     return PyBool_FromLong(cased);
    190 }
    191 
    192 
    193 PyDoc_STRVAR_shared(_Py_istitle__doc__,
    194 "B.istitle() -> bool\n\
    195 \n\
    196 Return True if B is a titlecased string and there is at least one\n\
    197 character in B, i.e. uppercase characters may only follow uncased\n\
    198 characters and lowercase characters only cased ones. Return False\n\
    199 otherwise.");
    200 
    201 PyObject*
    202 _Py_bytes_istitle(const char *cptr, Py_ssize_t len)
    203 {
    204     const unsigned char *p
    205         = (unsigned char *) cptr;
    206     const unsigned char *e;
    207     int cased, previous_is_cased;
    208 
    209     /* Shortcut for single character strings */
    210     if (len == 1)
    211         return PyBool_FromLong(Py_ISUPPER(*p));
    212 
    213     /* Special case for empty strings */
    214     if (len == 0)
    215         Py_RETURN_FALSE;
    216 
    217     e = p + len;
    218     cased = 0;
    219     previous_is_cased = 0;
    220     for (; p < e; p++) {
    221         const unsigned char ch = *p;
    222 
    223         if (Py_ISUPPER(ch)) {
    224             if (previous_is_cased)
    225                 Py_RETURN_FALSE;
    226             previous_is_cased = 1;
    227             cased = 1;
    228         }
    229         else if (Py_ISLOWER(ch)) {
    230             if (!previous_is_cased)
    231                 Py_RETURN_FALSE;
    232             previous_is_cased = 1;
    233             cased = 1;
    234         }
    235         else
    236             previous_is_cased = 0;
    237     }
    238     return PyBool_FromLong(cased);
    239 }
    240 
    241 
    242 PyDoc_STRVAR_shared(_Py_lower__doc__,
    243 "B.lower() -> copy of B\n\
    244 \n\
    245 Return a copy of B with all ASCII characters converted to lowercase.");
    246 
    247 void
    248 _Py_bytes_lower(char *result, const char *cptr, Py_ssize_t len)
    249 {
    250     Py_ssize_t i;
    251 
    252     for (i = 0; i < len; i++) {
    253         result[i] = Py_TOLOWER((unsigned char) cptr[i]);
    254     }
    255 }
    256 
    257 
    258 PyDoc_STRVAR_shared(_Py_upper__doc__,
    259 "B.upper() -> copy of B\n\
    260 \n\
    261 Return a copy of B with all ASCII characters converted to uppercase.");
    262 
    263 void
    264 _Py_bytes_upper(char *result, const char *cptr, Py_ssize_t len)
    265 {
    266     Py_ssize_t i;
    267 
    268     for (i = 0; i < len; i++) {
    269         result[i] = Py_TOUPPER((unsigned char) cptr[i]);
    270     }
    271 }
    272 
    273 
    274 PyDoc_STRVAR_shared(_Py_title__doc__,
    275 "B.title() -> copy of B\n\
    276 \n\
    277 Return a titlecased version of B, i.e. ASCII words start with uppercase\n\
    278 characters, all remaining cased characters have lowercase.");
    279 
    280 void
    281 _Py_bytes_title(char *result, const char *s, Py_ssize_t len)
    282 {
    283     Py_ssize_t i;
    284     int previous_is_cased = 0;
    285 
    286     for (i = 0; i < len; i++) {
    287         int c = Py_CHARMASK(*s++);
    288         if (Py_ISLOWER(c)) {
    289             if (!previous_is_cased)
    290                 c = Py_TOUPPER(c);
    291             previous_is_cased = 1;
    292         } else if (Py_ISUPPER(c)) {
    293             if (previous_is_cased)
    294                 c = Py_TOLOWER(c);
    295             previous_is_cased = 1;
    296         } else
    297             previous_is_cased = 0;
    298         *result++ = c;
    299     }
    300 }
    301 
    302 
    303 PyDoc_STRVAR_shared(_Py_capitalize__doc__,
    304 "B.capitalize() -> copy of B\n\
    305 \n\
    306 Return a copy of B with only its first character capitalized (ASCII)\n\
    307 and the rest lower-cased.");
    308 
    309 void
    310 _Py_bytes_capitalize(char *result, const char *s, Py_ssize_t len)
    311 {
    312     Py_ssize_t i;
    313 
    314     if (0 < len) {
    315         int c = Py_CHARMASK(*s++);
    316         if (Py_ISLOWER(c))
    317             *result = Py_TOUPPER(c);
    318         else
    319             *result = c;
    320         result++;
    321     }
    322     for (i = 1; i < len; i++) {
    323         int c = Py_CHARMASK(*s++);
    324         if (Py_ISUPPER(c))
    325             *result = Py_TOLOWER(c);
    326         else
    327             *result = c;
    328         result++;
    329     }
    330 }
    331 
    332 
    333 PyDoc_STRVAR_shared(_Py_swapcase__doc__,
    334 "B.swapcase() -> copy of B\n\
    335 \n\
    336 Return a copy of B with uppercase ASCII characters converted\n\
    337 to lowercase ASCII and vice versa.");
    338 
    339 void
    340 _Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len)
    341 {
    342     Py_ssize_t i;
    343 
    344     for (i = 0; i < len; i++) {
    345         int c = Py_CHARMASK(*s++);
    346         if (Py_ISLOWER(c)) {
    347             *result = Py_TOUPPER(c);
    348         }
    349         else if (Py_ISUPPER(c)) {
    350             *result = Py_TOLOWER(c);
    351         }
    352         else
    353             *result = c;
    354         result++;
    355     }
    356 }
    357 
    358 
    359 PyDoc_STRVAR_shared(_Py_maketrans__doc__,
    360 "B.maketrans(frm, to) -> translation table\n\
    361 \n\
    362 Return a translation table (a bytes object of length 256) suitable\n\
    363 for use in the bytes or bytearray translate method where each byte\n\
    364 in frm is mapped to the byte at the same position in to.\n\
    365 The bytes objects frm and to must be of the same length.");
    366 
    367 PyObject *
    368 _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to)
    369 {
    370     PyObject *res = NULL;
    371     Py_ssize_t i;
    372     char *p;
    373 
    374     if (frm->len != to->len) {
    375         PyErr_Format(PyExc_ValueError,
    376                      "maketrans arguments must have same length");
    377         return NULL;
    378     }
    379     res = PyBytes_FromStringAndSize(NULL, 256);
    380     if (!res)
    381         return NULL;
    382     p = PyBytes_AS_STRING(res);
    383     for (i = 0; i < 256; i++)
    384         p[i] = (char) i;
    385     for (i = 0; i < frm->len; i++) {
    386         p[((unsigned char *)frm->buf)[i]] = ((char *)to->buf)[i];
    387     }
    388 
    389     return res;
    390 }
    391 
    392 #define FASTSEARCH fastsearch
    393 #define STRINGLIB(F) stringlib_##F
    394 #define STRINGLIB_CHAR char
    395 #define STRINGLIB_SIZEOF_CHAR 1
    396 
    397 #include "stringlib/fastsearch.h"
    398 #include "stringlib/count.h"
    399 #include "stringlib/find.h"
    400 
    401 /*
    402 Wraps stringlib_parse_args_finds() and additionally checks whether the
    403 first argument is an integer in range(0, 256).
    404 
    405 If this is the case, writes the integer value to the byte parameter
    406 and sets subobj to NULL. Otherwise, sets the first argument to subobj
    407 and doesn't touch byte. The other parameters are similar to those of
    408 stringlib_parse_args_finds().
    409 */
    410 
    411 Py_LOCAL_INLINE(int)
    412 parse_args_finds_byte(const char *function_name, PyObject *args,
    413                       PyObject **subobj, char *byte,
    414                       Py_ssize_t *start, Py_ssize_t *end)
    415 {
    416     PyObject *tmp_subobj;
    417     Py_ssize_t ival;
    418     PyObject *err;
    419 
    420     if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj,
    421                                    start, end))
    422         return 0;
    423 
    424     if (!PyNumber_Check(tmp_subobj)) {
    425         *subobj = tmp_subobj;
    426         return 1;
    427     }
    428 
    429     ival = PyNumber_AsSsize_t(tmp_subobj, PyExc_OverflowError);
    430     if (ival == -1) {
    431         err = PyErr_Occurred();
    432         if (err && !PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
    433             PyErr_Clear();
    434             *subobj = tmp_subobj;
    435             return 1;
    436         }
    437     }
    438 
    439     if (ival < 0 || ival > 255) {
    440         PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
    441         return 0;
    442     }
    443 
    444     *subobj = NULL;
    445     *byte = (char)ival;
    446     return 1;
    447 }
    448 
    449 /* helper macro to fixup start/end slice values */
    450 #define ADJUST_INDICES(start, end, len)         \
    451     if (end > len)                          \
    452         end = len;                          \
    453     else if (end < 0) {                     \
    454         end += len;                         \
    455         if (end < 0)                        \
    456         end = 0;                        \
    457     }                                       \
    458     if (start < 0) {                        \
    459         start += len;                       \
    460         if (start < 0)                      \
    461         start = 0;                      \
    462     }
    463 
    464 Py_LOCAL_INLINE(Py_ssize_t)
    465 find_internal(const char *str, Py_ssize_t len,
    466               const char *function_name, PyObject *args, int dir)
    467 {
    468     PyObject *subobj;
    469     char byte;
    470     Py_buffer subbuf;
    471     const char *sub;
    472     Py_ssize_t sub_len;
    473     Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
    474     Py_ssize_t res;
    475 
    476     if (!parse_args_finds_byte(function_name, args,
    477                                &subobj, &byte, &start, &end))
    478         return -2;
    479 
    480     if (subobj) {
    481         if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
    482             return -2;
    483 
    484         sub = subbuf.buf;
    485         sub_len = subbuf.len;
    486     }
    487     else {
    488         sub = &byte;
    489         sub_len = 1;
    490     }
    491 
    492     ADJUST_INDICES(start, end, len);
    493     if (end - start < sub_len)
    494         res = -1;
    495     else if (sub_len == 1) {
    496         if (dir > 0)
    497             res = stringlib_find_char(
    498                 str + start, end - start,
    499                 *sub);
    500         else
    501             res = stringlib_rfind_char(
    502                 str + start, end - start,
    503                 *sub);
    504         if (res >= 0)
    505             res += start;
    506     }
    507     else {
    508         if (dir > 0)
    509             res = stringlib_find_slice(
    510                 str, len,
    511                 sub, sub_len, start, end);
    512         else
    513             res = stringlib_rfind_slice(
    514                 str, len,
    515                 sub, sub_len, start, end);
    516     }
    517 
    518     if (subobj)
    519         PyBuffer_Release(&subbuf);
    520 
    521     return res;
    522 }
    523 
    524 PyDoc_STRVAR_shared(_Py_find__doc__,
    525 "B.find(sub[, start[, end]]) -> int\n\
    526 \n\
    527 Return the lowest index in B where subsection sub is found,\n\
    528 such that sub is contained within B[start,end].  Optional\n\
    529 arguments start and end are interpreted as in slice notation.\n\
    530 \n\
    531 Return -1 on failure.");
    532 
    533 PyObject *
    534 _Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args)
    535 {
    536     Py_ssize_t result = find_internal(str, len, "find", args, +1);
    537     if (result == -2)
    538         return NULL;
    539     return PyLong_FromSsize_t(result);
    540 }
    541 
    542 PyDoc_STRVAR_shared(_Py_index__doc__,
    543 "B.index(sub[, start[, end]]) -> int\n\
    544 \n\
    545 Like B.find() but raise ValueError when the subsection is not found.");
    546 
    547 PyObject *
    548 _Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args)
    549 {
    550     Py_ssize_t result = find_internal(str, len, "index", args, +1);
    551     if (result == -2)
    552         return NULL;
    553     if (result == -1) {
    554         PyErr_SetString(PyExc_ValueError,
    555                         "subsection not found");
    556         return NULL;
    557     }
    558     return PyLong_FromSsize_t(result);
    559 }
    560 
    561 PyDoc_STRVAR_shared(_Py_rfind__doc__,
    562 "B.rfind(sub[, start[, end]]) -> int\n\
    563 \n\
    564 Return the highest index in B where subsection sub is found,\n\
    565 such that sub is contained within B[start,end].  Optional\n\
    566 arguments start and end are interpreted as in slice notation.\n\
    567 \n\
    568 Return -1 on failure.");
    569 
    570 PyObject *
    571 _Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args)
    572 {
    573     Py_ssize_t result = find_internal(str, len, "rfind", args, -1);
    574     if (result == -2)
    575         return NULL;
    576     return PyLong_FromSsize_t(result);
    577 }
    578 
    579 PyDoc_STRVAR_shared(_Py_rindex__doc__,
    580 "B.rindex(sub[, start[, end]]) -> int\n\
    581 \n\
    582 Like B.rfind() but raise ValueError when the subsection is not found.");
    583 
    584 PyObject *
    585 _Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args)
    586 {
    587     Py_ssize_t result = find_internal(str, len, "rindex", args, -1);
    588     if (result == -2)
    589         return NULL;
    590     if (result == -1) {
    591         PyErr_SetString(PyExc_ValueError,
    592                         "subsection not found");
    593         return NULL;
    594     }
    595     return PyLong_FromSsize_t(result);
    596 }
    597 
    598 PyDoc_STRVAR_shared(_Py_count__doc__,
    599 "B.count(sub[, start[, end]]) -> int\n\
    600 \n\
    601 Return the number of non-overlapping occurrences of subsection sub in\n\
    602 bytes B[start:end].  Optional arguments start and end are interpreted\n\
    603 as in slice notation.");
    604 
    605 PyObject *
    606 _Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args)
    607 {
    608     PyObject *sub_obj;
    609     const char *sub;
    610     Py_ssize_t sub_len;
    611     char byte;
    612     Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
    613 
    614     Py_buffer vsub;
    615     PyObject *count_obj;
    616 
    617     if (!parse_args_finds_byte("count", args,
    618                                &sub_obj, &byte, &start, &end))
    619         return NULL;
    620 
    621     if (sub_obj) {
    622         if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
    623             return NULL;
    624 
    625         sub = vsub.buf;
    626         sub_len = vsub.len;
    627     }
    628     else {
    629         sub = &byte;
    630         sub_len = 1;
    631     }
    632 
    633     ADJUST_INDICES(start, end, len);
    634 
    635     count_obj = PyLong_FromSsize_t(
    636         stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX)
    637         );
    638 
    639     if (sub_obj)
    640         PyBuffer_Release(&vsub);
    641 
    642     return count_obj;
    643 }
    644 
    645 int
    646 _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg)
    647 {
    648     Py_ssize_t ival = PyNumber_AsSsize_t(arg, NULL);
    649     if (ival == -1 && PyErr_Occurred()) {
    650         Py_buffer varg;
    651         Py_ssize_t pos;
    652         PyErr_Clear();
    653         if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
    654             return -1;
    655         pos = stringlib_find(str, len,
    656                              varg.buf, varg.len, 0);
    657         PyBuffer_Release(&varg);
    658         return pos >= 0;
    659     }
    660     if (ival < 0 || ival >= 256) {
    661         PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
    662         return -1;
    663     }
    664 
    665     return memchr(str, (int) ival, len) != NULL;
    666 }
    667 
    668 
    669 /* Matches the end (direction >= 0) or start (direction < 0) of the buffer
    670  * against substr, using the start and end arguments. Returns
    671  * -1 on error, 0 if not found and 1 if found.
    672  */
    673 static int
    674 tailmatch(const char *str, Py_ssize_t len, PyObject *substr,
    675           Py_ssize_t start, Py_ssize_t end, int direction)
    676 {
    677     Py_buffer sub_view = {NULL, NULL};
    678     const char *sub;
    679     Py_ssize_t slen;
    680 
    681     if (PyBytes_Check(substr)) {
    682         sub = PyBytes_AS_STRING(substr);
    683         slen = PyBytes_GET_SIZE(substr);
    684     }
    685     else {
    686         if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0)
    687             return -1;
    688         sub = sub_view.buf;
    689         slen = sub_view.len;
    690     }
    691 
    692     ADJUST_INDICES(start, end, len);
    693 
    694     if (direction < 0) {
    695         /* startswith */
    696         if (start + slen > len)
    697             goto notfound;
    698     } else {
    699         /* endswith */
    700         if (end - start < slen || start > len)
    701             goto notfound;
    702 
    703         if (end - slen > start)
    704             start = end - slen;
    705     }
    706     if (end - start < slen)
    707         goto notfound;
    708     if (memcmp(str + start, sub, slen) != 0)
    709         goto notfound;
    710 
    711     PyBuffer_Release(&sub_view);
    712     return 1;
    713 
    714 notfound:
    715     PyBuffer_Release(&sub_view);
    716     return 0;
    717 }
    718 
    719 static PyObject *
    720 _Py_bytes_tailmatch(const char *str, Py_ssize_t len,
    721                     const char *function_name, PyObject *args,
    722                     int direction)
    723 {
    724     Py_ssize_t start = 0;
    725     Py_ssize_t end = PY_SSIZE_T_MAX;
    726     PyObject *subobj;
    727     int result;
    728 
    729     if (!stringlib_parse_args_finds(function_name, args, &subobj, &start, &end))
    730         return NULL;
    731     if (PyTuple_Check(subobj)) {
    732         Py_ssize_t i;
    733         for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
    734             result = tailmatch(str, len, PyTuple_GET_ITEM(subobj, i),
    735                                start, end, direction);
    736             if (result == -1)
    737                 return NULL;
    738             else if (result) {
    739                 Py_RETURN_TRUE;
    740             }
    741         }
    742         Py_RETURN_FALSE;
    743     }
    744     result = tailmatch(str, len, subobj, start, end, direction);
    745     if (result == -1) {
    746         if (PyErr_ExceptionMatches(PyExc_TypeError))
    747             PyErr_Format(PyExc_TypeError,
    748                          "%s first arg must be bytes or a tuple of bytes, "
    749                          "not %s",
    750                          function_name, Py_TYPE(subobj)->tp_name);
    751         return NULL;
    752     }
    753     else
    754         return PyBool_FromLong(result);
    755 }
    756 
    757 PyDoc_STRVAR_shared(_Py_startswith__doc__,
    758 "B.startswith(prefix[, start[, end]]) -> bool\n\
    759 \n\
    760 Return True if B starts with the specified prefix, False otherwise.\n\
    761 With optional start, test B beginning at that position.\n\
    762 With optional end, stop comparing B at that position.\n\
    763 prefix can also be a tuple of bytes to try.");
    764 
    765 PyObject *
    766 _Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args)
    767 {
    768     return _Py_bytes_tailmatch(str, len, "startswith", args, -1);
    769 }
    770 
    771 PyDoc_STRVAR_shared(_Py_endswith__doc__,
    772 "B.endswith(suffix[, start[, end]]) -> bool\n\
    773 \n\
    774 Return True if B ends with the specified suffix, False otherwise.\n\
    775 With optional start, test B beginning at that position.\n\
    776 With optional end, stop comparing B at that position.\n\
    777 suffix can also be a tuple of bytes to try.");
    778 
    779 PyObject *
    780 _Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args)
    781 {
    782     return _Py_bytes_tailmatch(str, len, "endswith", args, +1);
    783 }
    784 
    785 PyDoc_STRVAR_shared(_Py_expandtabs__doc__,
    786 "B.expandtabs(tabsize=8) -> copy of B\n\
    787 \n\
    788 Return a copy of B where all tab characters are expanded using spaces.\n\
    789 If tabsize is not given, a tab size of 8 characters is assumed.");
    790 
    791 PyDoc_STRVAR_shared(_Py_ljust__doc__,
    792 "B.ljust(width[, fillchar]) -> copy of B\n"
    793 "\n"
    794 "Return B left justified in a string of length width. Padding is\n"
    795 "done using the specified fill character (default is a space).");
    796 
    797 PyDoc_STRVAR_shared(_Py_rjust__doc__,
    798 "B.rjust(width[, fillchar]) -> copy of B\n"
    799 "\n"
    800 "Return B right justified in a string of length width. Padding is\n"
    801 "done using the specified fill character (default is a space)");
    802 
    803 PyDoc_STRVAR_shared(_Py_center__doc__,
    804 "B.center(width[, fillchar]) -> copy of B\n"
    805 "\n"
    806 "Return B centered in a string of length width.  Padding is\n"
    807 "done using the specified fill character (default is a space).");
    808 
    809 PyDoc_STRVAR_shared(_Py_zfill__doc__,
    810 "B.zfill(width) -> copy of B\n"
    811 "\n"
    812 "Pad a numeric string B with zeros on the left, to fill a field\n"
    813 "of the specified width.  B is never truncated.");
    814 
    815