/home/mdboom/Work/builds/cpython/Objects/bytes_methods.c
Line | Count | Source (jump to first uncovered line) |
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_ISSPACE10 (*p)) Branch (20:9): [True: 10, False: 10]
|
21 | Py_RETURN_TRUE; |
22 | |
23 | /* Special case for empty strings */ |
24 | if (len == 0) Branch (24:9): [True: 2, False: 10]
|
25 | Py_RETURN_FALSE; |
26 | |
27 | e = p + len; |
28 | for (; p < e; p++20.6k ) { Branch (28:12): [True: 20.6k, False: 4]
|
29 | if (!Py_ISSPACE(*p)) Branch (29:13): [True: 6, False: 20.6k]
|
30 | Py_RETURN_FALSE; |
31 | } |
32 | Py_RETURN_TRUE4 ; |
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_ISALPHA6 (*p)) Branch (50:9): [True: 6, False: 12]
|
51 | Py_RETURN_TRUE; |
52 | |
53 | /* Special case for empty strings */ |
54 | if (len == 0) Branch (54:9): [True: 2, False: 12]
|
55 | Py_RETURN_FALSE; |
56 | |
57 | e = p + len; |
58 | for (; p < e; p++20.6k ) { Branch (58:12): [True: 20.6k, False: 4]
|
59 | if (!Py_ISALPHA(*p)) Branch (59:13): [True: 8, False: 20.6k]
|
60 | Py_RETURN_FALSE; |
61 | } |
62 | Py_RETURN_TRUE4 ; |
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_ISALNUM6 (*p)) Branch (80:9): [True: 6, False: 14]
|
81 | Py_RETURN_TRUE; |
82 | |
83 | /* Special case for empty strings */ |
84 | if (len == 0) Branch (84:9): [True: 2, False: 14]
|
85 | Py_RETURN_FALSE; |
86 | |
87 | e = p + len; |
88 | for (; p < e; p++20.6k ) { Branch (88:12): [True: 20.6k, False: 6]
|
89 | if (!Py_ISALNUM(*p)) Branch (89:13): [True: 8, False: 20.6k]
|
90 | Py_RETURN_FALSE; |
91 | } |
92 | Py_RETURN_TRUE6 ; |
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) { Branch (119:12): [True: 190, False: 36]
|
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) { Branch (125:20): [True: 40, False: 54]
|
126 | size_t value = *(const size_t *) _p; |
127 | if (value & ASCII_CHAR_MASK) { Branch (127:21): [True: 20, False: 20]
|
128 | Py_RETURN_FALSE; |
129 | } |
130 | _p += SIZEOF_SIZE_T; |
131 | } |
132 | p = _p; |
133 | if (_p == end) Branch (133:17): [True: 4, False: 50]
|
134 | break; |
135 | } |
136 | if ((unsigned char)*p & 0x80) { Branch (136:13): [True: 16, False: 150]
|
137 | Py_RETURN_FALSE; |
138 | } |
139 | p++; |
140 | } |
141 | Py_RETURN_TRUE40 ; |
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_ISDIGIT4 (*p)) Branch (161:9): [True: 4, False: 10]
|
162 | Py_RETURN_TRUE; |
163 | |
164 | /* Special case for empty strings */ |
165 | if (len == 0) Branch (165:9): [True: 2, False: 10]
|
166 | Py_RETURN_FALSE; |
167 | |
168 | e = p + len; |
169 | for (; p < e; p++20.6k ) { Branch (169:12): [True: 20.6k, False: 4]
|
170 | if (!Py_ISDIGIT(*p)) Branch (170:13): [True: 6, False: 20.6k]
|
171 | Py_RETURN_FALSE; |
172 | } |
173 | Py_RETURN_TRUE4 ; |
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) Branch (192:9): [True: 6, False: 12]
|
193 | return PyBool_FromLong(Py_ISLOWER(*p)); |
194 | |
195 | /* Special case for empty strings */ |
196 | if (len == 0) Branch (196:9): [True: 2, False: 10]
|
197 | Py_RETURN_FALSE; |
198 | |
199 | e = p + len; |
200 | cased = 0; |
201 | for (; p < e; p++21.5k ) { Branch (201:12): [True: 21.5k, False: 6]
|
202 | if (Py_ISUPPER(*p)) |
203 | Py_RETURN_FALSE; |
204 | else if (!cased && Py_ISLOWER294 (*p)) Branch (204:18): [True: 294, False: 21.2k]
|
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) Branch (226:9): [True: 6, False: 12]
|
227 | return PyBool_FromLong(Py_ISUPPER(*p)); |
228 | |
229 | /* Special case for empty strings */ |
230 | if (len == 0) Branch (230:9): [True: 2, False: 10]
|
231 | Py_RETURN_FALSE; |
232 | |
233 | e = p + len; |
234 | cased = 0; |
235 | for (; p < e; p++21.8k ) { Branch (235:12): [True: 21.8k, False: 6]
|
236 | if (Py_ISLOWER(*p)) |
237 | Py_RETURN_FALSE; |
238 | else if (!cased && Py_ISUPPER270 (*p)) Branch (238:18): [True: 270, False: 21.5k]
|
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 | /* Shortcut for single character strings */ |
262 | if (len == 1) Branch (262:9): [True: 6, False: 22]
|
263 | return PyBool_FromLong(Py_ISUPPER(*p)); |
264 | |
265 | /* Special case for empty strings */ |
266 | if (len == 0) Branch (266:9): [True: 2, False: 20]
|
267 | Py_RETURN_FALSE; |
268 | |
269 | e = p + len; |
270 | cased = 0; |
271 | previous_is_cased = 0; |
272 | for (; p < e; p++31.0k ) { Branch (272:12): [True: 31.0k, False: 10]
|
273 | const unsigned char ch = *p; |
274 | |
275 | if (Py_ISUPPER(ch)) { |
276 | if (previous_is_cased) Branch (276:17): [True: 4, False: 36]
|
277 | Py_RETURN_FALSE; |
278 | previous_is_cased = 1; |
279 | cased = 1; |
280 | } |
281 | else if (Py_ISLOWER(ch)) { |
282 | if (!previous_is_cased) Branch (282:17): [True: 6, False: 30.9k]
|
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++4.69M ) { Branch (304:17): [True: 4.69M, False: 412k]
|
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++105k ) { Branch (320:17): [True: 105k, False: 8.19k]
|
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++10.5k ) { Branch (338:17): [True: 10.5k, False: 16]
|
339 | int c = Py_CHARMASK(*s++); |
340 | if (Py_ISLOWER(c)) { |
341 | if (!previous_is_cased) Branch (341:17): [True: 22, False: 7.28k]
|
342 | c = Py_TOUPPER(c); |
343 | previous_is_cased = 1; |
344 | } else if (3.25k Py_ISUPPER3.25k (c)) { |
345 | if (previous_is_cased) Branch (345:17): [True: 3.22k, False: 10]
|
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 | if (len > 0) { Branch (364:9): [True: 14, False: 0]
|
365 | *result = Py_TOUPPER(*s); |
366 | _Py_bytes_lower(result + 1, s + 1, len - 1); |
367 | } |
368 | } |
369 | |
370 | |
371 | PyDoc_STRVAR_shared(_Py_swapcase__doc__, |
372 | "B.swapcase() -> copy of B\n\ |
373 | \n\ |
374 | Return a copy of B with uppercase ASCII characters converted\n\ |
375 | to lowercase ASCII and vice versa."); |
376 | |
377 | void |
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++10.4k ) { Branch (382:17): [True: 10.4k, False: 8]
|
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 | |
397 | PyDoc_STRVAR_shared(_Py_maketrans__doc__, |
398 | "B.maketrans(frm, to) -> translation table\n\ |
399 | \n\ |
400 | Return a translation table (a bytes object of length 256) suitable\n\ |
401 | for use in the bytes or bytearray translate method where each byte\n\ |
402 | in frm is mapped to the byte at the same position in to.\n\ |
403 | The bytes objects frm and to must be of the same length."); |
404 | |
405 | PyObject * |
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) { Branch (412:9): [True: 2, False: 97]
|
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) Branch (418:9): [True: 0, False: 97]
|
419 | return NULL; |
420 | p = PyBytes_AS_STRING(res); |
421 | for (i = 0; i < 256; i++24.8k ) Branch (421:17): [True: 24.8k, False: 97]
|
422 | p[i] = (char) i; |
423 | for (i = 0; i < frm->len; i++272 ) { Branch (423:17): [True: 272, False: 97]
|
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 | #define STRINGLIB_FAST_MEMCHR memchr |
435 | |
436 | #include "stringlib/fastsearch.h" |
437 | #include "stringlib/count.h" |
438 | #include "stringlib/find.h" |
439 | |
440 | /* |
441 | Wraps stringlib_parse_args_finds() and additionally checks the first |
442 | argument type. |
443 | |
444 | In case the first argument is a bytes-like object, sets it to subobj, |
445 | and doesn't touch the byte parameter. |
446 | In case it is an integer in range(0, 256), writes the integer value |
447 | to byte, and sets subobj to NULL. |
448 | |
449 | The other parameters are similar to those of |
450 | stringlib_parse_args_finds(). |
451 | */ |
452 | |
453 | Py_LOCAL_INLINE(int) |
454 | parse_args_finds_byte(const char *function_name, PyObject *args, |
455 | PyObject **subobj, char *byte, |
456 | Py_ssize_t *start, Py_ssize_t *end) |
457 | { |
458 | PyObject *tmp_subobj; |
459 | Py_ssize_t ival; |
460 | |
461 | if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj, Branch (461:8): [True: 20, False: 895k]
|
462 | start, end)) |
463 | return 0; |
464 | |
465 | if (PyObject_CheckBuffer(tmp_subobj)) { Branch (465:9): [True: 880k, False: 15.5k]
|
466 | *subobj = tmp_subobj; |
467 | return 1; |
468 | } |
469 | |
470 | if (!_PyIndex_Check(tmp_subobj)) { Branch (470:9): [True: 0, False: 15.5k]
|
471 | PyErr_Format(PyExc_TypeError, |
472 | "argument should be integer or bytes-like object, " |
473 | "not '%.200s'", |
474 | Py_TYPE(tmp_subobj)->tp_name); |
475 | return 0; |
476 | } |
477 | |
478 | ival = PyNumber_AsSsize_t(tmp_subobj, NULL); |
479 | if (ival == -1 && PyErr_Occurred()12 ) { Branch (479:9): [True: 12, False: 15.5k]
Branch (479:23): [True: 0, False: 12]
|
480 | return 0; |
481 | } |
482 | if (ival < 0 || ival > 25515.5k ) { Branch (482:9): [True: 12, False: 15.5k]
Branch (482:21): [True: 24, False: 15.5k]
|
483 | PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); |
484 | return 0; |
485 | } |
486 | |
487 | *subobj = NULL; |
488 | *byte = (char)ival; |
489 | return 1; |
490 | } |
491 | |
492 | /* helper macro to fixup start/end slice values */ |
493 | #define ADJUST_INDICES(start, end, len) \ |
494 | if (end > len) \ |
495 | end = len1.17M ; \ |
496 | else if (156 end < 0156 ) { \ |
497 | end += len; \ |
498 | if (end < 0) \ |
499 | end = 02 ; \ |
500 | } \ |
501 | if (start < 0) { \ |
502 | start += len; \ |
503 | if (start < 0) \ |
504 | start = 04 ; \ |
505 | } |
506 | |
507 | Py_LOCAL_INLINE(Py_ssize_t) |
508 | find_internal(const char *str, Py_ssize_t len, |
509 | const char *function_name, PyObject *args, int dir) |
510 | { |
511 | PyObject *subobj; |
512 | char byte; |
513 | Py_buffer subbuf; |
514 | const char *sub; |
515 | Py_ssize_t sub_len; |
516 | Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; |
517 | Py_ssize_t res; |
518 | |
519 | if (!parse_args_finds_byte(function_name, args, Branch (519:9): [True: 46, False: 754k]
|
520 | &subobj, &byte, &start, &end)) |
521 | return -2; |
522 | |
523 | if (subobj) { Branch (523:9): [True: 739k, False: 15.4k]
|
524 | if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0) Branch (524:13): [True: 0, False: 739k]
|
525 | return -2; |
526 | |
527 | sub = subbuf.buf; |
528 | sub_len = subbuf.len; |
529 | } |
530 | else { |
531 | sub = &byte; |
532 | sub_len = 1; |
533 | } |
534 | |
535 | ADJUST_INDICES(start, end, len); |
536 | if (end - start < sub_len) Branch (536:9): [True: 132k, False: 622k]
|
537 | res = -1; |
538 | else if (sub_len == 1) { Branch (538:14): [True: 224k, False: 397k]
|
539 | if (dir > 0) Branch (539:13): [True: 217k, False: 7.39k]
|
540 | res = stringlib_find_char( |
541 | str + start, end - start, |
542 | *sub); |
543 | else |
544 | res = stringlib_rfind_char( |
545 | str + start, end - start, |
546 | *sub); |
547 | if (res >= 0) Branch (547:13): [True: 203k, False: 21.5k]
|
548 | res += start; |
549 | } |
550 | else { |
551 | if (dir > 0) Branch (551:13): [True: 200k, False: 196k]
|
552 | res = stringlib_find_slice( |
553 | str, len, |
554 | sub, sub_len, start, end); |
555 | else |
556 | res = stringlib_rfind_slice( |
557 | str, len, |
558 | sub, sub_len, start, end); |
559 | } |
560 | |
561 | if (subobj) Branch (561:9): [True: 739k, False: 15.4k]
|
562 | PyBuffer_Release(&subbuf); |
563 | |
564 | return res; |
565 | } |
566 | |
567 | PyDoc_STRVAR_shared(_Py_find__doc__, |
568 | "B.find(sub[, start[, end]]) -> int\n\ |
569 | \n\ |
570 | Return the lowest index in B where subsection sub is found,\n\ |
571 | such that sub is contained within B[start,end]. Optional\n\ |
572 | arguments start and end are interpreted as in slice notation.\n\ |
573 | \n\ |
574 | Return -1 on failure."); |
575 | |
576 | PyObject * |
577 | _Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args) |
578 | { |
579 | Py_ssize_t result = find_internal(str, len, "find", args, +1); |
580 | if (result == -2) Branch (580:9): [True: 16, False: 484k]
|
581 | return NULL; |
582 | return PyLong_FromSsize_t(result); |
583 | } |
584 | |
585 | PyDoc_STRVAR_shared(_Py_index__doc__, |
586 | "B.index(sub[, start[, end]]) -> int\n\ |
587 | \n\ |
588 | Return the lowest index in B where subsection sub is found,\n\ |
589 | such that sub is contained within B[start,end]. Optional\n\ |
590 | arguments start and end are interpreted as in slice notation.\n\ |
591 | \n\ |
592 | Raises ValueError when the subsection is not found."); |
593 | |
594 | PyObject * |
595 | _Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args) |
596 | { |
597 | Py_ssize_t result = find_internal(str, len, "index", args, +1); |
598 | if (result == -2) Branch (598:9): [True: 10, False: 123]
|
599 | return NULL; |
600 | if (result == -1) { Branch (600:9): [True: 33, False: 90]
|
601 | PyErr_SetString(PyExc_ValueError, |
602 | "subsection not found"); |
603 | return NULL; |
604 | } |
605 | return PyLong_FromSsize_t(result); |
606 | } |
607 | |
608 | PyDoc_STRVAR_shared(_Py_rfind__doc__, |
609 | "B.rfind(sub[, start[, end]]) -> int\n\ |
610 | \n\ |
611 | Return the highest index in B where subsection sub is found,\n\ |
612 | such that sub is contained within B[start,end]. Optional\n\ |
613 | arguments start and end are interpreted as in slice notation.\n\ |
614 | \n\ |
615 | Return -1 on failure."); |
616 | |
617 | PyObject * |
618 | _Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args) |
619 | { |
620 | Py_ssize_t result = find_internal(str, len, "rfind", args, -1); |
621 | if (result == -2) Branch (621:9): [True: 10, False: 270k]
|
622 | return NULL; |
623 | return PyLong_FromSsize_t(result); |
624 | } |
625 | |
626 | PyDoc_STRVAR_shared(_Py_rindex__doc__, |
627 | "B.rindex(sub[, start[, end]]) -> int\n\ |
628 | \n\ |
629 | Return the highest index in B where subsection sub is found,\n\ |
630 | such that sub is contained within B[start,end]. Optional\n\ |
631 | arguments start and end are interpreted as in slice notation.\n\ |
632 | \n\ |
633 | Raise ValueError when the subsection is not found."); |
634 | |
635 | PyObject * |
636 | _Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args) |
637 | { |
638 | Py_ssize_t result = find_internal(str, len, "rindex", args, -1); |
639 | if (result == -2) Branch (639:9): [True: 10, False: 84]
|
640 | return NULL; |
641 | if (result == -1) { Branch (641:9): [True: 24, False: 60]
|
642 | PyErr_SetString(PyExc_ValueError, |
643 | "subsection not found"); |
644 | return NULL; |
645 | } |
646 | return PyLong_FromSsize_t(result); |
647 | } |
648 | |
649 | PyDoc_STRVAR_shared(_Py_count__doc__, |
650 | "B.count(sub[, start[, end]]) -> int\n\ |
651 | \n\ |
652 | Return the number of non-overlapping occurrences of subsection sub in\n\ |
653 | bytes B[start:end]. Optional arguments start and end are interpreted\n\ |
654 | as in slice notation."); |
655 | |
656 | PyObject * |
657 | _Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args) |
658 | { |
659 | PyObject *sub_obj; |
660 | const char *sub; |
661 | Py_ssize_t sub_len; |
662 | char byte; |
663 | Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; |
664 | |
665 | Py_buffer vsub; |
666 | PyObject *count_obj; |
667 | |
668 | if (!parse_args_finds_byte("count", args, Branch (668:9): [True: 10, False: 141k]
|
669 | &sub_obj, &byte, &start, &end)) |
670 | return NULL; |
671 | |
672 | if (sub_obj) { Branch (672:9): [True: 140k, False: 14]
|
673 | if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0) Branch (673:13): [True: 0, False: 140k]
|
674 | return NULL; |
675 | |
676 | sub = vsub.buf; |
677 | sub_len = vsub.len; |
678 | } |
679 | else { |
680 | sub = &byte; |
681 | sub_len = 1; |
682 | } |
683 | |
684 | ADJUST_INDICES(start, end, len); |
685 | |
686 | count_obj = PyLong_FromSsize_t( |
687 | stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX) |
688 | ); |
689 | |
690 | if (sub_obj) Branch (690:9): [True: 140k, False: 14]
|
691 | PyBuffer_Release(&vsub); |
692 | |
693 | return count_obj; |
694 | } |
695 | |
696 | int |
697 | _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg) |
698 | { |
699 | Py_ssize_t ival = PyNumber_AsSsize_t(arg, NULL); |
700 | if (ival == -1 && PyErr_Occurred()627k ) { Branch (700:9): [True: 627k, False: 7.09k]
Branch (700:23): [True: 627k, False: 2]
|
701 | Py_buffer varg; |
702 | Py_ssize_t pos; |
703 | PyErr_Clear(); |
704 | if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) Branch (704:13): [True: 9, False: 627k]
|
705 | return -1; |
706 | pos = stringlib_find(str, len, |
707 | varg.buf, varg.len, 0); |
708 | PyBuffer_Release(&varg); |
709 | return pos >= 0; |
710 | } |
711 | if (ival < 0 || ival >= 2567.09k ) { Branch (711:9): [True: 2, False: 7.09k]
Branch (711:21): [True: 4, False: 7.09k]
|
712 | PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); |
713 | return -1; |
714 | } |
715 | |
716 | return memchr(str, (int) ival, len) != NULL; |
717 | } |
718 | |
719 | |
720 | /* Matches the end (direction >= 0) or start (direction < 0) of the buffer |
721 | * against substr, using the start and end arguments. Returns |
722 | * -1 on error, 0 if not found and 1 if found. |
723 | */ |
724 | static int |
725 | tailmatch(const char *str, Py_ssize_t len, PyObject *substr, |
726 | Py_ssize_t start, Py_ssize_t end, int direction) |
727 | { |
728 | Py_buffer sub_view = {NULL, NULL}; |
729 | const char *sub; |
730 | Py_ssize_t slen; |
731 | |
732 | if (PyBytes_Check(substr)) { |
733 | sub = PyBytes_AS_STRING(substr); |
734 | slen = PyBytes_GET_SIZE(substr); |
735 | } |
736 | else { |
737 | if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0) Branch (737:13): [True: 5, False: 24]
|
738 | return -1; |
739 | sub = sub_view.buf; |
740 | slen = sub_view.len; |
741 | } |
742 | |
743 | ADJUST_INDICES(start, end, len); |
744 | |
745 | if (direction < 0) { Branch (745:9): [True: 97.6k, False: 182k]
|
746 | /* startswith */ |
747 | if (start > len - slen) Branch (747:13): [True: 761, False: 96.8k]
|
748 | goto notfound; |
749 | } else { |
750 | /* endswith */ |
751 | if (end - start < slen || start > len182k ) Branch (751:13): [True: 650, False: 182k]
Branch (751:35): [True: 0, False: 182k]
|
752 | goto notfound; |
753 | |
754 | if (end - slen > start) Branch (754:13): [True: 180k, False: 1.34k]
|
755 | start = end - slen; |
756 | } |
757 | if (end - start < slen) Branch (757:9): [True: 0, False: 278k]
|
758 | goto notfound; |
759 | if (memcmp(str + start, sub, slen) != 0) Branch (759:9): [True: 187k, False: 91.6k]
|
760 | goto notfound; |
761 | |
762 | PyBuffer_Release(&sub_view); |
763 | return 1; |
764 | |
765 | notfound: |
766 | PyBuffer_Release(&sub_view); |
767 | return 0; |
768 | } |
769 | |
770 | static PyObject * |
771 | _Py_bytes_tailmatch(const char *str, Py_ssize_t len, |
772 | const char *function_name, PyObject *args, |
773 | int direction) |
774 | { |
775 | Py_ssize_t start = 0; |
776 | Py_ssize_t end = PY_SSIZE_T_MAX; |
777 | PyObject *subobj; |
778 | int result; |
779 | |
780 | if (!stringlib_parse_args_finds(function_name, args, &subobj, &start, &end)) Branch (780:9): [True: 4, False: 280k]
|
781 | return NULL; |
782 | if (PyTuple_Check(subobj)) { |
783 | Py_ssize_t i; |
784 | for (i = 0; i < PyTuple_GET_SIZE(subobj); i++427 ) { Branch (784:21): [True: 441, False: 210]
|
785 | result = tailmatch(str, len, PyTuple_GET_ITEM(subobj, i), |
786 | start, end, direction); |
787 | if (result == -1) Branch (787:17): [True: 0, False: 441]
|
788 | return NULL; |
789 | else if (result) { Branch (789:22): [True: 14, False: 427]
|
790 | Py_RETURN_TRUE; |
791 | } |
792 | } |
793 | Py_RETURN_FALSE210 ; |
794 | } |
795 | result = tailmatch(str, len, subobj, start, end, direction); |
796 | if (result == -1) { Branch (796:9): [True: 5, False: 279k]
|
797 | if (PyErr_ExceptionMatches(PyExc_TypeError)) Branch (797:13): [True: 5, False: 0]
|
798 | PyErr_Format(PyExc_TypeError, |
799 | "%s first arg must be bytes or a tuple of bytes, " |
800 | "not %s", |
801 | function_name, Py_TYPE(subobj)->tp_name); |
802 | return NULL; |
803 | } |
804 | else |
805 | return PyBool_FromLong(result); |
806 | } |
807 | |
808 | PyDoc_STRVAR_shared(_Py_startswith__doc__, |
809 | "B.startswith(prefix[, start[, end]]) -> bool\n\ |
810 | \n\ |
811 | Return True if B starts with the specified prefix, False otherwise.\n\ |
812 | With optional start, test B beginning at that position.\n\ |
813 | With optional end, stop comparing B at that position.\n\ |
814 | prefix can also be a tuple of bytes to try."); |
815 | |
816 | PyObject * |
817 | _Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) |
818 | { |
819 | return _Py_bytes_tailmatch(str, len, "startswith", args, -1); |
820 | } |
821 | |
822 | PyDoc_STRVAR_shared(_Py_endswith__doc__, |
823 | "B.endswith(suffix[, start[, end]]) -> bool\n\ |
824 | \n\ |
825 | Return True if B ends with the specified suffix, False otherwise.\n\ |
826 | With optional start, test B beginning at that position.\n\ |
827 | With optional end, stop comparing B at that position.\n\ |
828 | suffix can also be a tuple of bytes to try."); |
829 | |
830 | PyObject * |
831 | _Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args) |
832 | { |
833 | return _Py_bytes_tailmatch(str, len, "endswith", args, +1); |
834 | } |