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