| 5085 | " Str: A new string with trailing characters removed."; |
| 5086 | |
| 5087 | static PyObject *Str_like_rstrip(PyObject *self, PyObject *const *args, Py_ssize_t positional_args_count, |
| 5088 | PyObject *args_names_tuple) { |
| 5089 | // Check arguments |
| 5090 | int is_member = self != NULL && PyObject_TypeCheck(self, &StrType); |
| 5091 | Py_ssize_t expected_min_args = !is_member; |
| 5092 | Py_ssize_t expected_max_args = !is_member + 1; |
| 5093 | if (positional_args_count < expected_min_args || positional_args_count > expected_max_args) { |
| 5094 | PyErr_SetString(PyExc_TypeError, "rstrip() takes at most 1 argument"); |
| 5095 | return NULL; |
| 5096 | } |
| 5097 | |
| 5098 | PyObject *text_obj = is_member ? self : args[0]; |
| 5099 | PyObject *chars_obj = positional_args_count > !is_member ? args[!is_member] : NULL; |
| 5100 | |
| 5101 | if (args_names_tuple) { |
| 5102 | Py_ssize_t args_names_count = PyTuple_GET_SIZE(args_names_tuple); |
| 5103 | for (Py_ssize_t i = 0; i < args_names_count; ++i) { |
| 5104 | PyObject *key = PyTuple_GET_ITEM(args_names_tuple, i); |
| 5105 | PyObject *value = args[positional_args_count + i]; |
| 5106 | if (PyUnicode_CompareWithASCIIString(key, "chars") == 0 && !chars_obj) { chars_obj = value; } |
| 5107 | else if (PyErr_Format(PyExc_TypeError, "Got an unexpected keyword argument '%U'", key)) |
| 5108 | return NULL; |
| 5109 | } |
| 5110 | } |
| 5111 | |
| 5112 | sz_string_view_t text; |
| 5113 | sz_string_view_t chars; |
| 5114 | |
| 5115 | // Validate and convert text |
| 5116 | if (!sz_py_export_string_like(text_obj, &text.start, &text.length)) { |
| 5117 | wrap_current_exception("The text argument must be string-like"); |
| 5118 | return NULL; |
| 5119 | } |
| 5120 | |
| 5121 | // Default to whitespace if chars is not provided |
| 5122 | char const *default_chars = " \t\n\r\f\v"; |
| 5123 | if (chars_obj) { |
| 5124 | if (!sz_py_export_string_like(chars_obj, &chars.start, &chars.length)) { |
| 5125 | wrap_current_exception("The chars argument must be string-like"); |
| 5126 | return NULL; |
| 5127 | } |
| 5128 | } |
| 5129 | else { |
| 5130 | chars.start = default_chars; |
| 5131 | chars.length = 6; |
| 5132 | } |
| 5133 | |
| 5134 | // Create byteset from chars |
| 5135 | sz_byteset_t set; |
| 5136 | sz_byteset_init(&set); |
| 5137 | for (sz_size_t i = 0; i < chars.length; ++i) sz_byteset_add(&set, chars.start[i]); |
| 5138 | sz_byteset_invert(&set); |
| 5139 | |
| 5140 | // Find last character NOT in the set (i.e., not to be stripped) |
| 5141 | sz_cptr_t new_end = sz_rfind_byteset(text.start, text.length, &set); |
| 5142 | if (!new_end) { |
| 5143 | // Return empty string |
| 5144 | Str *result = (Str *)StrType.tp_alloc(&StrType, 0); |
nothing calls this directly
no test coverage detected
searching dependent graphs…