1#define PY_SSIZE_T_CLEAN 2#include "Python.h" 3#include "pycore_abstract.h" // _PyIndex_Check() 4#include "pycore_bytes_methods.h" 5 6PyDoc_STRVAR_shared(_Py_isspace__doc__, 7"B.isspace() -> bool\n\ 8\n\ 9Return True if all characters in B are whitespace\n\ 10and there is at least one character in B, False otherwise."); 11 12PyObject* 13_Py_bytes_isspace(const char *cptr, Py_ssize_t len) 14{ 15 const unsigned char *p 16 = (const unsigned char *) cptr; 17 const unsigned char *e; 18 19 /* Shortcut for single character strings */ 20 if (len == 1 && Py_ISSPACE(*p)) 21 Py_RETURN_TRUE; 22 23 /* Special case for empty strings */ 24 if (len == 0) 25 Py_RETURN_FALSE; 26 27 e = p + len; 28 for (; p < e; p++) { 29 if (!Py_ISSPACE(*p)) 30 Py_RETURN_FALSE; 31 } 32 Py_RETURN_TRUE; 33} 34 35 36PyDoc_STRVAR_shared(_Py_isalpha__doc__, 37"B.isalpha() -> bool\n\ 38\n\ 39Return True if all characters in B are alphabetic\n\ 40and there is at least one character in B, False otherwise."); 41 42PyObject* 43_Py_bytes_isalpha(const char *cptr, Py_ssize_t len) 44{ 45 const unsigned char *p 46 = (const unsigned char *) cptr; 47 const unsigned char *e; 48 49 /* Shortcut for single character strings */ 50 if (len == 1 && Py_ISALPHA(*p)) 51 Py_RETURN_TRUE; 52 53 /* Special case for empty strings */ 54 if (len == 0) 55 Py_RETURN_FALSE; 56 57 e = p + len; 58 for (; p < e; p++) { 59 if (!Py_ISALPHA(*p)) 60 Py_RETURN_FALSE; 61 } 62 Py_RETURN_TRUE; 63} 64 65 66PyDoc_STRVAR_shared(_Py_isalnum__doc__, 67"B.isalnum() -> bool\n\ 68\n\ 69Return True if all characters in B are alphanumeric\n\ 70and there is at least one character in B, False otherwise."); 71 72PyObject* 73_Py_bytes_isalnum(const char *cptr, Py_ssize_t len) 74{ 75 const unsigned char *p 76 = (const unsigned char *) cptr; 77 const unsigned char *e; 78 79 /* Shortcut for single character strings */ 80 if (len == 1 && Py_ISALNUM(*p)) 81 Py_RETURN_TRUE; 82 83 /* Special case for empty strings */ 84 if (len == 0) 85 Py_RETURN_FALSE; 86 87 e = p + len; 88 for (; p < e; p++) { 89 if (!Py_ISALNUM(*p)) 90 Py_RETURN_FALSE; 91 } 92 Py_RETURN_TRUE; 93} 94 95 96PyDoc_STRVAR_shared(_Py_isascii__doc__, 97"B.isascii() -> bool\n\ 98\n\ 99Return True if B is empty or all characters in B are ASCII,\n\ 100False otherwise."); 101 102// Optimization is copied from ascii_decode in unicodeobject.c 103/* Mask to quickly check whether a C 'size_t' contains a 104 non-ASCII, UTF8-encoded char. */ 105#if (SIZEOF_SIZE_T == 8) 106# define ASCII_CHAR_MASK 0x8080808080808080ULL 107#elif (SIZEOF_SIZE_T == 4) 108# define ASCII_CHAR_MASK 0x80808080U 109#else 110# error C 'size_t' size should be either 4 or 8! 111#endif 112 113PyObject* 114_Py_bytes_isascii(const char *cptr, Py_ssize_t len) 115{ 116 const char *p = cptr; 117 const char *end = p + len; 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, ALIGNOF_SIZE_T)) { 123 /* Help allocation */ 124 const char *_p = p; 125 while (_p + SIZEOF_SIZE_T <= end) { 126 size_t value = *(const size_t *) _p; 127 if (value & ASCII_CHAR_MASK) { 128 Py_RETURN_FALSE; 129 } 130 _p += SIZEOF_SIZE_T; 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 147PyDoc_STRVAR_shared(_Py_isdigit__doc__, 148"B.isdigit() -> bool\n\ 149\n\ 150Return True if all characters in B are digits\n\ 151and there is at least one character in B, False otherwise."); 152 153PyObject* 154_Py_bytes_isdigit(const char *cptr, Py_ssize_t len) 155{ 156 const unsigned char *p 157 = (const 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 177PyDoc_STRVAR_shared(_Py_islower__doc__, 178"B.islower() -> bool\n\ 179\n\ 180Return True if all cased characters in B are lowercase and there is\n\ 181at least one cased character in B, False otherwise."); 182 183PyObject* 184_Py_bytes_islower(const char *cptr, Py_ssize_t len) 185{ 186 const unsigned char *p 187 = (const 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 211PyDoc_STRVAR_shared(_Py_isupper__doc__, 212"B.isupper() -> bool\n\ 213\n\ 214Return True if all cased characters in B are uppercase and there is\n\ 215at least one cased character in B, False otherwise."); 216 217PyObject* 218_Py_bytes_isupper(const char *cptr, Py_ssize_t len) 219{ 220 const unsigned char *p 221 = (const 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 245PyDoc_STRVAR_shared(_Py_istitle__doc__, 246"B.istitle() -> bool\n\ 247\n\ 248Return True if B is a titlecased string and there is at least one\n\ 249character in B, i.e. uppercase characters may only follow uncased\n\ 250characters and lowercase characters only cased ones. Return False\n\ 251otherwise."); 252 253PyObject* 254_Py_bytes_istitle(const char *cptr, Py_ssize_t len) 255{ 256 const unsigned char *p 257 = (const 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 294PyDoc_STRVAR_shared(_Py_lower__doc__, 295"B.lower() -> copy of B\n\ 296\n\ 297Return a copy of B with all ASCII characters converted to lowercase."); 298 299void 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 310PyDoc_STRVAR_shared(_Py_upper__doc__, 311"B.upper() -> copy of B\n\ 312\n\ 313Return a copy of B with all ASCII characters converted to uppercase."); 314 315void 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 326PyDoc_STRVAR_shared(_Py_title__doc__, 327"B.title() -> copy of B\n\ 328\n\ 329Return a titlecased version of B, i.e. ASCII words start with uppercase\n\ 330characters, all remaining cased characters have lowercase."); 331 332void 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 355PyDoc_STRVAR_shared(_Py_capitalize__doc__, 356"B.capitalize() -> copy of B\n\ 357\n\ 358Return a copy of B with only its first character capitalized (ASCII)\n\ 359and the rest lower-cased."); 360 361void 362_Py_bytes_capitalize(char *result, const char *s, Py_ssize_t len) 363{ 364 if (len > 0) { 365 *result = Py_TOUPPER(*s); 366 _Py_bytes_lower(result + 1, s + 1, len - 1); 367 } 368} 369 370 371PyDoc_STRVAR_shared(_Py_swapcase__doc__, 372"B.swapcase() -> copy of B\n\ 373\n\ 374Return a copy of B with uppercase ASCII characters converted\n\ 375to lowercase ASCII and vice versa."); 376 377void 378_Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len) 379{ 380 Py_ssize_t i; 381 382 for (i = 0; i < len; i++) { 383 int c = Py_CHARMASK(*s++); 384 if (Py_ISLOWER(c)) { 385 *result = Py_TOUPPER(c); 386 } 387 else if (Py_ISUPPER(c)) { 388 *result = Py_TOLOWER(c); 389 } 390 else 391 *result = c; 392 result++; 393 } 394} 395 396 397PyDoc_STRVAR_shared(_Py_maketrans__doc__, 398"B.maketrans(frm, to) -> translation table\n\ 399\n\ 400Return a translation table (a bytes object of length 256) suitable\n\ 401for use in the bytes or bytearray translate method where each byte\n\ 402in frm is mapped to the byte at the same position in to.\n\ 403The bytes objects frm and to must be of the same length."); 404 405PyObject * 406_Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to) 407{ 408 PyObject *res = NULL; 409 Py_ssize_t i; 410 char *p; 411 412 if (frm->len != to->len) { 413 PyErr_Format(PyExc_ValueError, 414 "maketrans arguments must have same length"); 415 return NULL; 416 } 417 res = PyBytes_FromStringAndSize(NULL, 256); 418 if (!res) 419 return NULL; 420 p = PyBytes_AS_STRING(res); 421 for (i = 0; i < 256; i++) 422 p[i] = (char) i; 423 for (i = 0; i < frm->len; i++) { 424 p[((unsigned char *)frm->buf)[i]] = ((char *)to->buf)[i]; 425 } 426 427 return res; 428} 429 430#define FASTSEARCH fastsearch 431#define STRINGLIB(F) stringlib_##F 432#define STRINGLIB_CHAR char 433#define STRINGLIB_SIZEOF_CHAR 1 434 435#include "stringlib/fastsearch.h" 436#include "stringlib/count.h" 437#include "stringlib/find.h" 438 439/* 440Wraps stringlib_parse_args_finds() and additionally checks the first 441argument type. 442 443In case the first argument is a bytes-like object, sets it to subobj, 444and doesn't touch the byte parameter. 445In case it is an integer in range(0, 256), writes the integer value 446to byte, and sets subobj to NULL. 447 448The other parameters are similar to those of 449stringlib_parse_args_finds(). 450*/ 451 452Py_LOCAL_INLINE(int) 453parse_args_finds_byte(const char *function_name, PyObject *args, 454 PyObject **subobj, char *byte, 455 Py_ssize_t *start, Py_ssize_t *end) 456{ 457 PyObject *tmp_subobj; 458 Py_ssize_t ival; 459 460 if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj, 461 start, end)) 462 return 0; 463 464 if (PyObject_CheckBuffer(tmp_subobj)) { 465 *subobj = tmp_subobj; 466 return 1; 467 } 468 469 if (!_PyIndex_Check(tmp_subobj)) { 470 PyErr_Format(PyExc_TypeError, 471 "argument should be integer or bytes-like object, " 472 "not '%.200s'", 473 Py_TYPE(tmp_subobj)->tp_name); 474 return 0; 475 } 476 477 ival = PyNumber_AsSsize_t(tmp_subobj, NULL); 478 if (ival == -1 && PyErr_Occurred()) { 479 return 0; 480 } 481 if (ival < 0 || ival > 255) { 482 PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); 483 return 0; 484 } 485 486 *subobj = NULL; 487 *byte = (char)ival; 488 return 1; 489} 490 491/* helper macro to fixup start/end slice values */ 492#define ADJUST_INDICES(start, end, len) \ 493 if (end > len) \ 494 end = len; \ 495 else if (end < 0) { \ 496 end += len; \ 497 if (end < 0) \ 498 end = 0; \ 499 } \ 500 if (start < 0) { \ 501 start += len; \ 502 if (start < 0) \ 503 start = 0; \ 504 } 505 506Py_LOCAL_INLINE(Py_ssize_t) 507find_internal(const char *str, Py_ssize_t len, 508 const char *function_name, PyObject *args, int dir) 509{ 510 PyObject *subobj; 511 char byte; 512 Py_buffer subbuf; 513 const char *sub; 514 Py_ssize_t sub_len; 515 Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; 516 Py_ssize_t res; 517 518 if (!parse_args_finds_byte(function_name, args, 519 &subobj, &byte, &start, &end)) 520 return -2; 521 522 if (subobj) { 523 if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0) 524 return -2; 525 526 sub = subbuf.buf; 527 sub_len = subbuf.len; 528 } 529 else { 530 sub = &byte; 531 sub_len = 1; 532 } 533 534 ADJUST_INDICES(start, end, len); 535 if (end - start < sub_len) 536 res = -1; 537 else if (sub_len == 1) { 538 if (dir > 0) 539 res = stringlib_find_char( 540 str + start, end - start, 541 *sub); 542 else 543 res = stringlib_rfind_char( 544 str + start, end - start, 545 *sub); 546 if (res >= 0) 547 res += start; 548 } 549 else { 550 if (dir > 0) 551 res = stringlib_find_slice( 552 str, len, 553 sub, sub_len, start, end); 554 else 555 res = stringlib_rfind_slice( 556 str, len, 557 sub, sub_len, start, end); 558 } 559 560 if (subobj) 561 PyBuffer_Release(&subbuf); 562 563 return res; 564} 565 566PyDoc_STRVAR_shared(_Py_find__doc__, 567"B.find(sub[, start[, end]]) -> int\n\ 568\n\ 569Return the lowest index in B where subsection sub is found,\n\ 570such that sub is contained within B[start,end]. Optional\n\ 571arguments start and end are interpreted as in slice notation.\n\ 572\n\ 573Return -1 on failure."); 574 575PyObject * 576_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args) 577{ 578 Py_ssize_t result = find_internal(str, len, "find", args, +1); 579 if (result == -2) 580 return NULL; 581 return PyLong_FromSsize_t(result); 582} 583 584PyDoc_STRVAR_shared(_Py_index__doc__, 585"B.index(sub[, start[, end]]) -> int\n\ 586\n\ 587Return the lowest index in B where subsection sub is found,\n\ 588such that sub is contained within B[start,end]. Optional\n\ 589arguments start and end are interpreted as in slice notation.\n\ 590\n\ 591Raises ValueError when the subsection is not found."); 592 593PyObject * 594_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args) 595{ 596 Py_ssize_t result = find_internal(str, len, "index", args, +1); 597 if (result == -2) 598 return NULL; 599 if (result == -1) { 600 PyErr_SetString(PyExc_ValueError, 601 "subsection not found"); 602 return NULL; 603 } 604 return PyLong_FromSsize_t(result); 605} 606 607PyDoc_STRVAR_shared(_Py_rfind__doc__, 608"B.rfind(sub[, start[, end]]) -> int\n\ 609\n\ 610Return the highest index in B where subsection sub is found,\n\ 611such that sub is contained within B[start,end]. Optional\n\ 612arguments start and end are interpreted as in slice notation.\n\ 613\n\ 614Return -1 on failure."); 615 616PyObject * 617_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args) 618{ 619 Py_ssize_t result = find_internal(str, len, "rfind", args, -1); 620 if (result == -2) 621 return NULL; 622 return PyLong_FromSsize_t(result); 623} 624 625PyDoc_STRVAR_shared(_Py_rindex__doc__, 626"B.rindex(sub[, start[, end]]) -> int\n\ 627\n\ 628Return the highest index in B where subsection sub is found,\n\ 629such that sub is contained within B[start,end]. Optional\n\ 630arguments start and end are interpreted as in slice notation.\n\ 631\n\ 632Raise ValueError when the subsection is not found."); 633 634PyObject * 635_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args) 636{ 637 Py_ssize_t result = find_internal(str, len, "rindex", args, -1); 638 if (result == -2) 639 return NULL; 640 if (result == -1) { 641 PyErr_SetString(PyExc_ValueError, 642 "subsection not found"); 643 return NULL; 644 } 645 return PyLong_FromSsize_t(result); 646} 647 648PyDoc_STRVAR_shared(_Py_count__doc__, 649"B.count(sub[, start[, end]]) -> int\n\ 650\n\ 651Return the number of non-overlapping occurrences of subsection sub in\n\ 652bytes B[start:end]. Optional arguments start and end are interpreted\n\ 653as in slice notation."); 654 655PyObject * 656_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args) 657{ 658 PyObject *sub_obj; 659 const char *sub; 660 Py_ssize_t sub_len; 661 char byte; 662 Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; 663 664 Py_buffer vsub; 665 PyObject *count_obj; 666 667 if (!parse_args_finds_byte("count", args, 668 &sub_obj, &byte, &start, &end)) 669 return NULL; 670 671 if (sub_obj) { 672 if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0) 673 return NULL; 674 675 sub = vsub.buf; 676 sub_len = vsub.len; 677 } 678 else { 679 sub = &byte; 680 sub_len = 1; 681 } 682 683 ADJUST_INDICES(start, end, len); 684 685 count_obj = PyLong_FromSsize_t( 686 stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX) 687 ); 688 689 if (sub_obj) 690 PyBuffer_Release(&vsub); 691 692 return count_obj; 693} 694 695int 696_Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg) 697{ 698 Py_ssize_t ival = PyNumber_AsSsize_t(arg, NULL); 699 if (ival == -1 && PyErr_Occurred()) { 700 Py_buffer varg; 701 Py_ssize_t pos; 702 PyErr_Clear(); 703 if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) 704 return -1; 705 pos = stringlib_find(str, len, 706 varg.buf, varg.len, 0); 707 PyBuffer_Release(&varg); 708 return pos >= 0; 709 } 710 if (ival < 0 || ival >= 256) { 711 PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); 712 return -1; 713 } 714 715 return memchr(str, (int) ival, len) != NULL; 716} 717 718 719/* Matches the end (direction >= 0) or start (direction < 0) of the buffer 720 * against substr, using the start and end arguments. Returns 721 * -1 on error, 0 if not found and 1 if found. 722 */ 723static int 724tailmatch(const char *str, Py_ssize_t len, PyObject *substr, 725 Py_ssize_t start, Py_ssize_t end, int direction) 726{ 727 Py_buffer sub_view = {NULL, NULL}; 728 const char *sub; 729 Py_ssize_t slen; 730 731 if (PyBytes_Check(substr)) { 732 sub = PyBytes_AS_STRING(substr); 733 slen = PyBytes_GET_SIZE(substr); 734 } 735 else { 736 if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0) 737 return -1; 738 sub = sub_view.buf; 739 slen = sub_view.len; 740 } 741 742 ADJUST_INDICES(start, end, len); 743 744 if (direction < 0) { 745 /* startswith */ 746 if (start > len - slen) 747 goto notfound; 748 } else { 749 /* endswith */ 750 if (end - start < slen || start > len) 751 goto notfound; 752 753 if (end - slen > start) 754 start = end - slen; 755 } 756 if (end - start < slen) 757 goto notfound; 758 if (memcmp(str + start, sub, slen) != 0) 759 goto notfound; 760 761 PyBuffer_Release(&sub_view); 762 return 1; 763 764notfound: 765 PyBuffer_Release(&sub_view); 766 return 0; 767} 768 769static PyObject * 770_Py_bytes_tailmatch(const char *str, Py_ssize_t len, 771 const char *function_name, PyObject *args, 772 int direction) 773{ 774 Py_ssize_t start = 0; 775 Py_ssize_t end = PY_SSIZE_T_MAX; 776 PyObject *subobj; 777 int result; 778 779 if (!stringlib_parse_args_finds(function_name, args, &subobj, &start, &end)) 780 return NULL; 781 if (PyTuple_Check(subobj)) { 782 Py_ssize_t i; 783 for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { 784 result = tailmatch(str, len, PyTuple_GET_ITEM(subobj, i), 785 start, end, direction); 786 if (result == -1) 787 return NULL; 788 else if (result) { 789 Py_RETURN_TRUE; 790 } 791 } 792 Py_RETURN_FALSE; 793 } 794 result = tailmatch(str, len, subobj, start, end, direction); 795 if (result == -1) { 796 if (PyErr_ExceptionMatches(PyExc_TypeError)) 797 PyErr_Format(PyExc_TypeError, 798 "%s first arg must be bytes or a tuple of bytes, " 799 "not %s", 800 function_name, Py_TYPE(subobj)->tp_name); 801 return NULL; 802 } 803 else 804 return PyBool_FromLong(result); 805} 806 807PyDoc_STRVAR_shared(_Py_startswith__doc__, 808"B.startswith(prefix[, start[, end]]) -> bool\n\ 809\n\ 810Return True if B starts with the specified prefix, False otherwise.\n\ 811With optional start, test B beginning at that position.\n\ 812With optional end, stop comparing B at that position.\n\ 813prefix can also be a tuple of bytes to try."); 814 815PyObject * 816_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) 817{ 818 return _Py_bytes_tailmatch(str, len, "startswith", args, -1); 819} 820 821PyDoc_STRVAR_shared(_Py_endswith__doc__, 822"B.endswith(suffix[, start[, end]]) -> bool\n\ 823\n\ 824Return True if B ends with the specified suffix, False otherwise.\n\ 825With optional start, test B beginning at that position.\n\ 826With optional end, stop comparing B at that position.\n\ 827suffix can also be a tuple of bytes to try."); 828 829PyObject * 830_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args) 831{ 832 return _Py_bytes_tailmatch(str, len, "endswith", args, +1); 833} 834