17db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN 27db96d56Sopenharmony_ci#include "Python.h" 37db96d56Sopenharmony_ci#include "pycore_abstract.h" // _PyIndex_Check() 47db96d56Sopenharmony_ci#include "pycore_bytes_methods.h" 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_isspace__doc__, 77db96d56Sopenharmony_ci"B.isspace() -> bool\n\ 87db96d56Sopenharmony_ci\n\ 97db96d56Sopenharmony_ciReturn True if all characters in B are whitespace\n\ 107db96d56Sopenharmony_ciand there is at least one character in B, False otherwise."); 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ciPyObject* 137db96d56Sopenharmony_ci_Py_bytes_isspace(const char *cptr, Py_ssize_t len) 147db96d56Sopenharmony_ci{ 157db96d56Sopenharmony_ci const unsigned char *p 167db96d56Sopenharmony_ci = (const unsigned char *) cptr; 177db96d56Sopenharmony_ci const unsigned char *e; 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci /* Shortcut for single character strings */ 207db96d56Sopenharmony_ci if (len == 1 && Py_ISSPACE(*p)) 217db96d56Sopenharmony_ci Py_RETURN_TRUE; 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ci /* Special case for empty strings */ 247db96d56Sopenharmony_ci if (len == 0) 257db96d56Sopenharmony_ci Py_RETURN_FALSE; 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci e = p + len; 287db96d56Sopenharmony_ci for (; p < e; p++) { 297db96d56Sopenharmony_ci if (!Py_ISSPACE(*p)) 307db96d56Sopenharmony_ci Py_RETURN_FALSE; 317db96d56Sopenharmony_ci } 327db96d56Sopenharmony_ci Py_RETURN_TRUE; 337db96d56Sopenharmony_ci} 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_isalpha__doc__, 377db96d56Sopenharmony_ci"B.isalpha() -> bool\n\ 387db96d56Sopenharmony_ci\n\ 397db96d56Sopenharmony_ciReturn True if all characters in B are alphabetic\n\ 407db96d56Sopenharmony_ciand there is at least one character in B, False otherwise."); 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ciPyObject* 437db96d56Sopenharmony_ci_Py_bytes_isalpha(const char *cptr, Py_ssize_t len) 447db96d56Sopenharmony_ci{ 457db96d56Sopenharmony_ci const unsigned char *p 467db96d56Sopenharmony_ci = (const unsigned char *) cptr; 477db96d56Sopenharmony_ci const unsigned char *e; 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci /* Shortcut for single character strings */ 507db96d56Sopenharmony_ci if (len == 1 && Py_ISALPHA(*p)) 517db96d56Sopenharmony_ci Py_RETURN_TRUE; 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci /* Special case for empty strings */ 547db96d56Sopenharmony_ci if (len == 0) 557db96d56Sopenharmony_ci Py_RETURN_FALSE; 567db96d56Sopenharmony_ci 577db96d56Sopenharmony_ci e = p + len; 587db96d56Sopenharmony_ci for (; p < e; p++) { 597db96d56Sopenharmony_ci if (!Py_ISALPHA(*p)) 607db96d56Sopenharmony_ci Py_RETURN_FALSE; 617db96d56Sopenharmony_ci } 627db96d56Sopenharmony_ci Py_RETURN_TRUE; 637db96d56Sopenharmony_ci} 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_isalnum__doc__, 677db96d56Sopenharmony_ci"B.isalnum() -> bool\n\ 687db96d56Sopenharmony_ci\n\ 697db96d56Sopenharmony_ciReturn True if all characters in B are alphanumeric\n\ 707db96d56Sopenharmony_ciand there is at least one character in B, False otherwise."); 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ciPyObject* 737db96d56Sopenharmony_ci_Py_bytes_isalnum(const char *cptr, Py_ssize_t len) 747db96d56Sopenharmony_ci{ 757db96d56Sopenharmony_ci const unsigned char *p 767db96d56Sopenharmony_ci = (const unsigned char *) cptr; 777db96d56Sopenharmony_ci const unsigned char *e; 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_ci /* Shortcut for single character strings */ 807db96d56Sopenharmony_ci if (len == 1 && Py_ISALNUM(*p)) 817db96d56Sopenharmony_ci Py_RETURN_TRUE; 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_ci /* Special case for empty strings */ 847db96d56Sopenharmony_ci if (len == 0) 857db96d56Sopenharmony_ci Py_RETURN_FALSE; 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci e = p + len; 887db96d56Sopenharmony_ci for (; p < e; p++) { 897db96d56Sopenharmony_ci if (!Py_ISALNUM(*p)) 907db96d56Sopenharmony_ci Py_RETURN_FALSE; 917db96d56Sopenharmony_ci } 927db96d56Sopenharmony_ci Py_RETURN_TRUE; 937db96d56Sopenharmony_ci} 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_isascii__doc__, 977db96d56Sopenharmony_ci"B.isascii() -> bool\n\ 987db96d56Sopenharmony_ci\n\ 997db96d56Sopenharmony_ciReturn True if B is empty or all characters in B are ASCII,\n\ 1007db96d56Sopenharmony_ciFalse otherwise."); 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci// Optimization is copied from ascii_decode in unicodeobject.c 1037db96d56Sopenharmony_ci/* Mask to quickly check whether a C 'size_t' contains a 1047db96d56Sopenharmony_ci non-ASCII, UTF8-encoded char. */ 1057db96d56Sopenharmony_ci#if (SIZEOF_SIZE_T == 8) 1067db96d56Sopenharmony_ci# define ASCII_CHAR_MASK 0x8080808080808080ULL 1077db96d56Sopenharmony_ci#elif (SIZEOF_SIZE_T == 4) 1087db96d56Sopenharmony_ci# define ASCII_CHAR_MASK 0x80808080U 1097db96d56Sopenharmony_ci#else 1107db96d56Sopenharmony_ci# error C 'size_t' size should be either 4 or 8! 1117db96d56Sopenharmony_ci#endif 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ciPyObject* 1147db96d56Sopenharmony_ci_Py_bytes_isascii(const char *cptr, Py_ssize_t len) 1157db96d56Sopenharmony_ci{ 1167db96d56Sopenharmony_ci const char *p = cptr; 1177db96d56Sopenharmony_ci const char *end = p + len; 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci while (p < end) { 1207db96d56Sopenharmony_ci /* Fast path, see in STRINGLIB(utf8_decode) in stringlib/codecs.h 1217db96d56Sopenharmony_ci for an explanation. */ 1227db96d56Sopenharmony_ci if (_Py_IS_ALIGNED(p, ALIGNOF_SIZE_T)) { 1237db96d56Sopenharmony_ci /* Help allocation */ 1247db96d56Sopenharmony_ci const char *_p = p; 1257db96d56Sopenharmony_ci while (_p + SIZEOF_SIZE_T <= end) { 1267db96d56Sopenharmony_ci size_t value = *(const size_t *) _p; 1277db96d56Sopenharmony_ci if (value & ASCII_CHAR_MASK) { 1287db96d56Sopenharmony_ci Py_RETURN_FALSE; 1297db96d56Sopenharmony_ci } 1307db96d56Sopenharmony_ci _p += SIZEOF_SIZE_T; 1317db96d56Sopenharmony_ci } 1327db96d56Sopenharmony_ci p = _p; 1337db96d56Sopenharmony_ci if (_p == end) 1347db96d56Sopenharmony_ci break; 1357db96d56Sopenharmony_ci } 1367db96d56Sopenharmony_ci if ((unsigned char)*p & 0x80) { 1377db96d56Sopenharmony_ci Py_RETURN_FALSE; 1387db96d56Sopenharmony_ci } 1397db96d56Sopenharmony_ci p++; 1407db96d56Sopenharmony_ci } 1417db96d56Sopenharmony_ci Py_RETURN_TRUE; 1427db96d56Sopenharmony_ci} 1437db96d56Sopenharmony_ci 1447db96d56Sopenharmony_ci#undef ASCII_CHAR_MASK 1457db96d56Sopenharmony_ci 1467db96d56Sopenharmony_ci 1477db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_isdigit__doc__, 1487db96d56Sopenharmony_ci"B.isdigit() -> bool\n\ 1497db96d56Sopenharmony_ci\n\ 1507db96d56Sopenharmony_ciReturn True if all characters in B are digits\n\ 1517db96d56Sopenharmony_ciand there is at least one character in B, False otherwise."); 1527db96d56Sopenharmony_ci 1537db96d56Sopenharmony_ciPyObject* 1547db96d56Sopenharmony_ci_Py_bytes_isdigit(const char *cptr, Py_ssize_t len) 1557db96d56Sopenharmony_ci{ 1567db96d56Sopenharmony_ci const unsigned char *p 1577db96d56Sopenharmony_ci = (const unsigned char *) cptr; 1587db96d56Sopenharmony_ci const unsigned char *e; 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ci /* Shortcut for single character strings */ 1617db96d56Sopenharmony_ci if (len == 1 && Py_ISDIGIT(*p)) 1627db96d56Sopenharmony_ci Py_RETURN_TRUE; 1637db96d56Sopenharmony_ci 1647db96d56Sopenharmony_ci /* Special case for empty strings */ 1657db96d56Sopenharmony_ci if (len == 0) 1667db96d56Sopenharmony_ci Py_RETURN_FALSE; 1677db96d56Sopenharmony_ci 1687db96d56Sopenharmony_ci e = p + len; 1697db96d56Sopenharmony_ci for (; p < e; p++) { 1707db96d56Sopenharmony_ci if (!Py_ISDIGIT(*p)) 1717db96d56Sopenharmony_ci Py_RETURN_FALSE; 1727db96d56Sopenharmony_ci } 1737db96d56Sopenharmony_ci Py_RETURN_TRUE; 1747db96d56Sopenharmony_ci} 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_ci 1777db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_islower__doc__, 1787db96d56Sopenharmony_ci"B.islower() -> bool\n\ 1797db96d56Sopenharmony_ci\n\ 1807db96d56Sopenharmony_ciReturn True if all cased characters in B are lowercase and there is\n\ 1817db96d56Sopenharmony_ciat least one cased character in B, False otherwise."); 1827db96d56Sopenharmony_ci 1837db96d56Sopenharmony_ciPyObject* 1847db96d56Sopenharmony_ci_Py_bytes_islower(const char *cptr, Py_ssize_t len) 1857db96d56Sopenharmony_ci{ 1867db96d56Sopenharmony_ci const unsigned char *p 1877db96d56Sopenharmony_ci = (const unsigned char *) cptr; 1887db96d56Sopenharmony_ci const unsigned char *e; 1897db96d56Sopenharmony_ci int cased; 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci /* Shortcut for single character strings */ 1927db96d56Sopenharmony_ci if (len == 1) 1937db96d56Sopenharmony_ci return PyBool_FromLong(Py_ISLOWER(*p)); 1947db96d56Sopenharmony_ci 1957db96d56Sopenharmony_ci /* Special case for empty strings */ 1967db96d56Sopenharmony_ci if (len == 0) 1977db96d56Sopenharmony_ci Py_RETURN_FALSE; 1987db96d56Sopenharmony_ci 1997db96d56Sopenharmony_ci e = p + len; 2007db96d56Sopenharmony_ci cased = 0; 2017db96d56Sopenharmony_ci for (; p < e; p++) { 2027db96d56Sopenharmony_ci if (Py_ISUPPER(*p)) 2037db96d56Sopenharmony_ci Py_RETURN_FALSE; 2047db96d56Sopenharmony_ci else if (!cased && Py_ISLOWER(*p)) 2057db96d56Sopenharmony_ci cased = 1; 2067db96d56Sopenharmony_ci } 2077db96d56Sopenharmony_ci return PyBool_FromLong(cased); 2087db96d56Sopenharmony_ci} 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_isupper__doc__, 2127db96d56Sopenharmony_ci"B.isupper() -> bool\n\ 2137db96d56Sopenharmony_ci\n\ 2147db96d56Sopenharmony_ciReturn True if all cased characters in B are uppercase and there is\n\ 2157db96d56Sopenharmony_ciat least one cased character in B, False otherwise."); 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ciPyObject* 2187db96d56Sopenharmony_ci_Py_bytes_isupper(const char *cptr, Py_ssize_t len) 2197db96d56Sopenharmony_ci{ 2207db96d56Sopenharmony_ci const unsigned char *p 2217db96d56Sopenharmony_ci = (const unsigned char *) cptr; 2227db96d56Sopenharmony_ci const unsigned char *e; 2237db96d56Sopenharmony_ci int cased; 2247db96d56Sopenharmony_ci 2257db96d56Sopenharmony_ci /* Shortcut for single character strings */ 2267db96d56Sopenharmony_ci if (len == 1) 2277db96d56Sopenharmony_ci return PyBool_FromLong(Py_ISUPPER(*p)); 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci /* Special case for empty strings */ 2307db96d56Sopenharmony_ci if (len == 0) 2317db96d56Sopenharmony_ci Py_RETURN_FALSE; 2327db96d56Sopenharmony_ci 2337db96d56Sopenharmony_ci e = p + len; 2347db96d56Sopenharmony_ci cased = 0; 2357db96d56Sopenharmony_ci for (; p < e; p++) { 2367db96d56Sopenharmony_ci if (Py_ISLOWER(*p)) 2377db96d56Sopenharmony_ci Py_RETURN_FALSE; 2387db96d56Sopenharmony_ci else if (!cased && Py_ISUPPER(*p)) 2397db96d56Sopenharmony_ci cased = 1; 2407db96d56Sopenharmony_ci } 2417db96d56Sopenharmony_ci return PyBool_FromLong(cased); 2427db96d56Sopenharmony_ci} 2437db96d56Sopenharmony_ci 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_istitle__doc__, 2467db96d56Sopenharmony_ci"B.istitle() -> bool\n\ 2477db96d56Sopenharmony_ci\n\ 2487db96d56Sopenharmony_ciReturn True if B is a titlecased string and there is at least one\n\ 2497db96d56Sopenharmony_cicharacter in B, i.e. uppercase characters may only follow uncased\n\ 2507db96d56Sopenharmony_cicharacters and lowercase characters only cased ones. Return False\n\ 2517db96d56Sopenharmony_ciotherwise."); 2527db96d56Sopenharmony_ci 2537db96d56Sopenharmony_ciPyObject* 2547db96d56Sopenharmony_ci_Py_bytes_istitle(const char *cptr, Py_ssize_t len) 2557db96d56Sopenharmony_ci{ 2567db96d56Sopenharmony_ci const unsigned char *p 2577db96d56Sopenharmony_ci = (const unsigned char *) cptr; 2587db96d56Sopenharmony_ci const unsigned char *e; 2597db96d56Sopenharmony_ci int cased, previous_is_cased; 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ci /* Shortcut for single character strings */ 2627db96d56Sopenharmony_ci if (len == 1) 2637db96d56Sopenharmony_ci return PyBool_FromLong(Py_ISUPPER(*p)); 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci /* Special case for empty strings */ 2667db96d56Sopenharmony_ci if (len == 0) 2677db96d56Sopenharmony_ci Py_RETURN_FALSE; 2687db96d56Sopenharmony_ci 2697db96d56Sopenharmony_ci e = p + len; 2707db96d56Sopenharmony_ci cased = 0; 2717db96d56Sopenharmony_ci previous_is_cased = 0; 2727db96d56Sopenharmony_ci for (; p < e; p++) { 2737db96d56Sopenharmony_ci const unsigned char ch = *p; 2747db96d56Sopenharmony_ci 2757db96d56Sopenharmony_ci if (Py_ISUPPER(ch)) { 2767db96d56Sopenharmony_ci if (previous_is_cased) 2777db96d56Sopenharmony_ci Py_RETURN_FALSE; 2787db96d56Sopenharmony_ci previous_is_cased = 1; 2797db96d56Sopenharmony_ci cased = 1; 2807db96d56Sopenharmony_ci } 2817db96d56Sopenharmony_ci else if (Py_ISLOWER(ch)) { 2827db96d56Sopenharmony_ci if (!previous_is_cased) 2837db96d56Sopenharmony_ci Py_RETURN_FALSE; 2847db96d56Sopenharmony_ci previous_is_cased = 1; 2857db96d56Sopenharmony_ci cased = 1; 2867db96d56Sopenharmony_ci } 2877db96d56Sopenharmony_ci else 2887db96d56Sopenharmony_ci previous_is_cased = 0; 2897db96d56Sopenharmony_ci } 2907db96d56Sopenharmony_ci return PyBool_FromLong(cased); 2917db96d56Sopenharmony_ci} 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_lower__doc__, 2957db96d56Sopenharmony_ci"B.lower() -> copy of B\n\ 2967db96d56Sopenharmony_ci\n\ 2977db96d56Sopenharmony_ciReturn a copy of B with all ASCII characters converted to lowercase."); 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_civoid 3007db96d56Sopenharmony_ci_Py_bytes_lower(char *result, const char *cptr, Py_ssize_t len) 3017db96d56Sopenharmony_ci{ 3027db96d56Sopenharmony_ci Py_ssize_t i; 3037db96d56Sopenharmony_ci 3047db96d56Sopenharmony_ci for (i = 0; i < len; i++) { 3057db96d56Sopenharmony_ci result[i] = Py_TOLOWER((unsigned char) cptr[i]); 3067db96d56Sopenharmony_ci } 3077db96d56Sopenharmony_ci} 3087db96d56Sopenharmony_ci 3097db96d56Sopenharmony_ci 3107db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_upper__doc__, 3117db96d56Sopenharmony_ci"B.upper() -> copy of B\n\ 3127db96d56Sopenharmony_ci\n\ 3137db96d56Sopenharmony_ciReturn a copy of B with all ASCII characters converted to uppercase."); 3147db96d56Sopenharmony_ci 3157db96d56Sopenharmony_civoid 3167db96d56Sopenharmony_ci_Py_bytes_upper(char *result, const char *cptr, Py_ssize_t len) 3177db96d56Sopenharmony_ci{ 3187db96d56Sopenharmony_ci Py_ssize_t i; 3197db96d56Sopenharmony_ci 3207db96d56Sopenharmony_ci for (i = 0; i < len; i++) { 3217db96d56Sopenharmony_ci result[i] = Py_TOUPPER((unsigned char) cptr[i]); 3227db96d56Sopenharmony_ci } 3237db96d56Sopenharmony_ci} 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_ci 3267db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_title__doc__, 3277db96d56Sopenharmony_ci"B.title() -> copy of B\n\ 3287db96d56Sopenharmony_ci\n\ 3297db96d56Sopenharmony_ciReturn a titlecased version of B, i.e. ASCII words start with uppercase\n\ 3307db96d56Sopenharmony_cicharacters, all remaining cased characters have lowercase."); 3317db96d56Sopenharmony_ci 3327db96d56Sopenharmony_civoid 3337db96d56Sopenharmony_ci_Py_bytes_title(char *result, const char *s, Py_ssize_t len) 3347db96d56Sopenharmony_ci{ 3357db96d56Sopenharmony_ci Py_ssize_t i; 3367db96d56Sopenharmony_ci int previous_is_cased = 0; 3377db96d56Sopenharmony_ci 3387db96d56Sopenharmony_ci for (i = 0; i < len; i++) { 3397db96d56Sopenharmony_ci int c = Py_CHARMASK(*s++); 3407db96d56Sopenharmony_ci if (Py_ISLOWER(c)) { 3417db96d56Sopenharmony_ci if (!previous_is_cased) 3427db96d56Sopenharmony_ci c = Py_TOUPPER(c); 3437db96d56Sopenharmony_ci previous_is_cased = 1; 3447db96d56Sopenharmony_ci } else if (Py_ISUPPER(c)) { 3457db96d56Sopenharmony_ci if (previous_is_cased) 3467db96d56Sopenharmony_ci c = Py_TOLOWER(c); 3477db96d56Sopenharmony_ci previous_is_cased = 1; 3487db96d56Sopenharmony_ci } else 3497db96d56Sopenharmony_ci previous_is_cased = 0; 3507db96d56Sopenharmony_ci *result++ = c; 3517db96d56Sopenharmony_ci } 3527db96d56Sopenharmony_ci} 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_capitalize__doc__, 3567db96d56Sopenharmony_ci"B.capitalize() -> copy of B\n\ 3577db96d56Sopenharmony_ci\n\ 3587db96d56Sopenharmony_ciReturn a copy of B with only its first character capitalized (ASCII)\n\ 3597db96d56Sopenharmony_ciand the rest lower-cased."); 3607db96d56Sopenharmony_ci 3617db96d56Sopenharmony_civoid 3627db96d56Sopenharmony_ci_Py_bytes_capitalize(char *result, const char *s, Py_ssize_t len) 3637db96d56Sopenharmony_ci{ 3647db96d56Sopenharmony_ci if (len > 0) { 3657db96d56Sopenharmony_ci *result = Py_TOUPPER(*s); 3667db96d56Sopenharmony_ci _Py_bytes_lower(result + 1, s + 1, len - 1); 3677db96d56Sopenharmony_ci } 3687db96d56Sopenharmony_ci} 3697db96d56Sopenharmony_ci 3707db96d56Sopenharmony_ci 3717db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_swapcase__doc__, 3727db96d56Sopenharmony_ci"B.swapcase() -> copy of B\n\ 3737db96d56Sopenharmony_ci\n\ 3747db96d56Sopenharmony_ciReturn a copy of B with uppercase ASCII characters converted\n\ 3757db96d56Sopenharmony_cito lowercase ASCII and vice versa."); 3767db96d56Sopenharmony_ci 3777db96d56Sopenharmony_civoid 3787db96d56Sopenharmony_ci_Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len) 3797db96d56Sopenharmony_ci{ 3807db96d56Sopenharmony_ci Py_ssize_t i; 3817db96d56Sopenharmony_ci 3827db96d56Sopenharmony_ci for (i = 0; i < len; i++) { 3837db96d56Sopenharmony_ci int c = Py_CHARMASK(*s++); 3847db96d56Sopenharmony_ci if (Py_ISLOWER(c)) { 3857db96d56Sopenharmony_ci *result = Py_TOUPPER(c); 3867db96d56Sopenharmony_ci } 3877db96d56Sopenharmony_ci else if (Py_ISUPPER(c)) { 3887db96d56Sopenharmony_ci *result = Py_TOLOWER(c); 3897db96d56Sopenharmony_ci } 3907db96d56Sopenharmony_ci else 3917db96d56Sopenharmony_ci *result = c; 3927db96d56Sopenharmony_ci result++; 3937db96d56Sopenharmony_ci } 3947db96d56Sopenharmony_ci} 3957db96d56Sopenharmony_ci 3967db96d56Sopenharmony_ci 3977db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_maketrans__doc__, 3987db96d56Sopenharmony_ci"B.maketrans(frm, to) -> translation table\n\ 3997db96d56Sopenharmony_ci\n\ 4007db96d56Sopenharmony_ciReturn a translation table (a bytes object of length 256) suitable\n\ 4017db96d56Sopenharmony_cifor use in the bytes or bytearray translate method where each byte\n\ 4027db96d56Sopenharmony_ciin frm is mapped to the byte at the same position in to.\n\ 4037db96d56Sopenharmony_ciThe bytes objects frm and to must be of the same length."); 4047db96d56Sopenharmony_ci 4057db96d56Sopenharmony_ciPyObject * 4067db96d56Sopenharmony_ci_Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to) 4077db96d56Sopenharmony_ci{ 4087db96d56Sopenharmony_ci PyObject *res = NULL; 4097db96d56Sopenharmony_ci Py_ssize_t i; 4107db96d56Sopenharmony_ci char *p; 4117db96d56Sopenharmony_ci 4127db96d56Sopenharmony_ci if (frm->len != to->len) { 4137db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 4147db96d56Sopenharmony_ci "maketrans arguments must have same length"); 4157db96d56Sopenharmony_ci return NULL; 4167db96d56Sopenharmony_ci } 4177db96d56Sopenharmony_ci res = PyBytes_FromStringAndSize(NULL, 256); 4187db96d56Sopenharmony_ci if (!res) 4197db96d56Sopenharmony_ci return NULL; 4207db96d56Sopenharmony_ci p = PyBytes_AS_STRING(res); 4217db96d56Sopenharmony_ci for (i = 0; i < 256; i++) 4227db96d56Sopenharmony_ci p[i] = (char) i; 4237db96d56Sopenharmony_ci for (i = 0; i < frm->len; i++) { 4247db96d56Sopenharmony_ci p[((unsigned char *)frm->buf)[i]] = ((char *)to->buf)[i]; 4257db96d56Sopenharmony_ci } 4267db96d56Sopenharmony_ci 4277db96d56Sopenharmony_ci return res; 4287db96d56Sopenharmony_ci} 4297db96d56Sopenharmony_ci 4307db96d56Sopenharmony_ci#define FASTSEARCH fastsearch 4317db96d56Sopenharmony_ci#define STRINGLIB(F) stringlib_##F 4327db96d56Sopenharmony_ci#define STRINGLIB_CHAR char 4337db96d56Sopenharmony_ci#define STRINGLIB_SIZEOF_CHAR 1 4347db96d56Sopenharmony_ci 4357db96d56Sopenharmony_ci#include "stringlib/fastsearch.h" 4367db96d56Sopenharmony_ci#include "stringlib/count.h" 4377db96d56Sopenharmony_ci#include "stringlib/find.h" 4387db96d56Sopenharmony_ci 4397db96d56Sopenharmony_ci/* 4407db96d56Sopenharmony_ciWraps stringlib_parse_args_finds() and additionally checks the first 4417db96d56Sopenharmony_ciargument type. 4427db96d56Sopenharmony_ci 4437db96d56Sopenharmony_ciIn case the first argument is a bytes-like object, sets it to subobj, 4447db96d56Sopenharmony_ciand doesn't touch the byte parameter. 4457db96d56Sopenharmony_ciIn case it is an integer in range(0, 256), writes the integer value 4467db96d56Sopenharmony_cito byte, and sets subobj to NULL. 4477db96d56Sopenharmony_ci 4487db96d56Sopenharmony_ciThe other parameters are similar to those of 4497db96d56Sopenharmony_cistringlib_parse_args_finds(). 4507db96d56Sopenharmony_ci*/ 4517db96d56Sopenharmony_ci 4527db96d56Sopenharmony_ciPy_LOCAL_INLINE(int) 4537db96d56Sopenharmony_ciparse_args_finds_byte(const char *function_name, PyObject *args, 4547db96d56Sopenharmony_ci PyObject **subobj, char *byte, 4557db96d56Sopenharmony_ci Py_ssize_t *start, Py_ssize_t *end) 4567db96d56Sopenharmony_ci{ 4577db96d56Sopenharmony_ci PyObject *tmp_subobj; 4587db96d56Sopenharmony_ci Py_ssize_t ival; 4597db96d56Sopenharmony_ci 4607db96d56Sopenharmony_ci if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj, 4617db96d56Sopenharmony_ci start, end)) 4627db96d56Sopenharmony_ci return 0; 4637db96d56Sopenharmony_ci 4647db96d56Sopenharmony_ci if (PyObject_CheckBuffer(tmp_subobj)) { 4657db96d56Sopenharmony_ci *subobj = tmp_subobj; 4667db96d56Sopenharmony_ci return 1; 4677db96d56Sopenharmony_ci } 4687db96d56Sopenharmony_ci 4697db96d56Sopenharmony_ci if (!_PyIndex_Check(tmp_subobj)) { 4707db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 4717db96d56Sopenharmony_ci "argument should be integer or bytes-like object, " 4727db96d56Sopenharmony_ci "not '%.200s'", 4737db96d56Sopenharmony_ci Py_TYPE(tmp_subobj)->tp_name); 4747db96d56Sopenharmony_ci return 0; 4757db96d56Sopenharmony_ci } 4767db96d56Sopenharmony_ci 4777db96d56Sopenharmony_ci ival = PyNumber_AsSsize_t(tmp_subobj, NULL); 4787db96d56Sopenharmony_ci if (ival == -1 && PyErr_Occurred()) { 4797db96d56Sopenharmony_ci return 0; 4807db96d56Sopenharmony_ci } 4817db96d56Sopenharmony_ci if (ival < 0 || ival > 255) { 4827db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); 4837db96d56Sopenharmony_ci return 0; 4847db96d56Sopenharmony_ci } 4857db96d56Sopenharmony_ci 4867db96d56Sopenharmony_ci *subobj = NULL; 4877db96d56Sopenharmony_ci *byte = (char)ival; 4887db96d56Sopenharmony_ci return 1; 4897db96d56Sopenharmony_ci} 4907db96d56Sopenharmony_ci 4917db96d56Sopenharmony_ci/* helper macro to fixup start/end slice values */ 4927db96d56Sopenharmony_ci#define ADJUST_INDICES(start, end, len) \ 4937db96d56Sopenharmony_ci if (end > len) \ 4947db96d56Sopenharmony_ci end = len; \ 4957db96d56Sopenharmony_ci else if (end < 0) { \ 4967db96d56Sopenharmony_ci end += len; \ 4977db96d56Sopenharmony_ci if (end < 0) \ 4987db96d56Sopenharmony_ci end = 0; \ 4997db96d56Sopenharmony_ci } \ 5007db96d56Sopenharmony_ci if (start < 0) { \ 5017db96d56Sopenharmony_ci start += len; \ 5027db96d56Sopenharmony_ci if (start < 0) \ 5037db96d56Sopenharmony_ci start = 0; \ 5047db96d56Sopenharmony_ci } 5057db96d56Sopenharmony_ci 5067db96d56Sopenharmony_ciPy_LOCAL_INLINE(Py_ssize_t) 5077db96d56Sopenharmony_cifind_internal(const char *str, Py_ssize_t len, 5087db96d56Sopenharmony_ci const char *function_name, PyObject *args, int dir) 5097db96d56Sopenharmony_ci{ 5107db96d56Sopenharmony_ci PyObject *subobj; 5117db96d56Sopenharmony_ci char byte; 5127db96d56Sopenharmony_ci Py_buffer subbuf; 5137db96d56Sopenharmony_ci const char *sub; 5147db96d56Sopenharmony_ci Py_ssize_t sub_len; 5157db96d56Sopenharmony_ci Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; 5167db96d56Sopenharmony_ci Py_ssize_t res; 5177db96d56Sopenharmony_ci 5187db96d56Sopenharmony_ci if (!parse_args_finds_byte(function_name, args, 5197db96d56Sopenharmony_ci &subobj, &byte, &start, &end)) 5207db96d56Sopenharmony_ci return -2; 5217db96d56Sopenharmony_ci 5227db96d56Sopenharmony_ci if (subobj) { 5237db96d56Sopenharmony_ci if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0) 5247db96d56Sopenharmony_ci return -2; 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_ci sub = subbuf.buf; 5277db96d56Sopenharmony_ci sub_len = subbuf.len; 5287db96d56Sopenharmony_ci } 5297db96d56Sopenharmony_ci else { 5307db96d56Sopenharmony_ci sub = &byte; 5317db96d56Sopenharmony_ci sub_len = 1; 5327db96d56Sopenharmony_ci } 5337db96d56Sopenharmony_ci 5347db96d56Sopenharmony_ci ADJUST_INDICES(start, end, len); 5357db96d56Sopenharmony_ci if (end - start < sub_len) 5367db96d56Sopenharmony_ci res = -1; 5377db96d56Sopenharmony_ci else if (sub_len == 1) { 5387db96d56Sopenharmony_ci if (dir > 0) 5397db96d56Sopenharmony_ci res = stringlib_find_char( 5407db96d56Sopenharmony_ci str + start, end - start, 5417db96d56Sopenharmony_ci *sub); 5427db96d56Sopenharmony_ci else 5437db96d56Sopenharmony_ci res = stringlib_rfind_char( 5447db96d56Sopenharmony_ci str + start, end - start, 5457db96d56Sopenharmony_ci *sub); 5467db96d56Sopenharmony_ci if (res >= 0) 5477db96d56Sopenharmony_ci res += start; 5487db96d56Sopenharmony_ci } 5497db96d56Sopenharmony_ci else { 5507db96d56Sopenharmony_ci if (dir > 0) 5517db96d56Sopenharmony_ci res = stringlib_find_slice( 5527db96d56Sopenharmony_ci str, len, 5537db96d56Sopenharmony_ci sub, sub_len, start, end); 5547db96d56Sopenharmony_ci else 5557db96d56Sopenharmony_ci res = stringlib_rfind_slice( 5567db96d56Sopenharmony_ci str, len, 5577db96d56Sopenharmony_ci sub, sub_len, start, end); 5587db96d56Sopenharmony_ci } 5597db96d56Sopenharmony_ci 5607db96d56Sopenharmony_ci if (subobj) 5617db96d56Sopenharmony_ci PyBuffer_Release(&subbuf); 5627db96d56Sopenharmony_ci 5637db96d56Sopenharmony_ci return res; 5647db96d56Sopenharmony_ci} 5657db96d56Sopenharmony_ci 5667db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_find__doc__, 5677db96d56Sopenharmony_ci"B.find(sub[, start[, end]]) -> int\n\ 5687db96d56Sopenharmony_ci\n\ 5697db96d56Sopenharmony_ciReturn the lowest index in B where subsection sub is found,\n\ 5707db96d56Sopenharmony_cisuch that sub is contained within B[start,end]. Optional\n\ 5717db96d56Sopenharmony_ciarguments start and end are interpreted as in slice notation.\n\ 5727db96d56Sopenharmony_ci\n\ 5737db96d56Sopenharmony_ciReturn -1 on failure."); 5747db96d56Sopenharmony_ci 5757db96d56Sopenharmony_ciPyObject * 5767db96d56Sopenharmony_ci_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args) 5777db96d56Sopenharmony_ci{ 5787db96d56Sopenharmony_ci Py_ssize_t result = find_internal(str, len, "find", args, +1); 5797db96d56Sopenharmony_ci if (result == -2) 5807db96d56Sopenharmony_ci return NULL; 5817db96d56Sopenharmony_ci return PyLong_FromSsize_t(result); 5827db96d56Sopenharmony_ci} 5837db96d56Sopenharmony_ci 5847db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_index__doc__, 5857db96d56Sopenharmony_ci"B.index(sub[, start[, end]]) -> int\n\ 5867db96d56Sopenharmony_ci\n\ 5877db96d56Sopenharmony_ciReturn the lowest index in B where subsection sub is found,\n\ 5887db96d56Sopenharmony_cisuch that sub is contained within B[start,end]. Optional\n\ 5897db96d56Sopenharmony_ciarguments start and end are interpreted as in slice notation.\n\ 5907db96d56Sopenharmony_ci\n\ 5917db96d56Sopenharmony_ciRaises ValueError when the subsection is not found."); 5927db96d56Sopenharmony_ci 5937db96d56Sopenharmony_ciPyObject * 5947db96d56Sopenharmony_ci_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args) 5957db96d56Sopenharmony_ci{ 5967db96d56Sopenharmony_ci Py_ssize_t result = find_internal(str, len, "index", args, +1); 5977db96d56Sopenharmony_ci if (result == -2) 5987db96d56Sopenharmony_ci return NULL; 5997db96d56Sopenharmony_ci if (result == -1) { 6007db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 6017db96d56Sopenharmony_ci "subsection not found"); 6027db96d56Sopenharmony_ci return NULL; 6037db96d56Sopenharmony_ci } 6047db96d56Sopenharmony_ci return PyLong_FromSsize_t(result); 6057db96d56Sopenharmony_ci} 6067db96d56Sopenharmony_ci 6077db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_rfind__doc__, 6087db96d56Sopenharmony_ci"B.rfind(sub[, start[, end]]) -> int\n\ 6097db96d56Sopenharmony_ci\n\ 6107db96d56Sopenharmony_ciReturn the highest index in B where subsection sub is found,\n\ 6117db96d56Sopenharmony_cisuch that sub is contained within B[start,end]. Optional\n\ 6127db96d56Sopenharmony_ciarguments start and end are interpreted as in slice notation.\n\ 6137db96d56Sopenharmony_ci\n\ 6147db96d56Sopenharmony_ciReturn -1 on failure."); 6157db96d56Sopenharmony_ci 6167db96d56Sopenharmony_ciPyObject * 6177db96d56Sopenharmony_ci_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args) 6187db96d56Sopenharmony_ci{ 6197db96d56Sopenharmony_ci Py_ssize_t result = find_internal(str, len, "rfind", args, -1); 6207db96d56Sopenharmony_ci if (result == -2) 6217db96d56Sopenharmony_ci return NULL; 6227db96d56Sopenharmony_ci return PyLong_FromSsize_t(result); 6237db96d56Sopenharmony_ci} 6247db96d56Sopenharmony_ci 6257db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_rindex__doc__, 6267db96d56Sopenharmony_ci"B.rindex(sub[, start[, end]]) -> int\n\ 6277db96d56Sopenharmony_ci\n\ 6287db96d56Sopenharmony_ciReturn the highest index in B where subsection sub is found,\n\ 6297db96d56Sopenharmony_cisuch that sub is contained within B[start,end]. Optional\n\ 6307db96d56Sopenharmony_ciarguments start and end are interpreted as in slice notation.\n\ 6317db96d56Sopenharmony_ci\n\ 6327db96d56Sopenharmony_ciRaise ValueError when the subsection is not found."); 6337db96d56Sopenharmony_ci 6347db96d56Sopenharmony_ciPyObject * 6357db96d56Sopenharmony_ci_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args) 6367db96d56Sopenharmony_ci{ 6377db96d56Sopenharmony_ci Py_ssize_t result = find_internal(str, len, "rindex", args, -1); 6387db96d56Sopenharmony_ci if (result == -2) 6397db96d56Sopenharmony_ci return NULL; 6407db96d56Sopenharmony_ci if (result == -1) { 6417db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 6427db96d56Sopenharmony_ci "subsection not found"); 6437db96d56Sopenharmony_ci return NULL; 6447db96d56Sopenharmony_ci } 6457db96d56Sopenharmony_ci return PyLong_FromSsize_t(result); 6467db96d56Sopenharmony_ci} 6477db96d56Sopenharmony_ci 6487db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_count__doc__, 6497db96d56Sopenharmony_ci"B.count(sub[, start[, end]]) -> int\n\ 6507db96d56Sopenharmony_ci\n\ 6517db96d56Sopenharmony_ciReturn the number of non-overlapping occurrences of subsection sub in\n\ 6527db96d56Sopenharmony_cibytes B[start:end]. Optional arguments start and end are interpreted\n\ 6537db96d56Sopenharmony_cias in slice notation."); 6547db96d56Sopenharmony_ci 6557db96d56Sopenharmony_ciPyObject * 6567db96d56Sopenharmony_ci_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args) 6577db96d56Sopenharmony_ci{ 6587db96d56Sopenharmony_ci PyObject *sub_obj; 6597db96d56Sopenharmony_ci const char *sub; 6607db96d56Sopenharmony_ci Py_ssize_t sub_len; 6617db96d56Sopenharmony_ci char byte; 6627db96d56Sopenharmony_ci Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; 6637db96d56Sopenharmony_ci 6647db96d56Sopenharmony_ci Py_buffer vsub; 6657db96d56Sopenharmony_ci PyObject *count_obj; 6667db96d56Sopenharmony_ci 6677db96d56Sopenharmony_ci if (!parse_args_finds_byte("count", args, 6687db96d56Sopenharmony_ci &sub_obj, &byte, &start, &end)) 6697db96d56Sopenharmony_ci return NULL; 6707db96d56Sopenharmony_ci 6717db96d56Sopenharmony_ci if (sub_obj) { 6727db96d56Sopenharmony_ci if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0) 6737db96d56Sopenharmony_ci return NULL; 6747db96d56Sopenharmony_ci 6757db96d56Sopenharmony_ci sub = vsub.buf; 6767db96d56Sopenharmony_ci sub_len = vsub.len; 6777db96d56Sopenharmony_ci } 6787db96d56Sopenharmony_ci else { 6797db96d56Sopenharmony_ci sub = &byte; 6807db96d56Sopenharmony_ci sub_len = 1; 6817db96d56Sopenharmony_ci } 6827db96d56Sopenharmony_ci 6837db96d56Sopenharmony_ci ADJUST_INDICES(start, end, len); 6847db96d56Sopenharmony_ci 6857db96d56Sopenharmony_ci count_obj = PyLong_FromSsize_t( 6867db96d56Sopenharmony_ci stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX) 6877db96d56Sopenharmony_ci ); 6887db96d56Sopenharmony_ci 6897db96d56Sopenharmony_ci if (sub_obj) 6907db96d56Sopenharmony_ci PyBuffer_Release(&vsub); 6917db96d56Sopenharmony_ci 6927db96d56Sopenharmony_ci return count_obj; 6937db96d56Sopenharmony_ci} 6947db96d56Sopenharmony_ci 6957db96d56Sopenharmony_ciint 6967db96d56Sopenharmony_ci_Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg) 6977db96d56Sopenharmony_ci{ 6987db96d56Sopenharmony_ci Py_ssize_t ival = PyNumber_AsSsize_t(arg, NULL); 6997db96d56Sopenharmony_ci if (ival == -1 && PyErr_Occurred()) { 7007db96d56Sopenharmony_ci Py_buffer varg; 7017db96d56Sopenharmony_ci Py_ssize_t pos; 7027db96d56Sopenharmony_ci PyErr_Clear(); 7037db96d56Sopenharmony_ci if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) 7047db96d56Sopenharmony_ci return -1; 7057db96d56Sopenharmony_ci pos = stringlib_find(str, len, 7067db96d56Sopenharmony_ci varg.buf, varg.len, 0); 7077db96d56Sopenharmony_ci PyBuffer_Release(&varg); 7087db96d56Sopenharmony_ci return pos >= 0; 7097db96d56Sopenharmony_ci } 7107db96d56Sopenharmony_ci if (ival < 0 || ival >= 256) { 7117db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); 7127db96d56Sopenharmony_ci return -1; 7137db96d56Sopenharmony_ci } 7147db96d56Sopenharmony_ci 7157db96d56Sopenharmony_ci return memchr(str, (int) ival, len) != NULL; 7167db96d56Sopenharmony_ci} 7177db96d56Sopenharmony_ci 7187db96d56Sopenharmony_ci 7197db96d56Sopenharmony_ci/* Matches the end (direction >= 0) or start (direction < 0) of the buffer 7207db96d56Sopenharmony_ci * against substr, using the start and end arguments. Returns 7217db96d56Sopenharmony_ci * -1 on error, 0 if not found and 1 if found. 7227db96d56Sopenharmony_ci */ 7237db96d56Sopenharmony_cistatic int 7247db96d56Sopenharmony_citailmatch(const char *str, Py_ssize_t len, PyObject *substr, 7257db96d56Sopenharmony_ci Py_ssize_t start, Py_ssize_t end, int direction) 7267db96d56Sopenharmony_ci{ 7277db96d56Sopenharmony_ci Py_buffer sub_view = {NULL, NULL}; 7287db96d56Sopenharmony_ci const char *sub; 7297db96d56Sopenharmony_ci Py_ssize_t slen; 7307db96d56Sopenharmony_ci 7317db96d56Sopenharmony_ci if (PyBytes_Check(substr)) { 7327db96d56Sopenharmony_ci sub = PyBytes_AS_STRING(substr); 7337db96d56Sopenharmony_ci slen = PyBytes_GET_SIZE(substr); 7347db96d56Sopenharmony_ci } 7357db96d56Sopenharmony_ci else { 7367db96d56Sopenharmony_ci if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0) 7377db96d56Sopenharmony_ci return -1; 7387db96d56Sopenharmony_ci sub = sub_view.buf; 7397db96d56Sopenharmony_ci slen = sub_view.len; 7407db96d56Sopenharmony_ci } 7417db96d56Sopenharmony_ci 7427db96d56Sopenharmony_ci ADJUST_INDICES(start, end, len); 7437db96d56Sopenharmony_ci 7447db96d56Sopenharmony_ci if (direction < 0) { 7457db96d56Sopenharmony_ci /* startswith */ 7467db96d56Sopenharmony_ci if (start > len - slen) 7477db96d56Sopenharmony_ci goto notfound; 7487db96d56Sopenharmony_ci } else { 7497db96d56Sopenharmony_ci /* endswith */ 7507db96d56Sopenharmony_ci if (end - start < slen || start > len) 7517db96d56Sopenharmony_ci goto notfound; 7527db96d56Sopenharmony_ci 7537db96d56Sopenharmony_ci if (end - slen > start) 7547db96d56Sopenharmony_ci start = end - slen; 7557db96d56Sopenharmony_ci } 7567db96d56Sopenharmony_ci if (end - start < slen) 7577db96d56Sopenharmony_ci goto notfound; 7587db96d56Sopenharmony_ci if (memcmp(str + start, sub, slen) != 0) 7597db96d56Sopenharmony_ci goto notfound; 7607db96d56Sopenharmony_ci 7617db96d56Sopenharmony_ci PyBuffer_Release(&sub_view); 7627db96d56Sopenharmony_ci return 1; 7637db96d56Sopenharmony_ci 7647db96d56Sopenharmony_cinotfound: 7657db96d56Sopenharmony_ci PyBuffer_Release(&sub_view); 7667db96d56Sopenharmony_ci return 0; 7677db96d56Sopenharmony_ci} 7687db96d56Sopenharmony_ci 7697db96d56Sopenharmony_cistatic PyObject * 7707db96d56Sopenharmony_ci_Py_bytes_tailmatch(const char *str, Py_ssize_t len, 7717db96d56Sopenharmony_ci const char *function_name, PyObject *args, 7727db96d56Sopenharmony_ci int direction) 7737db96d56Sopenharmony_ci{ 7747db96d56Sopenharmony_ci Py_ssize_t start = 0; 7757db96d56Sopenharmony_ci Py_ssize_t end = PY_SSIZE_T_MAX; 7767db96d56Sopenharmony_ci PyObject *subobj; 7777db96d56Sopenharmony_ci int result; 7787db96d56Sopenharmony_ci 7797db96d56Sopenharmony_ci if (!stringlib_parse_args_finds(function_name, args, &subobj, &start, &end)) 7807db96d56Sopenharmony_ci return NULL; 7817db96d56Sopenharmony_ci if (PyTuple_Check(subobj)) { 7827db96d56Sopenharmony_ci Py_ssize_t i; 7837db96d56Sopenharmony_ci for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { 7847db96d56Sopenharmony_ci result = tailmatch(str, len, PyTuple_GET_ITEM(subobj, i), 7857db96d56Sopenharmony_ci start, end, direction); 7867db96d56Sopenharmony_ci if (result == -1) 7877db96d56Sopenharmony_ci return NULL; 7887db96d56Sopenharmony_ci else if (result) { 7897db96d56Sopenharmony_ci Py_RETURN_TRUE; 7907db96d56Sopenharmony_ci } 7917db96d56Sopenharmony_ci } 7927db96d56Sopenharmony_ci Py_RETURN_FALSE; 7937db96d56Sopenharmony_ci } 7947db96d56Sopenharmony_ci result = tailmatch(str, len, subobj, start, end, direction); 7957db96d56Sopenharmony_ci if (result == -1) { 7967db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_TypeError)) 7977db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 7987db96d56Sopenharmony_ci "%s first arg must be bytes or a tuple of bytes, " 7997db96d56Sopenharmony_ci "not %s", 8007db96d56Sopenharmony_ci function_name, Py_TYPE(subobj)->tp_name); 8017db96d56Sopenharmony_ci return NULL; 8027db96d56Sopenharmony_ci } 8037db96d56Sopenharmony_ci else 8047db96d56Sopenharmony_ci return PyBool_FromLong(result); 8057db96d56Sopenharmony_ci} 8067db96d56Sopenharmony_ci 8077db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_startswith__doc__, 8087db96d56Sopenharmony_ci"B.startswith(prefix[, start[, end]]) -> bool\n\ 8097db96d56Sopenharmony_ci\n\ 8107db96d56Sopenharmony_ciReturn True if B starts with the specified prefix, False otherwise.\n\ 8117db96d56Sopenharmony_ciWith optional start, test B beginning at that position.\n\ 8127db96d56Sopenharmony_ciWith optional end, stop comparing B at that position.\n\ 8137db96d56Sopenharmony_ciprefix can also be a tuple of bytes to try."); 8147db96d56Sopenharmony_ci 8157db96d56Sopenharmony_ciPyObject * 8167db96d56Sopenharmony_ci_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) 8177db96d56Sopenharmony_ci{ 8187db96d56Sopenharmony_ci return _Py_bytes_tailmatch(str, len, "startswith", args, -1); 8197db96d56Sopenharmony_ci} 8207db96d56Sopenharmony_ci 8217db96d56Sopenharmony_ciPyDoc_STRVAR_shared(_Py_endswith__doc__, 8227db96d56Sopenharmony_ci"B.endswith(suffix[, start[, end]]) -> bool\n\ 8237db96d56Sopenharmony_ci\n\ 8247db96d56Sopenharmony_ciReturn True if B ends with the specified suffix, False otherwise.\n\ 8257db96d56Sopenharmony_ciWith optional start, test B beginning at that position.\n\ 8267db96d56Sopenharmony_ciWith optional end, stop comparing B at that position.\n\ 8277db96d56Sopenharmony_cisuffix can also be a tuple of bytes to try."); 8287db96d56Sopenharmony_ci 8297db96d56Sopenharmony_ciPyObject * 8307db96d56Sopenharmony_ci_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args) 8317db96d56Sopenharmony_ci{ 8327db96d56Sopenharmony_ci return _Py_bytes_tailmatch(str, len, "endswith", args, +1); 8337db96d56Sopenharmony_ci} 834