// Collator.startswith {{{ static PyObject * icu_Collator_startswith(icu_Collator *self, PyObject *args, PyObject *kwargs) { PyObject *a_ = NULL, *b_ = NULL; int32_t asz = 0, bsz = 0; UChar *a = NULL, *b = NULL; uint8_t ans = 0; if (!PyArg_ParseTuple(args, "OO", &a_, &b_)) return NULL; a = python_to_icu(a_, &asz, 1); if (a == NULL) goto end; b = python_to_icu(b_, &bsz, 1); if (b == NULL) goto end; if (asz < bsz) goto end; if (bsz == 0) { ans = 1; goto end; } ans = ucol_equal(self->collator, a, bsz, b, bsz); end: if (a != NULL) free(a); if (b != NULL) free(b); if (PyErr_Occurred()) return NULL; if (ans) { Py_RETURN_TRUE; } Py_RETURN_FALSE; } // }}}
// Collator.contains {{{ static PyObject * icu_Collator_contains(icu_Collator *self, PyObject *args, PyObject *kwargs) { PyObject *a_ = NULL, *b_ = NULL; UChar *a = NULL, *b = NULL; int32_t asz = 0, bsz = 0, pos = -1; uint8_t found = 0; UErrorCode status = U_ZERO_ERROR; UStringSearch *search = NULL; if (!PyArg_ParseTuple(args, "OO", &a_, &b_)) return NULL; a = python_to_icu(a_, &asz, 1); if (a == NULL) goto end; if (asz == 0) { found = TRUE; goto end; } b = python_to_icu(b_, &bsz, 1); if (b == NULL) goto end; search = usearch_openFromCollator(a, asz, b, bsz, self->collator, NULL, &status); if (U_SUCCESS(status)) { pos = usearch_first(search, &status); if (pos != USEARCH_DONE) found = TRUE; } end: if (search != NULL) usearch_close(search); if (a != NULL) free(a); if (b != NULL) free(b); if (PyErr_Occurred()) return NULL; if (found) Py_RETURN_TRUE; Py_RETURN_FALSE; } // }}}
static int Matcher_init(Matcher *self, PyObject *args, PyObject *kwds) { PyObject *items = NULL, *p = NULL, *py_items = NULL, *level1 = NULL, *level2 = NULL, *level3 = NULL; int32_t i = 0; if (!PyArg_ParseTuple(args, "OOOO", &items, &level1, &level2, &level3)) return -1; py_items = PySequence_Fast(items, "Must pass in two sequence objects"); if (py_items == NULL) goto end; self->item_count = (uint32_t)PySequence_Size(items); self->items = (UChar**)calloc(self->item_count, sizeof(UChar*)); self->item_lengths = (int32_t*)calloc(self->item_count, sizeof(uint32_t)); self->level1 = python_to_icu(level1, NULL, 1); self->level2 = python_to_icu(level2, NULL, 1); self->level3 = python_to_icu(level3, NULL, 1); if (self->items == NULL || self->item_lengths == NULL ) { PyErr_NoMemory(); goto end; } if (self->level1 == NULL || self->level2 == NULL || self->level3 == NULL) goto end; for (i = 0; i < (int32_t)self->item_count; i++) { p = PySequence_Fast_GET_ITEM(py_items, i); self->items[i] = python_to_icu(p, self->item_lengths + i, 1); if (self->items[i] == NULL) { PyErr_NoMemory(); goto end; } } end: Py_XDECREF(py_items); if (PyErr_Occurred()) { free_matcher(self); } return (PyErr_Occurred()) ? -1 : 0; }
static PyObject* icu_swap_case(PyObject *self, PyObject *input) { PyObject *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; input_buf = python_to_icu(input, &sz); 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; } // }}}
// character_name {{{ static PyObject * icu_character_name(PyObject *self, PyObject *args) { char name[512] = {0}; int32_t sz = 0, alias = 0; UChar *buf; UErrorCode status = U_ZERO_ERROR; PyObject *palias = NULL, *result = NULL, *input = NULL; UChar32 code = 0; if (!PyArg_ParseTuple(args, "O|O", &input, &palias)) return NULL; if (palias != NULL && PyObject_IsTrue(palias)) alias = 1; buf = python_to_icu(input, &sz, 1); if (buf == NULL) goto end; U16_GET(buf, 0, 0, sz, code); if (alias) { sz = u_charName(code, U_CHAR_NAME_ALIAS, name, 511, &status); } else { sz = u_charName(code, U_UNICODE_CHAR_NAME, name, 511, &status); } if (U_FAILURE(status)) { PyErr_SetString(PyExc_ValueError, "Failed to get name for code"); goto end; } result = PyUnicode_DecodeUTF8(name, sz, "strict"); end: if (buf != NULL) free(buf); return result; } // }}}
// Collator.sort_key {{{ static PyObject * icu_Collator_sort_key(icu_Collator *self, PyObject *args, PyObject *kwargs) { int32_t sz = 0, key_size = 0, bsz = 0; UChar *buf = NULL; uint8_t *buf2 = NULL; PyObject *ans = NULL, *input = NULL; if (!PyArg_ParseTuple(args, "O", &input)) return NULL; buf = python_to_icu(input, &sz, 1); if (buf == NULL) return NULL; bsz = 7 * sz + 1; buf2 = (uint8_t*)calloc(bsz, sizeof(uint8_t)); if (buf2 == NULL) { PyErr_NoMemory(); goto end; } key_size = ucol_getSortKey(self->collator, buf, sz, buf2, bsz); if (key_size > bsz) { buf2 = realloc(buf2, (key_size + 1) * sizeof(uint8_t)); if (buf2 == NULL) { PyErr_NoMemory(); goto end; } key_size = ucol_getSortKey(self->collator, buf, sz, buf2, key_size + 1); } ans = PyBytes_FromStringAndSize((char*)buf2, key_size); end: if (buf != NULL) free(buf); if (buf2 != NULL) free(buf2); return ans; } // }}}
static PyObject * icu_normalize(PyObject *self, PyObject *args) { UErrorCode status = U_ZERO_ERROR; int32_t sz = 0, cap = 0, rsz = 0; NORM_MODES mode; UChar *dest = NULL, *source = NULL; PyObject *ret = NULL, *src = NULL; if (!PyArg_ParseTuple(args, "iO", &mode, &src)) return NULL; const UNormalizer2 *n = NULL; switch (mode) { case NFC: n = unorm2_getNFCInstance(&status); break; case NFKC: n = unorm2_getNFKCInstance(&status); break; case NFD: n = unorm2_getNFDInstance(&status); break; case NFKD: n = unorm2_getNFKDInstance(&status); break; } if (U_FAILURE(status)) { PyErr_SetString(PyExc_ValueError, u_errorName(status)); goto end; } source = python_to_icu(src, &sz); if (source == NULL) goto end; cap = 2 * sz; dest = (UChar*) calloc(cap, sizeof(UChar)); if (dest == NULL) { PyErr_NoMemory(); goto end; } while (1) { rsz = unorm2_normalize(n, source, sz, dest, cap, &status); if (status == U_BUFFER_OVERFLOW_ERROR) { cap *= 2; dest = (UChar*) realloc(dest, cap*sizeof(UChar)); if (dest == NULL) { PyErr_NoMemory(); goto end; } continue; } break; } if (U_FAILURE(status)) { PyErr_SetString(PyExc_ValueError, u_errorName(status)); goto end; } ret = icu_to_python(dest, rsz); end: if (source != NULL) free(source); if (dest != NULL) free(dest); return ret; } // }}}
// BreakIterator.index {{{ static PyObject * icu_BreakIterator_index(icu_BreakIterator *self, PyObject *token) { #if PY_VERSION_HEX >= 0x03030000 #error Not implemented for python >= 3.3 #endif UChar *buf = NULL, *needle = NULL; int32_t word_start = 0, p = 0, sz = 0, ans = -1, leading_hyphen = 0, trailing_hyphen = 0; buf = python_to_icu(token, &sz); if (buf == NULL) return NULL; if (sz < 1) goto end; needle = buf; if (sz > 1 && IS_HYPHEN_CHAR(buf[0])) { needle = buf + 1; leading_hyphen = 1; sz -= 1; } if (sz > 1 && IS_HYPHEN_CHAR(buf[sz-1])) trailing_hyphen = 1; Py_BEGIN_ALLOW_THREADS; p = ubrk_first(self->break_iterator); while (p != UBRK_DONE) { word_start = p; p = ubrk_next(self->break_iterator); if (self->type == UBRK_WORD && ubrk_getRuleStatus(self->break_iterator) == UBRK_WORD_NONE) continue; // We are not at the start of a word if (self->text_len >= word_start + sz && memcmp(self->text + word_start, needle, sz * sizeof(UChar)) == 0) { if (word_start > 0 && ( (leading_hyphen && !IS_HYPHEN_CHAR(self->text[word_start-1])) || (!leading_hyphen && IS_HYPHEN_CHAR(self->text[word_start-1])) )) continue; if (!trailing_hyphen && IS_HYPHEN_CHAR(self->text[word_start + sz])) continue; if (p == UBRK_DONE || self->text_len <= word_start + sz) { ans = word_start; break; } if ( // Check that the found word is followed by a word boundary ubrk_isBoundary(self->break_iterator, word_start + sz) && // If there is a leading hyphen check that the leading // hyphen is preceded by a word boundary (!leading_hyphen || (word_start > 1 && ubrk_isBoundary(self->break_iterator, word_start - 2))) && // Check that there is a word boundary *after* the trailing // hyphen. We cannot rely on ubrk_isBoundary() as that // always returns true because of the trailing hyphen. (!trailing_hyphen || ubrk_following(self->break_iterator, word_start + sz) == UBRK_DONE || ubrk_getRuleStatus(self->break_iterator) == UBRK_WORD_NONE) ) { ans = word_start; break; } if (p != UBRK_DONE) ubrk_isBoundary(self->break_iterator, p); // Reset the iterator to its position before the call to ubrk_isBoundary() } } if (leading_hyphen && ans > -1) ans -= 1; #ifdef Py_UNICODE_WIDE if (ans > 0) ans = u_countChar32(self->text, ans); #endif Py_END_ALLOW_THREADS; end: free(buf); return Py_BuildValue("l", (long)ans); } // }}}
// Collator.strcmp {{{ static PyObject * icu_Collator_strcmp(icu_Collator *self, PyObject *args, PyObject *kwargs) { PyObject *a_ = NULL, *b_ = NULL; int32_t asz = 0, bsz = 0; UChar *a = NULL, *b = NULL; UCollationResult res = UCOL_EQUAL; if (!PyArg_ParseTuple(args, "OO", &a_, &b_)) return NULL; a = python_to_icu(a_, &asz, 1); if (a == NULL) goto end; b = python_to_icu(b_, &bsz, 1); if (b == NULL) goto end; res = ucol_strcoll(self->collator, a, asz, b, bsz); end: if (a != NULL) free(a); if (b != NULL) free(b); return (PyErr_Occurred()) ? NULL : Py_BuildValue("i", res); } // }}}
static int Matcher_init(Matcher *self, PyObject *args, PyObject *kwds) { PyObject *items = NULL, *p = NULL, *py_items = NULL, *level1 = NULL, *level2 = NULL, *level3 = NULL, *collator = NULL; int32_t i = 0; UErrorCode status = U_ZERO_ERROR; UCollator *col = NULL; if (!PyArg_ParseTuple(args, "OOOOO", &items, &collator, &level1, &level2, &level3)) return -1; // Clone the passed in collator (cloning is needed as collators are not thread safe) if (!PyCapsule_CheckExact(collator)) { PyErr_SetString(PyExc_TypeError, "Collator must be a capsule"); return -1; } col = (UCollator*)PyCapsule_GetPointer(collator, NULL); if (col == NULL) return -1; self->collator = ucol_safeClone(col, NULL, NULL, &status); col = NULL; if (U_FAILURE(status)) { self->collator = NULL; PyErr_SetString(PyExc_ValueError, u_errorName(status)); return -1; } py_items = PySequence_Fast(items, "Must pass in two sequence objects"); if (py_items == NULL) goto end; self->item_count = (uint32_t)PySequence_Size(items); self->items = (UChar**)calloc(self->item_count, sizeof(UChar*)); self->item_lengths = (int32_t*)calloc(self->item_count, sizeof(uint32_t)); self->level1 = python_to_icu(level1, NULL); self->level2 = python_to_icu(level2, NULL); self->level3 = python_to_icu(level3, NULL); if (self->items == NULL || self->item_lengths == NULL ) { PyErr_NoMemory(); goto end; } if (self->level1 == NULL || self->level2 == NULL || self->level3 == NULL) goto end; for (i = 0; i < (int32_t)self->item_count; i++) { p = PySequence_Fast_GET_ITEM(py_items, i); self->items[i] = python_to_icu(p, self->item_lengths + i); if (self->items[i] == NULL) { PyErr_NoMemory(); goto end; } } end: Py_XDECREF(py_items); if (PyErr_Occurred()) { free_matcher(self); } return (PyErr_Occurred()) ? -1 : 0; }
// string_length {{{ static PyObject * icu_string_length(PyObject *self, PyObject *src) { int32_t sz = 0; UChar *icu = NULL; icu = python_to_icu(src, &sz); if (icu == NULL) return NULL; sz = u_countChar32(icu, sz); free(icu); return Py_BuildValue("l", (long)sz); } // }}}
// roundtrip {{{ static PyObject * icu_roundtrip(PyObject *self, PyObject *src) { int32_t sz = 0; UChar *icu = NULL; PyObject *ret = NULL; icu = python_to_icu(src, &sz); if (icu != NULL) { ret = icu_to_python(icu, sz); free(icu); } return ret; } // }}}
// string_length {{{ static PyObject * icu_string_length(PyObject *self, PyObject *args) { int32_t sz = 0; UChar *icu = NULL; PyObject *src = NULL; if (!PyArg_ParseTuple(args, "O", &src)) return NULL; icu = python_to_icu(src, &sz, 1); if (icu == NULL) return NULL; sz = u_countChar32(icu, sz); free(icu); return Py_BuildValue("i", sz); } // }}}
// Collator.find {{{ static PyObject * icu_Collator_find(icu_Collator *self, PyObject *args, PyObject *kwargs) { #if PY_VERSION_HEX >= 0x03030000 #error Not implemented for python >= 3.3 #endif PyObject *a_ = NULL, *b_ = NULL; UChar *a = NULL, *b = NULL; int32_t asz = 0, bsz = 0, pos = -1, length = -1; UErrorCode status = U_ZERO_ERROR; UStringSearch *search = NULL; if (!PyArg_ParseTuple(args, "OO", &a_, &b_)) return NULL; a = python_to_icu(a_, &asz, 1); if (a == NULL) goto end; b = python_to_icu(b_, &bsz, 1); if (b == NULL) goto end; search = usearch_openFromCollator(a, asz, b, bsz, self->collator, NULL, &status); if (U_SUCCESS(status)) { pos = usearch_first(search, &status); if (pos != USEARCH_DONE) { length = usearch_getMatchedLength(search); #ifdef Py_UNICODE_WIDE // We have to return number of unicode characters since the string // could contain surrogate pairs which are represented as a single // character in python wide builds length = u_countChar32(b + pos, length); pos = u_countChar32(b, pos); #endif } else pos = -1; } end: if (search != NULL) usearch_close(search); if (a != NULL) free(a); if (b != NULL) free(b); return (PyErr_Occurred()) ? NULL : Py_BuildValue("ii", pos, length); } // }}}
// Matcher.calculate_scores {{{ static PyObject * Matcher_calculate_scores(Matcher *self, PyObject *args) { int32_t *final_positions = NULL, *p; Match *matches = NULL; bool ok = FALSE; uint32_t i = 0, needle_char_len = 0, j = 0; PyObject *items = NULL, *score = NULL, *positions = NULL, *pneedle = NULL; UChar *needle = NULL; if (!PyArg_ParseTuple(args, "O", &pneedle)) return NULL; needle = python_to_icu(pneedle, NULL); if (needle == NULL) return NULL; needle_char_len = u_countChar32(needle, -1); items = PyTuple_New(self->item_count); positions = PyTuple_New(self->item_count); matches = (Match*)calloc(self->item_count, sizeof(Match)); final_positions = (int32_t*) calloc(needle_char_len * self->item_count, sizeof(int32_t)); if (items == NULL || matches == NULL || final_positions == NULL || positions == NULL) {PyErr_NoMemory(); goto end;} for (i = 0; i < self->item_count; i++) { score = PyTuple_New(needle_char_len); if (score == NULL) { PyErr_NoMemory(); goto end; } PyTuple_SET_ITEM(positions, (Py_ssize_t)i, score); } Py_BEGIN_ALLOW_THREADS; ok = match(self->items, self->item_lengths, self->item_count, needle, matches, final_positions, needle_char_len, self->collator, self->level1, self->level2, self->level3); Py_END_ALLOW_THREADS; if (ok) { for (i = 0; i < self->item_count; i++) { score = PyFloat_FromDouble(matches[i].score); if (score == NULL) { PyErr_NoMemory(); goto end; } PyTuple_SET_ITEM(items, (Py_ssize_t)i, score); p = final_positions + (i * needle_char_len); for (j = 0; j < needle_char_len; j++) { score = PyLong_FromLong((long)p[j]); if (score == NULL) { PyErr_NoMemory(); goto end; } PyTuple_SET_ITEM(PyTuple_GET_ITEM(positions, (Py_ssize_t)i), (Py_ssize_t)j, score); } } } else { PyErr_NoMemory(); goto end; } end: nullfree(needle); nullfree(matches); nullfree(final_positions); if (PyErr_Occurred()) { Py_XDECREF(items); items = NULL; Py_XDECREF(positions); positions = NULL; return NULL; } return Py_BuildValue("NN", items, positions); } // }}}
// roundtrip {{{ static PyObject * icu_roundtrip(PyObject *self, PyObject *args) { int32_t sz = 0; UChar *icu = NULL; PyObject *ret = NULL, *src = NULL; if (!PyArg_ParseTuple(args, "O", &src)) return NULL; icu = python_to_icu(src, &sz, 1); if (icu != NULL) { ret = icu_to_python(icu, sz); free(icu); } return ret; } // }}}
// BreakIterator.set_text {{{ static PyObject * icu_BreakIterator_set_text(icu_BreakIterator *self, PyObject *input) { int32_t sz = 0; UChar *buf = NULL; UErrorCode status = U_ZERO_ERROR; buf = python_to_icu(input, &sz); if (buf == NULL) return NULL; ubrk_setText(self->break_iterator, buf, sz, &status); if (U_FAILURE(status)) { free(buf); buf = NULL; PyErr_SetString(PyExc_ValueError, u_errorName(status)); } else { self->text = buf; self->text_len = sz; } Py_RETURN_NONE; } // }}}
// string_length {{{ static PyObject * icu_string_length(PyObject *self, PyObject *args) { #if PY_VERSION_HEX >= 0x03030000 #error Not implemented for python >= 3.3 #endif int32_t sz = 0; UChar *icu = NULL; PyObject *src = NULL; if (!PyArg_ParseTuple(args, "O", &src)) return NULL; icu = python_to_icu(src, &sz, 1); if (icu == NULL) return NULL; sz = u_countChar32(icu, sz); free(icu); return Py_BuildValue("i", sz); } // }}}
// Collator.collation_order {{{ static PyObject * icu_Collator_collation_order(icu_Collator *self, PyObject *a_) { int32_t asz = 0; UChar *a = NULL; UErrorCode status = U_ZERO_ERROR; UCollationElements *iter = NULL; int order = 0, len = -1; a = python_to_icu(a_, &asz); if (a == NULL) goto end; iter = ucol_openElements(self->collator, a, asz, &status); if (U_FAILURE(status)) { PyErr_SetString(PyExc_ValueError, u_errorName(status)); goto end; } order = ucol_next(iter, &status); len = ucol_getOffset(iter); end: if (iter != NULL) ucol_closeElements(iter); iter = NULL; if (a != NULL) free(a); if (PyErr_Occurred()) return NULL; return Py_BuildValue("ii", order, len); } // }}}
static PyObject* icu_change_case(PyObject *self, PyObject *args) { char *locale = NULL; PyObject *input = NULL, *result = NULL; int which = UPPER_CASE; UErrorCode status = U_ZERO_ERROR; UChar *input_buf = NULL, *output_buf = NULL; int32_t sz = 0; if (!PyArg_ParseTuple(args, "Oiz", &input, &which, &locale)) return NULL; if (locale == NULL) { PyErr_SetString(PyExc_NotImplementedError, "You must specify a locale"); // We deliberately use NotImplementedError so that this error can be unambiguously identified return NULL; } input_buf = python_to_icu(input, &sz, 1); if (input_buf == NULL) goto end; output_buf = (UChar*) calloc(3 * sz, sizeof(UChar)); if (output_buf == NULL) { PyErr_NoMemory(); goto end; } switch (which) { case TITLE_CASE: sz = u_strToTitle(output_buf, 3 * sz, input_buf, sz, NULL, locale, &status); break; case UPPER_CASE: sz = u_strToUpper(output_buf, 3 * sz, input_buf, sz, locale, &status); break; default: sz = u_strToLower(output_buf, 3 * sz, input_buf, sz, locale, &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); return result; } // }}}
// BreakIterator.index {{{ static PyObject * icu_BreakIterator_index(icu_BreakIterator *self, PyObject *args, PyObject *kwargs) { #if PY_VERSION_HEX >= 0x03030000 #error Not implemented for python >= 3.3 #endif UChar *buf = NULL; int32_t prev = 0, p = 0, sz = 0, tsz = 0, ans = -1; PyObject *token = NULL; if (!PyArg_ParseTuple(args, "O", &token)) return NULL; buf = python_to_icu(token, &sz, 1); if (buf == NULL) return NULL; if (sz < 1) goto end; Py_BEGIN_ALLOW_THREADS; p = ubrk_first(self->break_iterator); while (p != UBRK_DONE) { prev = p; p = ubrk_next(self->break_iterator); if (self->type == UBRK_WORD && ubrk_getRuleStatus(self->break_iterator) == UBRK_WORD_NONE) continue; // We are not at the start of a word tsz = (p == UBRK_DONE) ? self->text_len - prev : p - prev; if (sz == tsz && memcmp(self->text + prev, buf, sz * sizeof(UChar)) == 0) { #ifdef PY_UNICODE_WIDE ans = u_countChar32(self->text, prev); #else ans = prev; #endif break; } } Py_END_ALLOW_THREADS; end: free(buf); return Py_BuildValue("i", ans); } // }}}
// normalize {{{ static PyObject * icu_normalize(PyObject *self, PyObject *args) { UErrorCode status = U_ZERO_ERROR; int32_t sz = 0, mode = UNORM_DEFAULT, cap = 0, rsz = 0; UChar *dest = NULL, *source = NULL; PyObject *ret = NULL, *src = NULL; if (!PyArg_ParseTuple(args, "iO", &mode, &src)) return NULL; source = python_to_icu(src, &sz, 1); if (source == NULL) goto end; cap = 2 * sz; dest = (UChar*) calloc(cap, sizeof(UChar)); if (dest == NULL) { PyErr_NoMemory(); goto end; } while (1) { rsz = unorm_normalize(source, sz, (UNormalizationMode)mode, 0, dest, cap, &status); if (status == U_BUFFER_OVERFLOW_ERROR) { cap *= 2; dest = (UChar*) realloc(dest, cap*sizeof(UChar)); if (dest == NULL) { PyErr_NoMemory(); goto end; } continue; } break; } if (U_FAILURE(status)) { PyErr_SetString(PyExc_ValueError, u_errorName(status)); goto end; } ret = icu_to_python(dest, rsz); end: if (source != NULL) free(source); if (dest != NULL) free(dest); return ret; } // }}}