Add an ICU based implementation of swapcase()

This commit is contained in:
Kovid Goyal 2014-08-06 21:16:16 +05:30
parent 0c8044e7b6
commit ebfdca8c18
3 changed files with 44 additions and 0 deletions

View File

@ -804,6 +804,40 @@ end:
} // }}} } // }}}
// swap_case {{{
static PyObject* icu_swap_case(PyObject *self, PyObject *args) {
PyObject *input = NULL, *result = NULL;
UErrorCode status = U_ZERO_ERROR;
UChar *input_buf = NULL, *output_buf = NULL;
UChar32 *buf = NULL;
int32_t sz = 0, sz32 = 0, i = 0;
if (!PyArg_ParseTuple(args, "O", &input)) return NULL;
input_buf = python_to_icu(input, &sz, 1);
if (input_buf == NULL) goto end;
output_buf = (UChar*) calloc(3 * sz, sizeof(UChar));
buf = (UChar32*) calloc(2 * sz, sizeof(UChar32));
if (output_buf == NULL || buf == NULL) { PyErr_NoMemory(); goto end; }
u_strToUTF32(buf, 2 * sz, &sz32, input_buf, sz, &status);
for (i = 0; i < sz32; i++) {
if (u_islower(buf[i])) buf[i] = u_toupper(buf[i]);
else if (u_isupper(buf[i])) buf[i] = u_tolower(buf[i]);
}
u_strFromUTF32(output_buf, 3*sz, &sz, buf, sz32, &status);
if (U_FAILURE(status)) { PyErr_SetString(PyExc_ValueError, u_errorName(status)); goto end; }
result = icu_to_python(output_buf, sz);
end:
if (input_buf != NULL) free(input_buf);
if (output_buf != NULL) free(output_buf);
if (buf != NULL) free(buf);
return result;
} // }}}
// set_default_encoding {{{ // set_default_encoding {{{
static PyObject * static PyObject *
icu_set_default_encoding(PyObject *self, PyObject *args) { icu_set_default_encoding(PyObject *self, PyObject *args) {
@ -1058,6 +1092,10 @@ static PyMethodDef icu_methods[] = {
"change_case(unicode object, which, locale) -> change case to one of UPPER_CASE, LOWER_CASE, TITLE_CASE" "change_case(unicode object, which, locale) -> change case to one of UPPER_CASE, LOWER_CASE, TITLE_CASE"
}, },
{"swap_case", icu_swap_case, METH_VARARGS,
"swap_case(unicode object) -> swaps the case using the simple, locale independent unicode algorithm"
},
{"set_default_encoding", icu_set_default_encoding, METH_VARARGS, {"set_default_encoding", icu_set_default_encoding, METH_VARARGS,
"set_default_encoding(encoding) -> Set the default encoding for the python unicode implementation." "set_default_encoding(encoding) -> Set the default encoding for the python unicode implementation."
}, },

View File

@ -212,6 +212,11 @@ def capitalize(x):
except (IndexError, TypeError, AttributeError): except (IndexError, TypeError, AttributeError):
return x return x
try:
swapcase = _icu.swap_case
except AttributeError: # For people running from source
swapcase = lambda x:x.swapcase()
find = _make_func(_strcmp_template, 'find', collator='_collator', collator_func='collator', func='find') find = _make_func(_strcmp_template, 'find', collator='_collator', collator_func='collator', func='find')
primary_find = _make_func(_strcmp_template, 'primary_find', collator='_primary_collator', collator_func='primary_collator', func='find') primary_find = _make_func(_strcmp_template, 'primary_find', collator='_primary_collator', collator_func='primary_collator', func='find')

View File

@ -90,6 +90,7 @@ class TestICU(unittest.TestCase):
# capitals inside words # capitals inside words
self.ae(icu.title_case(x), titlecase(x).replace('machIne', 'Machine')) self.ae(icu.title_case(x), titlecase(x).replace('machIne', 'Machine'))
self.ae(icu.capitalize(x), x[0].upper() + x[1:].lower()) self.ae(icu.capitalize(x), x[0].upper() + x[1:].lower())
self.ae(icu.swapcase(x), x.swapcase())
def test_find(self): def test_find(self):
' Test searching for substrings ' ' Test searching for substrings '