1 #define PY_SSIZE_T_CLEAN
2 #include "Python.h"
3 #include "pycore_abstract.h" // _PyIndex_Check()
4 #include "pycore_bytes_methods.h"
5
6 PyDoc_STRVAR_shared(_Py_isspace__doc__,
7 "B.isspace() -> bool\n\
8 \n\
9 Return True if all characters in B are whitespace\n\
10 and there is at least one character in B, False otherwise.");
11
12 PyObject*
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
36 PyDoc_STRVAR_shared(_Py_isalpha__doc__,
37 "B.isalpha() -> bool\n\
38 \n\
39 Return True if all characters in B are alphabetic\n\
40 and there is at least one character in B, False otherwise.");
41
42 PyObject*
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
66 PyDoc_STRVAR_shared(_Py_isalnum__doc__,
67 "B.isalnum() -> bool\n\
68 \n\
69 Return True if all characters in B are alphanumeric\n\
70 and there is at least one character in B, False otherwise.");
71
72 PyObject*
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
96 PyDoc_STRVAR_shared(_Py_isascii__doc__,
97 "B.isascii() -> bool\n\
98 \n\
99 Return True if B is empty or all characters in B are ASCII,\n\
100 False 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
113 PyObject*
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
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 = (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
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 = (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
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 = (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
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 = (const unsigned char *) cptr;
258 const unsigned char *e;
259 int cased, previous_is_cased;
260
261 if (len == 1) {
262 if (Py_ISUPPER(*p)) {
263 Py_RETURN_TRUE;
264 }
265 Py_RETURN_FALSE;
266 }
267
268 /* Special case for empty strings */
269 if (len == 0)
270 Py_RETURN_FALSE;
271
272 e = p + len;
273 cased = 0;
274 previous_is_cased = 0;
275 for (; p < e; p++) {
276 const unsigned char ch = *p;
277
278 if (Py_ISUPPER(ch)) {
279 if (previous_is_cased)
280 Py_RETURN_FALSE;
281 previous_is_cased = 1;
282 cased = 1;
283 }
284 else if (Py_ISLOWER(ch)) {
285 if (!previous_is_cased)
286 Py_RETURN_FALSE;
287 previous_is_cased = 1;
288 cased = 1;
289 }
290 else
291 previous_is_cased = 0;
292 }
293 return PyBool_FromLong(cased);
294 }
295
296
297 PyDoc_STRVAR_shared(_Py_lower__doc__,
298 "B.lower() -> copy of B\n\
299 \n\
300 Return a copy of B with all ASCII characters converted to lowercase.");
301
302 void
303 _Py_bytes_lower(char *result, const char *cptr, Py_ssize_t len)
304 {
305 Py_ssize_t i;
306
307 for (i = 0; i < len; i++) {
308 result[i] = Py_TOLOWER((unsigned char) cptr[i]);
309 }
310 }
311
312
313 PyDoc_STRVAR_shared(_Py_upper__doc__,
314 "B.upper() -> copy of B\n\
315 \n\
316 Return a copy of B with all ASCII characters converted to uppercase.");
317
318 void
319 _Py_bytes_upper(char *result, const char *cptr, Py_ssize_t len)
320 {
321 Py_ssize_t i;
322
323 for (i = 0; i < len; i++) {
324 result[i] = Py_TOUPPER((unsigned char) cptr[i]);
325 }
326 }
327
328
329 PyDoc_STRVAR_shared(_Py_title__doc__,
330 "B.title() -> copy of B\n\
331 \n\
332 Return a titlecased version of B, i.e. ASCII words start with uppercase\n\
333 characters, all remaining cased characters have lowercase.");
334
335 void
336 _Py_bytes_title(char *result, const char *s, Py_ssize_t len)
337 {
338 Py_ssize_t i;
339 int previous_is_cased = 0;
340
341 for (i = 0; i < len; i++) {
342 int c = Py_CHARMASK(*s++);
343 if (Py_ISLOWER(c)) {
344 if (!previous_is_cased)
345 c = Py_TOUPPER(c);
346 previous_is_cased = 1;
347 } else if (Py_ISUPPER(c)) {
348 if (previous_is_cased)
349 c = Py_TOLOWER(c);
350 previous_is_cased = 1;
351 } else
352 previous_is_cased = 0;
353 *result++ = c;
354 }
355 }
356
357
358 PyDoc_STRVAR_shared(_Py_capitalize__doc__,
359 "B.capitalize() -> copy of B\n\
360 \n\
361 Return a copy of B with only its first character capitalized (ASCII)\n\
362 and the rest lower-cased.");
363
364 void
365 _Py_bytes_capitalize(char *result, const char *s, Py_ssize_t len)
366 {
367 if (len > 0) {
368 *result = Py_TOUPPER(*s);
369 _Py_bytes_lower(result + 1, s + 1, len - 1);
370 }
371 }
372
373
374 PyDoc_STRVAR_shared(_Py_swapcase__doc__,
375 "B.swapcase() -> copy of B\n\
376 \n\
377 Return a copy of B with uppercase ASCII characters converted\n\
378 to lowercase ASCII and vice versa.");
379
380 void
381 _Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len)
382 {
383 Py_ssize_t i;
384
385 for (i = 0; i < len; i++) {
386 int c = Py_CHARMASK(*s++);
387 if (Py_ISLOWER(c)) {
388 *result = Py_TOUPPER(c);
389 }
390 else if (Py_ISUPPER(c)) {
391 *result = Py_TOLOWER(c);
392 }
393 else
394 *result = c;
395 result++;
396 }
397 }
398
399
400 PyDoc_STRVAR_shared(_Py_maketrans__doc__,
401 "B.maketrans(frm, to) -> translation table\n\
402 \n\
403 Return a translation table (a bytes object of length 256) suitable\n\
404 for use in the bytes or bytearray translate method where each byte\n\
405 in frm is mapped to the byte at the same position in to.\n\
406 The bytes objects frm and to must be of the same length.");
407
408 PyObject *
409 _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to)
410 {
411 PyObject *res = NULL;
412 Py_ssize_t i;
413 char *p;
414
415 if (frm->len != to->len) {
416 PyErr_Format(PyExc_ValueError,
417 "maketrans arguments must have same length");
418 return NULL;
419 }
420 res = PyBytes_FromStringAndSize(NULL, 256);
421 if (!res)
422 return NULL;
423 p = PyBytes_AS_STRING(res);
424 for (i = 0; i < 256; i++)
425 p[i] = (char) i;
426 for (i = 0; i < frm->len; i++) {
427 p[((unsigned char *)frm->buf)[i]] = ((char *)to->buf)[i];
428 }
429
430 return res;
431 }
432
433 #define FASTSEARCH fastsearch
434 #define STRINGLIB(F) stringlib_##F
435 #define STRINGLIB_CHAR char
436 #define STRINGLIB_SIZEOF_CHAR 1
437 #define STRINGLIB_FAST_MEMCHR memchr
438
439 #include "stringlib/fastsearch.h"
440 #include "stringlib/count.h"
441 #include "stringlib/find.h"
442
443 /*
444 Wraps stringlib_parse_args_finds() and additionally checks the first
445 argument type.
446
447 In case the first argument is a bytes-like object, sets it to subobj,
448 and doesn't touch the byte parameter.
449 In case it is an integer in range(0, 256), writes the integer value
450 to byte, and sets subobj to NULL.
451
452 The other parameters are similar to those of
453 stringlib_parse_args_finds().
454 */
455
456 Py_LOCAL_INLINE(int)
457 parse_args_finds_byte(const char *function_name, PyObject *args,
458 PyObject **subobj, char *byte,
459 Py_ssize_t *start, Py_ssize_t *end)
460 {
461 PyObject *tmp_subobj;
462 Py_ssize_t ival;
463
464 if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj,
465 start, end))
466 return 0;
467
468 if (PyObject_CheckBuffer(tmp_subobj)) {
469 *subobj = tmp_subobj;
470 return 1;
471 }
472
473 if (!_PyIndex_Check(tmp_subobj)) {
474 PyErr_Format(PyExc_TypeError,
475 "argument should be integer or bytes-like object, "
476 "not '%.200s'",
477 Py_TYPE(tmp_subobj)->tp_name);
478 return 0;
479 }
480
481 ival = PyNumber_AsSsize_t(tmp_subobj, NULL);
482 if (ival == -1 && PyErr_Occurred()) {
483 return 0;
484 }
485 if (ival < 0 || ival > 255) {
486 PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
487 return 0;
488 }
489
490 *subobj = NULL;
491 *byte = (char)ival;
492 return 1;
493 }
494
495 /* helper macro to fixup start/end slice values */
496 #define ADJUST_INDICES(start, end, len) \
497 if (end > len) \
498 end = len; \
499 else if (end < 0) { \
500 end += len; \
501 if (end < 0) \
502 end = 0; \
503 } \
504 if (start < 0) { \
505 start += len; \
506 if (start < 0) \
507 start = 0; \
508 }
509
510 Py_LOCAL_INLINE(Py_ssize_t)
511 find_internal(const char *str, Py_ssize_t len,
512 const char *function_name, PyObject *args, int dir)
513 {
514 PyObject *subobj;
515 char byte;
516 Py_buffer subbuf;
517 const char *sub;
518 Py_ssize_t sub_len;
519 Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
520 Py_ssize_t res;
521
522 if (!parse_args_finds_byte(function_name, args,
523 &subobj, &byte, &start, &end))
524 return -2;
525
526 if (subobj) {
527 if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
528 return -2;
529
530 sub = subbuf.buf;
531 sub_len = subbuf.len;
532 }
533 else {
534 sub = &byte;
535 sub_len = 1;
536 }
537
538 ADJUST_INDICES(start, end, len);
539 if (end - start < sub_len)
540 res = -1;
541 else if (sub_len == 1) {
542 if (dir > 0)
543 res = stringlib_find_char(
544 str + start, end - start,
545 *sub);
546 else
547 res = stringlib_rfind_char(
548 str + start, end - start,
549 *sub);
550 if (res >= 0)
551 res += start;
552 }
553 else {
554 if (dir > 0)
555 res = stringlib_find_slice(
556 str, len,
557 sub, sub_len, start, end);
558 else
559 res = stringlib_rfind_slice(
560 str, len,
561 sub, sub_len, start, end);
562 }
563
564 if (subobj)
565 PyBuffer_Release(&subbuf);
566
567 return res;
568 }
569
570 PyDoc_STRVAR_shared(_Py_find__doc__,
571 "B.find(sub[, start[, end]]) -> int\n\
572 \n\
573 Return the lowest index in B where subsection sub is found,\n\
574 such that sub is contained within B[start,end]. Optional\n\
575 arguments start and end are interpreted as in slice notation.\n\
576 \n\
577 Return -1 on failure.");
578
579 PyObject *
580 _Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args)
581 {
582 Py_ssize_t result = find_internal(str, len, "find", args, +1);
583 if (result == -2)
584 return NULL;
585 return PyLong_FromSsize_t(result);
586 }
587
588 PyDoc_STRVAR_shared(_Py_index__doc__,
589 "B.index(sub[, start[, end]]) -> int\n\
590 \n\
591 Return the lowest index in B where subsection sub is found,\n\
592 such that sub is contained within B[start,end]. Optional\n\
593 arguments start and end are interpreted as in slice notation.\n\
594 \n\
595 Raises ValueError when the subsection is not found.");
596
597 PyObject *
598 _Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args)
599 {
600 Py_ssize_t result = find_internal(str, len, "index", args, +1);
601 if (result == -2)
602 return NULL;
603 if (result == -1) {
604 PyErr_SetString(PyExc_ValueError,
605 "subsection not found");
606 return NULL;
607 }
608 return PyLong_FromSsize_t(result);
609 }
610
611 PyDoc_STRVAR_shared(_Py_rfind__doc__,
612 "B.rfind(sub[, start[, end]]) -> int\n\
613 \n\
614 Return the highest index in B where subsection sub is found,\n\
615 such that sub is contained within B[start,end]. Optional\n\
616 arguments start and end are interpreted as in slice notation.\n\
617 \n\
618 Return -1 on failure.");
619
620 PyObject *
621 _Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args)
622 {
623 Py_ssize_t result = find_internal(str, len, "rfind", args, -1);
624 if (result == -2)
625 return NULL;
626 return PyLong_FromSsize_t(result);
627 }
628
629 PyDoc_STRVAR_shared(_Py_rindex__doc__,
630 "B.rindex(sub[, start[, end]]) -> int\n\
631 \n\
632 Return the highest index in B where subsection sub is found,\n\
633 such that sub is contained within B[start,end]. Optional\n\
634 arguments start and end are interpreted as in slice notation.\n\
635 \n\
636 Raise ValueError when the subsection is not found.");
637
638 PyObject *
639 _Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args)
640 {
641 Py_ssize_t result = find_internal(str, len, "rindex", args, -1);
642 if (result == -2)
643 return NULL;
644 if (result == -1) {
645 PyErr_SetString(PyExc_ValueError,
646 "subsection not found");
647 return NULL;
648 }
649 return PyLong_FromSsize_t(result);
650 }
651
652 PyDoc_STRVAR_shared(_Py_count__doc__,
653 "B.count(sub[, start[, end]]) -> int\n\
654 \n\
655 Return the number of non-overlapping occurrences of subsection sub in\n\
656 bytes B[start:end]. Optional arguments start and end are interpreted\n\
657 as in slice notation.");
658
659 PyObject *
660 _Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args)
661 {
662 PyObject *sub_obj;
663 const char *sub;
664 Py_ssize_t sub_len;
665 char byte;
666 Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
667
668 Py_buffer vsub;
669 PyObject *count_obj;
670
671 if (!parse_args_finds_byte("count", args,
672 &sub_obj, &byte, &start, &end))
673 return NULL;
674
675 if (sub_obj) {
676 if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
677 return NULL;
678
679 sub = vsub.buf;
680 sub_len = vsub.len;
681 }
682 else {
683 sub = &byte;
684 sub_len = 1;
685 }
686
687 ADJUST_INDICES(start, end, len);
688
689 count_obj = PyLong_FromSsize_t(
690 stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX)
691 );
692
693 if (sub_obj)
694 PyBuffer_Release(&vsub);
695
696 return count_obj;
697 }
698
699 int
700 _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg)
701 {
702 Py_ssize_t ival = PyNumber_AsSsize_t(arg, NULL);
703 if (ival == -1 && PyErr_Occurred()) {
704 Py_buffer varg;
705 Py_ssize_t pos;
706 PyErr_Clear();
707 if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
708 return -1;
709 pos = stringlib_find(str, len,
710 varg.buf, varg.len, 0);
711 PyBuffer_Release(&varg);
712 return pos >= 0;
713 }
714 if (ival < 0 || ival >= 256) {
715 PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
716 return -1;
717 }
718
719 return memchr(str, (int) ival, len) != NULL;
720 }
721
722
723 /* Matches the end (direction >= 0) or start (direction < 0) of the buffer
724 * against substr, using the start and end arguments. Returns
725 * -1 on error, 0 if not found and 1 if found.
726 */
727 static int
728 tailmatch(const char *str, Py_ssize_t len, PyObject *substr,
729 Py_ssize_t start, Py_ssize_t end, int direction)
730 {
731 Py_buffer sub_view = {NULL, NULL};
732 const char *sub;
733 Py_ssize_t slen;
734
735 if (PyBytes_Check(substr)) {
736 sub = PyBytes_AS_STRING(substr);
737 slen = PyBytes_GET_SIZE(substr);
738 }
739 else {
740 if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0)
741 return -1;
742 sub = sub_view.buf;
743 slen = sub_view.len;
744 }
745
746 ADJUST_INDICES(start, end, len);
747
748 if (direction < 0) {
749 /* startswith */
750 if (start > len - slen)
751 goto notfound;
752 } else {
753 /* endswith */
754 if (end - start < slen || start > len)
755 goto notfound;
756
757 if (end - slen > start)
758 start = end - slen;
759 }
760 if (end - start < slen)
761 goto notfound;
762 if (memcmp(str + start, sub, slen) != 0)
763 goto notfound;
764
765 PyBuffer_Release(&sub_view);
766 return 1;
767
768 notfound:
769 PyBuffer_Release(&sub_view);
770 return 0;
771 }
772
773 static PyObject *
774 _Py_bytes_tailmatch(const char *str, Py_ssize_t len,
775 const char *function_name, PyObject *args,
776 int direction)
777 {
778 Py_ssize_t start = 0;
779 Py_ssize_t end = PY_SSIZE_T_MAX;
780 PyObject *subobj = NULL;
781 int result;
782
783 if (!stringlib_parse_args_finds(function_name, args, &subobj, &start, &end))
784 return NULL;
785 if (PyTuple_Check(subobj)) {
786 Py_ssize_t i;
787 for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
788 result = tailmatch(str, len, PyTuple_GET_ITEM(subobj, i),
789 start, end, direction);
790 if (result == -1)
791 return NULL;
792 else if (result) {
793 Py_RETURN_TRUE;
794 }
795 }
796 Py_RETURN_FALSE;
797 }
798 result = tailmatch(str, len, subobj, start, end, direction);
799 if (result == -1) {
800 if (PyErr_ExceptionMatches(PyExc_TypeError))
801 PyErr_Format(PyExc_TypeError,
802 "%s first arg must be bytes or a tuple of bytes, "
803 "not %s",
804 function_name, Py_TYPE(subobj)->tp_name);
805 return NULL;
806 }
807 else
808 return PyBool_FromLong(result);
809 }
810
811 PyDoc_STRVAR_shared(_Py_startswith__doc__,
812 "B.startswith(prefix[, start[, end]]) -> bool\n\
813 \n\
814 Return True if B starts with the specified prefix, False otherwise.\n\
815 With optional start, test B beginning at that position.\n\
816 With optional end, stop comparing B at that position.\n\
817 prefix can also be a tuple of bytes to try.");
818
819 PyObject *
820 _Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args)
821 {
822 return _Py_bytes_tailmatch(str, len, "startswith", args, -1);
823 }
824
825 PyDoc_STRVAR_shared(_Py_endswith__doc__,
826 "B.endswith(suffix[, start[, end]]) -> bool\n\
827 \n\
828 Return True if B ends with the specified suffix, False otherwise.\n\
829 With optional start, test B beginning at that position.\n\
830 With optional end, stop comparing B at that position.\n\
831 suffix can also be a tuple of bytes to try.");
832
833 PyObject *
834 _Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args)
835 {
836 return _Py_bytes_tailmatch(str, len, "endswith", args, +1);
837 }