ยปCore Development>Code coverage>Objects/bytes_methods.c

Python code coverage for Objects/bytes_methods.c

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