| 
									
										
										
										
											2016-07-03 13:26:52 +03:00
										 |  |  | #define PY_SSIZE_T_CLEAN
 | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2020-04-08 02:01:56 +02:00
										 |  |  | #include "pycore_abstract.h"   // _PyIndex_Check()
 | 
					
						
							| 
									
										
										
										
											2020-02-12 22:32:34 +01:00
										 |  |  | #include "pycore_bytes_methods.h"
 | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_isspace__doc__, | 
					
						
							|  |  |  | "B.isspace() -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if all characters in B are whitespace\n\ | 
					
						
							|  |  |  | and there is at least one character in B, False otherwise."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* | 
					
						
							|  |  |  | _Py_bytes_isspace(const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *p | 
					
						
							| 
									
										
										
											
												closes bpo-39605: Fix some casts to not cast away const. (GH-18453)
gcc -Wcast-qual turns up a number of instances of casting away constness of pointers. Some of these can be safely modified, by either:
Adding the const to the type cast, as in:
-    return _PyUnicode_FromUCS1((unsigned char*)s, size);
+    return _PyUnicode_FromUCS1((const unsigned char*)s, size);
or, Removing the cast entirely, because it's not necessary (but probably was at one time), as in:
-    PyDTrace_FUNCTION_ENTRY((char *)filename, (char *)funcname, lineno);
+    PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
These changes will not change code, but they will make it much easier to check for errors in consts
											
										 
											2020-02-11 20:28:35 -06:00
										 |  |  |         = (const unsigned char *) cptr; | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *e; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Shortcut for single character strings */ | 
					
						
							| 
									
										
										
										
											2009-04-27 20:39:49 +00:00
										 |  |  |     if (len == 1 && Py_ISSPACE(*p)) | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |         Py_RETURN_TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Special case for empty strings */ | 
					
						
							|  |  |  |     if (len == 0) | 
					
						
							|  |  |  |         Py_RETURN_FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     e = p + len; | 
					
						
							|  |  |  |     for (; p < e; p++) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (!Py_ISSPACE(*p)) | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |             Py_RETURN_FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_isalpha__doc__, | 
					
						
							|  |  |  | "B.isalpha() -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if all characters in B are alphabetic\n\ | 
					
						
							|  |  |  | and there is at least one character in B, False otherwise."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* | 
					
						
							|  |  |  | _Py_bytes_isalpha(const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *p | 
					
						
							| 
									
										
										
											
												closes bpo-39605: Fix some casts to not cast away const. (GH-18453)
gcc -Wcast-qual turns up a number of instances of casting away constness of pointers. Some of these can be safely modified, by either:
Adding the const to the type cast, as in:
-    return _PyUnicode_FromUCS1((unsigned char*)s, size);
+    return _PyUnicode_FromUCS1((const unsigned char*)s, size);
or, Removing the cast entirely, because it's not necessary (but probably was at one time), as in:
-    PyDTrace_FUNCTION_ENTRY((char *)filename, (char *)funcname, lineno);
+    PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
These changes will not change code, but they will make it much easier to check for errors in consts
											
										 
											2020-02-11 20:28:35 -06:00
										 |  |  |         = (const unsigned char *) cptr; | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *e; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Shortcut for single character strings */ | 
					
						
							| 
									
										
										
										
											2009-04-27 20:39:49 +00:00
										 |  |  |     if (len == 1 && Py_ISALPHA(*p)) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_RETURN_TRUE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Special case for empty strings */ | 
					
						
							|  |  |  |     if (len == 0) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     e = p + len; | 
					
						
							|  |  |  |     for (; p < e; p++) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (!Py_ISALPHA(*p)) | 
					
						
							|  |  |  |             Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_isalnum__doc__, | 
					
						
							|  |  |  | "B.isalnum() -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if all characters in B are alphanumeric\n\ | 
					
						
							|  |  |  | and there is at least one character in B, False otherwise."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* | 
					
						
							|  |  |  | _Py_bytes_isalnum(const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *p | 
					
						
							| 
									
										
										
											
												closes bpo-39605: Fix some casts to not cast away const. (GH-18453)
gcc -Wcast-qual turns up a number of instances of casting away constness of pointers. Some of these can be safely modified, by either:
Adding the const to the type cast, as in:
-    return _PyUnicode_FromUCS1((unsigned char*)s, size);
+    return _PyUnicode_FromUCS1((const unsigned char*)s, size);
or, Removing the cast entirely, because it's not necessary (but probably was at one time), as in:
-    PyDTrace_FUNCTION_ENTRY((char *)filename, (char *)funcname, lineno);
+    PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
These changes will not change code, but they will make it much easier to check for errors in consts
											
										 
											2020-02-11 20:28:35 -06:00
										 |  |  |         = (const unsigned char *) cptr; | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *e; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Shortcut for single character strings */ | 
					
						
							| 
									
										
										
										
											2009-04-27 20:39:49 +00:00
										 |  |  |     if (len == 1 && Py_ISALNUM(*p)) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_RETURN_TRUE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Special case for empty strings */ | 
					
						
							|  |  |  |     if (len == 0) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     e = p + len; | 
					
						
							|  |  |  |     for (; p < e; p++) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (!Py_ISALNUM(*p)) | 
					
						
							|  |  |  |             Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-27 14:06:21 +09:00
										 |  |  | PyDoc_STRVAR_shared(_Py_isascii__doc__, | 
					
						
							|  |  |  | "B.isascii() -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if B is empty or all characters in B are ASCII,\n\ | 
					
						
							|  |  |  | False otherwise."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  | // Optimization is copied from ascii_decode in unicodeobject.c
 | 
					
						
							| 
									
										
										
										
											2020-10-18 22:48:38 +08:00
										 |  |  | /* Mask to quickly check whether a C 'size_t' contains a
 | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  |    non-ASCII, UTF8-encoded char. */ | 
					
						
							| 
									
										
										
										
											2020-10-18 22:48:38 +08:00
										 |  |  | #if (SIZEOF_SIZE_T == 8)
 | 
					
						
							|  |  |  | # define ASCII_CHAR_MASK 0x8080808080808080ULL
 | 
					
						
							|  |  |  | #elif (SIZEOF_SIZE_T == 4)
 | 
					
						
							|  |  |  | # define ASCII_CHAR_MASK 0x80808080U
 | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2020-10-18 22:48:38 +08:00
										 |  |  | # error C 'size_t' size should be either 4 or 8!
 | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-27 14:06:21 +09:00
										 |  |  | PyObject* | 
					
						
							|  |  |  | _Py_bytes_isascii(const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  |     const char *p = cptr; | 
					
						
							|  |  |  |     const char *end = p + len; | 
					
						
							| 
									
										
										
										
											2020-10-18 22:48:38 +08:00
										 |  |  |     const char *aligned_end = (const char *) _Py_ALIGN_DOWN(end, SIZEOF_SIZE_T); | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     while (p < end) { | 
					
						
							|  |  |  |         /* Fast path, see in STRINGLIB(utf8_decode) in stringlib/codecs.h
 | 
					
						
							|  |  |  |            for an explanation. */ | 
					
						
							| 
									
										
										
										
											2020-10-18 22:48:38 +08:00
										 |  |  |         if (_Py_IS_ALIGNED(p, SIZEOF_SIZE_T)) { | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  |             /* Help allocation */ | 
					
						
							|  |  |  |             const char *_p = p; | 
					
						
							|  |  |  |             while (_p < aligned_end) { | 
					
						
							| 
									
										
										
										
											2020-10-18 22:48:38 +08:00
										 |  |  |                 size_t value = *(const size_t *) _p; | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  |                 if (value & ASCII_CHAR_MASK) { | 
					
						
							|  |  |  |                     Py_RETURN_FALSE; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-10-18 22:48:38 +08:00
										 |  |  |                 _p += SIZEOF_SIZE_T; | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  |             } | 
					
						
							|  |  |  |             p = _p; | 
					
						
							|  |  |  |             if (_p == end) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ((unsigned char)*p & 0x80) { | 
					
						
							| 
									
										
										
										
											2018-01-27 14:06:21 +09:00
										 |  |  |             Py_RETURN_FALSE; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  |         p++; | 
					
						
							| 
									
										
										
										
											2018-01-27 14:06:21 +09:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 09:59:12 +09:00
										 |  |  | #undef ASCII_CHAR_MASK
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-27 14:06:21 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | PyDoc_STRVAR_shared(_Py_isdigit__doc__, | 
					
						
							|  |  |  | "B.isdigit() -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if all characters in B are digits\n\ | 
					
						
							|  |  |  | and there is at least one character in B, False otherwise."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* | 
					
						
							|  |  |  | _Py_bytes_isdigit(const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *p | 
					
						
							| 
									
										
										
											
												closes bpo-39605: Fix some casts to not cast away const. (GH-18453)
gcc -Wcast-qual turns up a number of instances of casting away constness of pointers. Some of these can be safely modified, by either:
Adding the const to the type cast, as in:
-    return _PyUnicode_FromUCS1((unsigned char*)s, size);
+    return _PyUnicode_FromUCS1((const unsigned char*)s, size);
or, Removing the cast entirely, because it's not necessary (but probably was at one time), as in:
-    PyDTrace_FUNCTION_ENTRY((char *)filename, (char *)funcname, lineno);
+    PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
These changes will not change code, but they will make it much easier to check for errors in consts
											
										 
											2020-02-11 20:28:35 -06:00
										 |  |  |         = (const unsigned char *) cptr; | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *e; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Shortcut for single character strings */ | 
					
						
							| 
									
										
										
										
											2009-04-27 20:39:49 +00:00
										 |  |  |     if (len == 1 && Py_ISDIGIT(*p)) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_RETURN_TRUE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Special case for empty strings */ | 
					
						
							|  |  |  |     if (len == 0) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     e = p + len; | 
					
						
							|  |  |  |     for (; p < e; p++) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (!Py_ISDIGIT(*p)) | 
					
						
							|  |  |  |             Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_islower__doc__, | 
					
						
							|  |  |  | "B.islower() -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if all cased characters in B are lowercase and there is\n\ | 
					
						
							|  |  |  | at least one cased character in B, False otherwise."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* | 
					
						
							|  |  |  | _Py_bytes_islower(const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *p | 
					
						
							| 
									
										
										
											
												closes bpo-39605: Fix some casts to not cast away const. (GH-18453)
gcc -Wcast-qual turns up a number of instances of casting away constness of pointers. Some of these can be safely modified, by either:
Adding the const to the type cast, as in:
-    return _PyUnicode_FromUCS1((unsigned char*)s, size);
+    return _PyUnicode_FromUCS1((const unsigned char*)s, size);
or, Removing the cast entirely, because it's not necessary (but probably was at one time), as in:
-    PyDTrace_FUNCTION_ENTRY((char *)filename, (char *)funcname, lineno);
+    PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
These changes will not change code, but they will make it much easier to check for errors in consts
											
										 
											2020-02-11 20:28:35 -06:00
										 |  |  |         = (const unsigned char *) cptr; | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *e; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |     int cased; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Shortcut for single character strings */ | 
					
						
							|  |  |  |     if (len == 1) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return PyBool_FromLong(Py_ISLOWER(*p)); | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Special case for empty strings */ | 
					
						
							|  |  |  |     if (len == 0) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     e = p + len; | 
					
						
							|  |  |  |     cased = 0; | 
					
						
							|  |  |  |     for (; p < e; p++) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (Py_ISUPPER(*p)) | 
					
						
							|  |  |  |             Py_RETURN_FALSE; | 
					
						
							|  |  |  |         else if (!cased && Py_ISLOWER(*p)) | 
					
						
							|  |  |  |             cased = 1; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     return PyBool_FromLong(cased); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_isupper__doc__, | 
					
						
							|  |  |  | "B.isupper() -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if all cased characters in B are uppercase and there is\n\ | 
					
						
							|  |  |  | at least one cased character in B, False otherwise."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* | 
					
						
							|  |  |  | _Py_bytes_isupper(const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *p | 
					
						
							| 
									
										
										
											
												closes bpo-39605: Fix some casts to not cast away const. (GH-18453)
gcc -Wcast-qual turns up a number of instances of casting away constness of pointers. Some of these can be safely modified, by either:
Adding the const to the type cast, as in:
-    return _PyUnicode_FromUCS1((unsigned char*)s, size);
+    return _PyUnicode_FromUCS1((const unsigned char*)s, size);
or, Removing the cast entirely, because it's not necessary (but probably was at one time), as in:
-    PyDTrace_FUNCTION_ENTRY((char *)filename, (char *)funcname, lineno);
+    PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
These changes will not change code, but they will make it much easier to check for errors in consts
											
										 
											2020-02-11 20:28:35 -06:00
										 |  |  |         = (const unsigned char *) cptr; | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *e; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |     int cased; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Shortcut for single character strings */ | 
					
						
							|  |  |  |     if (len == 1) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return PyBool_FromLong(Py_ISUPPER(*p)); | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Special case for empty strings */ | 
					
						
							|  |  |  |     if (len == 0) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     e = p + len; | 
					
						
							|  |  |  |     cased = 0; | 
					
						
							|  |  |  |     for (; p < e; p++) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (Py_ISLOWER(*p)) | 
					
						
							|  |  |  |             Py_RETURN_FALSE; | 
					
						
							|  |  |  |         else if (!cased && Py_ISUPPER(*p)) | 
					
						
							|  |  |  |             cased = 1; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     return PyBool_FromLong(cased); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_istitle__doc__, | 
					
						
							|  |  |  | "B.istitle() -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if B is a titlecased string and there is at least one\n\ | 
					
						
							|  |  |  | character in B, i.e. uppercase characters may only follow uncased\n\ | 
					
						
							|  |  |  | characters and lowercase characters only cased ones. Return False\n\ | 
					
						
							|  |  |  | otherwise."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* | 
					
						
							|  |  |  | _Py_bytes_istitle(const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *p | 
					
						
							| 
									
										
										
											
												closes bpo-39605: Fix some casts to not cast away const. (GH-18453)
gcc -Wcast-qual turns up a number of instances of casting away constness of pointers. Some of these can be safely modified, by either:
Adding the const to the type cast, as in:
-    return _PyUnicode_FromUCS1((unsigned char*)s, size);
+    return _PyUnicode_FromUCS1((const unsigned char*)s, size);
or, Removing the cast entirely, because it's not necessary (but probably was at one time), as in:
-    PyDTrace_FUNCTION_ENTRY((char *)filename, (char *)funcname, lineno);
+    PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
These changes will not change code, but they will make it much easier to check for errors in consts
											
										 
											2020-02-11 20:28:35 -06:00
										 |  |  |         = (const unsigned char *) cptr; | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |     const unsigned char *e; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |     int cased, previous_is_cased; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Shortcut for single character strings */ | 
					
						
							|  |  |  |     if (len == 1) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return PyBool_FromLong(Py_ISUPPER(*p)); | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Special case for empty strings */ | 
					
						
							|  |  |  |     if (len == 0) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     e = p + len; | 
					
						
							|  |  |  |     cased = 0; | 
					
						
							|  |  |  |     previous_is_cased = 0; | 
					
						
							|  |  |  |     for (; p < e; p++) { | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  |         const unsigned char ch = *p; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (Py_ISUPPER(ch)) { | 
					
						
							|  |  |  |             if (previous_is_cased) | 
					
						
							|  |  |  |                 Py_RETURN_FALSE; | 
					
						
							|  |  |  |             previous_is_cased = 1; | 
					
						
							|  |  |  |             cased = 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (Py_ISLOWER(ch)) { | 
					
						
							|  |  |  |             if (!previous_is_cased) | 
					
						
							|  |  |  |                 Py_RETURN_FALSE; | 
					
						
							|  |  |  |             previous_is_cased = 1; | 
					
						
							|  |  |  |             cased = 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             previous_is_cased = 0; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     return PyBool_FromLong(cased); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_lower__doc__, | 
					
						
							|  |  |  | "B.lower() -> copy of B\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return a copy of B with all ASCII characters converted to lowercase."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _Py_bytes_lower(char *result, const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     for (i = 0; i < len; i++) { | 
					
						
							| 
									
										
										
										
											2012-01-08 16:22:46 +01:00
										 |  |  |         result[i] = Py_TOLOWER((unsigned char) cptr[i]); | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_upper__doc__, | 
					
						
							|  |  |  | "B.upper() -> copy of B\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return a copy of B with all ASCII characters converted to uppercase."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _Py_bytes_upper(char *result, const char *cptr, Py_ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     for (i = 0; i < len; i++) { | 
					
						
							| 
									
										
										
										
											2012-01-08 16:22:46 +01:00
										 |  |  |         result[i] = Py_TOUPPER((unsigned char) cptr[i]); | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_title__doc__, | 
					
						
							|  |  |  | "B.title() -> copy of B\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return a titlecased version of B, i.e. ASCII words start with uppercase\n\ | 
					
						
							|  |  |  | characters, all remaining cased characters have lowercase."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2015-12-25 20:01:53 +02:00
										 |  |  | _Py_bytes_title(char *result, const char *s, Py_ssize_t len) | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  |     int previous_is_cased = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < len; i++) { | 
					
						
							|  |  |  |         int c = Py_CHARMASK(*s++); | 
					
						
							|  |  |  |         if (Py_ISLOWER(c)) { | 
					
						
							|  |  |  |             if (!previous_is_cased) | 
					
						
							|  |  |  |                 c = Py_TOUPPER(c); | 
					
						
							|  |  |  |             previous_is_cased = 1; | 
					
						
							|  |  |  |         } else if (Py_ISUPPER(c)) { | 
					
						
							|  |  |  |             if (previous_is_cased) | 
					
						
							|  |  |  |                 c = Py_TOLOWER(c); | 
					
						
							|  |  |  |             previous_is_cased = 1; | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |             previous_is_cased = 0; | 
					
						
							|  |  |  |         *result++ = c; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_capitalize__doc__, | 
					
						
							|  |  |  | "B.capitalize() -> copy of B\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2010-07-05 12:00:56 +00:00
										 |  |  | Return a copy of B with only its first character capitalized (ASCII)\n\ | 
					
						
							|  |  |  | and the rest lower-cased."); | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2015-12-25 20:01:53 +02:00
										 |  |  | _Py_bytes_capitalize(char *result, const char *s, Py_ssize_t len) | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-07 09:54:49 +05:00
										 |  |  |     if (len > 0) { | 
					
						
							|  |  |  |         *result = Py_TOUPPER(*s); | 
					
						
							|  |  |  |         _Py_bytes_lower(result + 1, s + 1, len - 1); | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_swapcase__doc__, | 
					
						
							|  |  |  | "B.swapcase() -> copy of B\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return a copy of B with uppercase ASCII characters converted\n\ | 
					
						
							|  |  |  | to lowercase ASCII and vice versa."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2015-12-25 20:01:53 +02:00
										 |  |  | _Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len) | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < len; i++) { | 
					
						
							|  |  |  |         int c = Py_CHARMASK(*s++); | 
					
						
							|  |  |  |         if (Py_ISLOWER(c)) { | 
					
						
							|  |  |  |             *result = Py_TOUPPER(c); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |         else if (Py_ISUPPER(c)) { | 
					
						
							|  |  |  |             *result = Py_TOLOWER(c); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             *result = c; | 
					
						
							|  |  |  |         result++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-10-16 06:31:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-12 15:51:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_maketrans__doc__, | 
					
						
							|  |  |  | "B.maketrans(frm, to) -> translation table\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2011-06-27 09:06:45 -07:00
										 |  |  | Return a translation table (a bytes object of length 256) suitable\n\ | 
					
						
							|  |  |  | for use in the bytes or bytearray translate method where each byte\n\ | 
					
						
							|  |  |  | in frm is mapped to the byte at the same position in to.\n\ | 
					
						
							|  |  |  | The bytes objects frm and to must be of the same length."); | 
					
						
							| 
									
										
										
										
											2009-04-12 15:51:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2015-02-03 01:25:42 +02:00
										 |  |  | _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to) | 
					
						
							| 
									
										
										
										
											2009-04-12 15:51:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-07-27 16:25:09 +02:00
										 |  |  |     PyObject *res = NULL; | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  |     char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-03 01:25:42 +02:00
										 |  |  |     if (frm->len != to->len) { | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |         PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                      "maketrans arguments must have same length"); | 
					
						
							| 
									
										
										
										
											2015-02-03 01:25:42 +02:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     res = PyBytes_FromStringAndSize(NULL, 256); | 
					
						
							| 
									
										
										
										
											2015-02-03 01:25:42 +02:00
										 |  |  |     if (!res) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     p = PyBytes_AS_STRING(res); | 
					
						
							|  |  |  |     for (i = 0; i < 256; i++) | 
					
						
							| 
									
										
										
										
											2010-08-15 17:41:31 +00:00
										 |  |  |         p[i] = (char) i; | 
					
						
							| 
									
										
										
										
											2015-02-03 01:25:42 +02:00
										 |  |  |     for (i = 0; i < frm->len; i++) { | 
					
						
							|  |  |  |         p[((unsigned char *)frm->buf)[i]] = ((char *)to->buf)[i]; | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-12 15:51:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-15 17:38:46 +00:00
										 |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2009-04-12 15:51:51 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define FASTSEARCH fastsearch
 | 
					
						
							|  |  |  | #define STRINGLIB(F) stringlib_##F
 | 
					
						
							|  |  |  | #define STRINGLIB_CHAR char
 | 
					
						
							|  |  |  | #define STRINGLIB_SIZEOF_CHAR 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "stringlib/fastsearch.h"
 | 
					
						
							|  |  |  | #include "stringlib/count.h"
 | 
					
						
							|  |  |  | #include "stringlib/find.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2017-03-13 00:37:05 +02:00
										 |  |  | Wraps stringlib_parse_args_finds() and additionally checks the first | 
					
						
							|  |  |  | argument type. | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-13 00:37:05 +02:00
										 |  |  | In case the first argument is a bytes-like object, sets it to subobj, | 
					
						
							|  |  |  | and doesn't touch the byte parameter. | 
					
						
							|  |  |  | In case it is an integer in range(0, 256), writes the integer value | 
					
						
							|  |  |  | to byte, and sets subobj to NULL. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The other parameters are similar to those of | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  | stringlib_parse_args_finds(). | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_LOCAL_INLINE(int) | 
					
						
							|  |  |  | parse_args_finds_byte(const char *function_name, PyObject *args, | 
					
						
							|  |  |  |                       PyObject **subobj, char *byte, | 
					
						
							|  |  |  |                       Py_ssize_t *start, Py_ssize_t *end) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *tmp_subobj; | 
					
						
							|  |  |  |     Py_ssize_t ival; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj, | 
					
						
							|  |  |  |                                    start, end)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-13 00:37:05 +02:00
										 |  |  |     if (PyObject_CheckBuffer(tmp_subobj)) { | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  |         *subobj = tmp_subobj; | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 02:01:56 +02:00
										 |  |  |     if (!_PyIndex_Check(tmp_subobj)) { | 
					
						
							| 
									
										
										
										
											2017-03-13 00:37:05 +02:00
										 |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                      "argument should be integer or bytes-like object, " | 
					
						
							|  |  |  |                      "not '%.200s'", | 
					
						
							|  |  |  |                      Py_TYPE(tmp_subobj)->tp_name); | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-13 00:37:05 +02:00
										 |  |  |     ival = PyNumber_AsSsize_t(tmp_subobj, NULL); | 
					
						
							|  |  |  |     if (ival == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  |     if (ival < 0 || ival > 255) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *subobj = NULL; | 
					
						
							|  |  |  |     *byte = (char)ival; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* helper macro to fixup start/end slice values */ | 
					
						
							|  |  |  | #define ADJUST_INDICES(start, end, len)         \
 | 
					
						
							|  |  |  |     if (end > len)                          \ | 
					
						
							|  |  |  |         end = len;                          \ | 
					
						
							|  |  |  |     else if (end < 0) {                     \ | 
					
						
							|  |  |  |         end += len;                         \ | 
					
						
							|  |  |  |         if (end < 0)                        \ | 
					
						
							|  |  |  |         end = 0;                        \ | 
					
						
							|  |  |  |     }                                       \ | 
					
						
							|  |  |  |     if (start < 0) {                        \ | 
					
						
							|  |  |  |         start += len;                       \ | 
					
						
							|  |  |  |         if (start < 0)                      \ | 
					
						
							|  |  |  |         start = 0;                      \ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_LOCAL_INLINE(Py_ssize_t) | 
					
						
							|  |  |  | find_internal(const char *str, Py_ssize_t len, | 
					
						
							|  |  |  |               const char *function_name, PyObject *args, int dir) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *subobj; | 
					
						
							|  |  |  |     char byte; | 
					
						
							|  |  |  |     Py_buffer subbuf; | 
					
						
							|  |  |  |     const char *sub; | 
					
						
							|  |  |  |     Py_ssize_t sub_len; | 
					
						
							|  |  |  |     Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; | 
					
						
							|  |  |  |     Py_ssize_t res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!parse_args_finds_byte(function_name, args, | 
					
						
							|  |  |  |                                &subobj, &byte, &start, &end)) | 
					
						
							|  |  |  |         return -2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (subobj) { | 
					
						
							|  |  |  |         if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0) | 
					
						
							|  |  |  |             return -2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sub = subbuf.buf; | 
					
						
							|  |  |  |         sub_len = subbuf.len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         sub = &byte; | 
					
						
							|  |  |  |         sub_len = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ADJUST_INDICES(start, end, len); | 
					
						
							|  |  |  |     if (end - start < sub_len) | 
					
						
							|  |  |  |         res = -1; | 
					
						
							|  |  |  |     else if (sub_len == 1) { | 
					
						
							|  |  |  |         if (dir > 0) | 
					
						
							|  |  |  |             res = stringlib_find_char( | 
					
						
							|  |  |  |                 str + start, end - start, | 
					
						
							|  |  |  |                 *sub); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             res = stringlib_rfind_char( | 
					
						
							|  |  |  |                 str + start, end - start, | 
					
						
							|  |  |  |                 *sub); | 
					
						
							|  |  |  |         if (res >= 0) | 
					
						
							|  |  |  |             res += start; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (dir > 0) | 
					
						
							|  |  |  |             res = stringlib_find_slice( | 
					
						
							|  |  |  |                 str, len, | 
					
						
							|  |  |  |                 sub, sub_len, start, end); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             res = stringlib_rfind_slice( | 
					
						
							|  |  |  |                 str, len, | 
					
						
							|  |  |  |                 sub, sub_len, start, end); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (subobj) | 
					
						
							|  |  |  |         PyBuffer_Release(&subbuf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_find__doc__, | 
					
						
							|  |  |  | "B.find(sub[, start[, end]]) -> int\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return the lowest index in B where subsection sub is found,\n\ | 
					
						
							|  |  |  | such that sub is contained within B[start,end].  Optional\n\ | 
					
						
							|  |  |  | arguments start and end are interpreted as in slice notation.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return -1 on failure."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t result = find_internal(str, len, "find", args, +1); | 
					
						
							|  |  |  |     if (result == -2) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     return PyLong_FromSsize_t(result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_index__doc__, | 
					
						
							|  |  |  | "B.index(sub[, start[, end]]) -> int\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2017-04-04 22:36:22 -07:00
										 |  |  | Return the lowest index in B where subsection sub is found,\n\ | 
					
						
							|  |  |  | such that sub is contained within B[start,end].  Optional\n\ | 
					
						
							|  |  |  | arguments start and end are interpreted as in slice notation.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Raises ValueError when the subsection is not found."); | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t result = find_internal(str, len, "index", args, +1); | 
					
						
							|  |  |  |     if (result == -2) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     if (result == -1) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |                         "subsection not found"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PyLong_FromSsize_t(result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_rfind__doc__, | 
					
						
							|  |  |  | "B.rfind(sub[, start[, end]]) -> int\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return the highest index in B where subsection sub is found,\n\ | 
					
						
							|  |  |  | such that sub is contained within B[start,end].  Optional\n\ | 
					
						
							|  |  |  | arguments start and end are interpreted as in slice notation.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return -1 on failure."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t result = find_internal(str, len, "rfind", args, -1); | 
					
						
							|  |  |  |     if (result == -2) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     return PyLong_FromSsize_t(result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_rindex__doc__, | 
					
						
							|  |  |  | "B.rindex(sub[, start[, end]]) -> int\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2017-04-04 22:36:22 -07:00
										 |  |  | Return the highest index in B where subsection sub is found,\n\ | 
					
						
							|  |  |  | such that sub is contained within B[start,end].  Optional\n\ | 
					
						
							|  |  |  | arguments start and end are interpreted as in slice notation.\n\ | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Raise ValueError when the subsection is not found."); | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t result = find_internal(str, len, "rindex", args, -1); | 
					
						
							|  |  |  |     if (result == -2) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     if (result == -1) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |                         "subsection not found"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PyLong_FromSsize_t(result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_count__doc__, | 
					
						
							|  |  |  | "B.count(sub[, start[, end]]) -> int\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return the number of non-overlapping occurrences of subsection sub in\n\ | 
					
						
							|  |  |  | bytes B[start:end].  Optional arguments start and end are interpreted\n\ | 
					
						
							|  |  |  | as in slice notation."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *sub_obj; | 
					
						
							|  |  |  |     const char *sub; | 
					
						
							|  |  |  |     Py_ssize_t sub_len; | 
					
						
							|  |  |  |     char byte; | 
					
						
							|  |  |  |     Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_buffer vsub; | 
					
						
							|  |  |  |     PyObject *count_obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!parse_args_finds_byte("count", args, | 
					
						
							|  |  |  |                                &sub_obj, &byte, &start, &end)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (sub_obj) { | 
					
						
							|  |  |  |         if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sub = vsub.buf; | 
					
						
							|  |  |  |         sub_len = vsub.len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         sub = &byte; | 
					
						
							|  |  |  |         sub_len = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ADJUST_INDICES(start, end, len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     count_obj = PyLong_FromSsize_t( | 
					
						
							|  |  |  |         stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (sub_obj) | 
					
						
							|  |  |  |         PyBuffer_Release(&vsub); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return count_obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-10 12:37:30 +03:00
										 |  |  |     Py_ssize_t ival = PyNumber_AsSsize_t(arg, NULL); | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  |     if (ival == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         Py_buffer varg; | 
					
						
							|  |  |  |         Py_ssize_t pos; | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         pos = stringlib_find(str, len, | 
					
						
							|  |  |  |                              varg.buf, varg.len, 0); | 
					
						
							|  |  |  |         PyBuffer_Release(&varg); | 
					
						
							|  |  |  |         return pos >= 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ival < 0 || ival >= 256) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return memchr(str, (int) ival, len) != NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Matches the end (direction >= 0) or start (direction < 0) of the buffer
 | 
					
						
							|  |  |  |  * against substr, using the start and end arguments. Returns | 
					
						
							|  |  |  |  * -1 on error, 0 if not found and 1 if found. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-09-09 13:54:34 -07:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  | tailmatch(const char *str, Py_ssize_t len, PyObject *substr, | 
					
						
							|  |  |  |           Py_ssize_t start, Py_ssize_t end, int direction) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_buffer sub_view = {NULL, NULL}; | 
					
						
							|  |  |  |     const char *sub; | 
					
						
							|  |  |  |     Py_ssize_t slen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyBytes_Check(substr)) { | 
					
						
							|  |  |  |         sub = PyBytes_AS_STRING(substr); | 
					
						
							|  |  |  |         slen = PyBytes_GET_SIZE(substr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         sub = sub_view.buf; | 
					
						
							|  |  |  |         slen = sub_view.len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ADJUST_INDICES(start, end, len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (direction < 0) { | 
					
						
							|  |  |  |         /* startswith */ | 
					
						
							| 
									
										
										
										
											2019-10-06 20:17:18 +08:00
										 |  |  |         if (start > len - slen) | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  |             goto notfound; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         /* endswith */ | 
					
						
							|  |  |  |         if (end - start < slen || start > len) | 
					
						
							|  |  |  |             goto notfound; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (end - slen > start) | 
					
						
							|  |  |  |             start = end - slen; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (end - start < slen) | 
					
						
							|  |  |  |         goto notfound; | 
					
						
							|  |  |  |     if (memcmp(str + start, sub, slen) != 0) | 
					
						
							|  |  |  |         goto notfound; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyBuffer_Release(&sub_view); | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | notfound: | 
					
						
							|  |  |  |     PyBuffer_Release(&sub_view); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 13:54:34 -07:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-05-04 22:23:26 +03:00
										 |  |  | _Py_bytes_tailmatch(const char *str, Py_ssize_t len, | 
					
						
							|  |  |  |                     const char *function_name, PyObject *args, | 
					
						
							|  |  |  |                     int direction) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t start = 0; | 
					
						
							|  |  |  |     Py_ssize_t end = PY_SSIZE_T_MAX; | 
					
						
							|  |  |  |     PyObject *subobj; | 
					
						
							|  |  |  |     int result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!stringlib_parse_args_finds(function_name, args, &subobj, &start, &end)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     if (PyTuple_Check(subobj)) { | 
					
						
							|  |  |  |         Py_ssize_t i; | 
					
						
							|  |  |  |         for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { | 
					
						
							|  |  |  |             result = tailmatch(str, len, PyTuple_GET_ITEM(subobj, i), | 
					
						
							|  |  |  |                                start, end, direction); | 
					
						
							|  |  |  |             if (result == -1) | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             else if (result) { | 
					
						
							|  |  |  |                 Py_RETURN_TRUE; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_RETURN_FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     result = tailmatch(str, len, subobj, start, end, direction); | 
					
						
							|  |  |  |     if (result == -1) { | 
					
						
							|  |  |  |         if (PyErr_ExceptionMatches(PyExc_TypeError)) | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                          "%s first arg must be bytes or a tuple of bytes, " | 
					
						
							|  |  |  |                          "not %s", | 
					
						
							|  |  |  |                          function_name, Py_TYPE(subobj)->tp_name); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return PyBool_FromLong(result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_startswith__doc__, | 
					
						
							|  |  |  | "B.startswith(prefix[, start[, end]]) -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if B starts with the specified prefix, False otherwise.\n\ | 
					
						
							|  |  |  | With optional start, test B beginning at that position.\n\ | 
					
						
							|  |  |  | With optional end, stop comparing B at that position.\n\ | 
					
						
							|  |  |  | prefix can also be a tuple of bytes to try."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _Py_bytes_tailmatch(str, len, "startswith", args, -1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR_shared(_Py_endswith__doc__, | 
					
						
							|  |  |  | "B.endswith(suffix[, start[, end]]) -> bool\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return True if B ends with the specified suffix, False otherwise.\n\ | 
					
						
							|  |  |  | With optional start, test B beginning at that position.\n\ | 
					
						
							|  |  |  | With optional end, stop comparing B at that position.\n\ | 
					
						
							|  |  |  | suffix can also be a tuple of bytes to try."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _Py_bytes_tailmatch(str, len, "endswith", args, +1); | 
					
						
							|  |  |  | } |