diff options
Diffstat (limited to 'intl/icu/source/i18n/utrans.cpp')
-rw-r--r-- | intl/icu/source/i18n/utrans.cpp | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/intl/icu/source/i18n/utrans.cpp b/intl/icu/source/i18n/utrans.cpp new file mode 100644 index 0000000000..29013ead12 --- /dev/null +++ b/intl/icu/source/i18n/utrans.cpp @@ -0,0 +1,533 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* + ******************************************************************************* + * Copyright (C) 1997-2009,2014 International Business Machines + * Corporation and others. All Rights Reserved. + ******************************************************************************* + * Date Name Description + * 06/21/00 aliu Creation. + ******************************************************************************* + */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_TRANSLITERATION + +#include "unicode/utrans.h" +#include "unicode/putil.h" +#include "unicode/rep.h" +#include "unicode/translit.h" +#include "unicode/unifilt.h" +#include "unicode/uniset.h" +#include "unicode/ustring.h" +#include "unicode/uenum.h" +#include "unicode/uset.h" +#include "uenumimp.h" +#include "cpputils.h" +#include "rbt.h" + +// Following macro is to be followed by <return value>';' or just ';' +#define utrans_ENTRY(s) if ((s)==NULL || U_FAILURE(*(s))) return + +/******************************************************************** + * Replaceable-UReplaceableCallbacks glue + ********************************************************************/ + +/** + * Make a UReplaceable + UReplaceableCallbacks into a Replaceable object. + */ +U_NAMESPACE_BEGIN +class ReplaceableGlue : public Replaceable { + + UReplaceable *rep; + const UReplaceableCallbacks *func; + +public: + + ReplaceableGlue(UReplaceable *replaceable, + const UReplaceableCallbacks *funcCallback); + + virtual ~ReplaceableGlue(); + + virtual void handleReplaceBetween(int32_t start, + int32_t limit, + const UnicodeString& text); + + virtual void extractBetween(int32_t start, + int32_t limit, + UnicodeString& target) const; + + virtual void copy(int32_t start, int32_t limit, int32_t dest); + + // virtual Replaceable *clone() const { return NULL; } same as default + + /** + * ICU "poor man's RTTI", returns a UClassID for the actual class. + * + * @draft ICU 2.2 + */ + virtual UClassID getDynamicClassID() const; + + /** + * ICU "poor man's RTTI", returns a UClassID for this class. + * + * @draft ICU 2.2 + */ + static UClassID U_EXPORT2 getStaticClassID(); + +protected: + + virtual int32_t getLength() const; + + virtual UChar getCharAt(int32_t offset) const; + + virtual UChar32 getChar32At(int32_t offset) const; +}; + +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue) + +ReplaceableGlue::ReplaceableGlue(UReplaceable *replaceable, + const UReplaceableCallbacks *funcCallback) + : Replaceable() +{ + this->rep = replaceable; + this->func = funcCallback; +} + +ReplaceableGlue::~ReplaceableGlue() {} + +int32_t ReplaceableGlue::getLength() const { + return (*func->length)(rep); +} + +UChar ReplaceableGlue::getCharAt(int32_t offset) const { + return (*func->charAt)(rep, offset); +} + +UChar32 ReplaceableGlue::getChar32At(int32_t offset) const { + return (*func->char32At)(rep, offset); +} + +void ReplaceableGlue::handleReplaceBetween(int32_t start, + int32_t limit, + const UnicodeString& text) { + (*func->replace)(rep, start, limit, text.getBuffer(), text.length()); +} + +void ReplaceableGlue::extractBetween(int32_t start, + int32_t limit, + UnicodeString& target) const { + (*func->extract)(rep, start, limit, target.getBuffer(limit-start)); + target.releaseBuffer(limit-start); +} + +void ReplaceableGlue::copy(int32_t start, int32_t limit, int32_t dest) { + (*func->copy)(rep, start, limit, dest); +} +U_NAMESPACE_END +/******************************************************************** + * General API + ********************************************************************/ +U_NAMESPACE_USE + +U_CAPI UTransliterator* U_EXPORT2 +utrans_openU(const UChar *id, + int32_t idLength, + UTransDirection dir, + const UChar *rules, + int32_t rulesLength, + UParseError *parseError, + UErrorCode *status) { + if(status==NULL || U_FAILURE(*status)) { + return NULL; + } + if (id == NULL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return NULL; + } + UParseError temp; + + if(parseError == NULL){ + parseError = &temp; + } + + UnicodeString ID(idLength<0, id, idLength); // r-o alias + + if(rules==NULL){ + + Transliterator *trans = NULL; + + trans = Transliterator::createInstance(ID, dir, *parseError, *status); + + if(U_FAILURE(*status)){ + return NULL; + } + return (UTransliterator*) trans; + }else{ + UnicodeString ruleStr(rulesLength < 0, + rules, + rulesLength); // r-o alias + + Transliterator *trans = NULL; + trans = Transliterator::createFromRules(ID, ruleStr, dir, *parseError, *status); + if(U_FAILURE(*status)) { + return NULL; + } + + return (UTransliterator*) trans; + } +} + +U_CAPI UTransliterator* U_EXPORT2 +utrans_open(const char* id, + UTransDirection dir, + const UChar* rules, /* may be Null */ + int32_t rulesLength, /* -1 if null-terminated */ + UParseError* parseError, /* may be Null */ + UErrorCode* status) { + UnicodeString ID(id, -1, US_INV); // use invariant converter + return utrans_openU(ID.getBuffer(), ID.length(), dir, + rules, rulesLength, + parseError, status); +} + +U_CAPI UTransliterator* U_EXPORT2 +utrans_openInverse(const UTransliterator* trans, + UErrorCode* status) { + + utrans_ENTRY(status) NULL; + + UTransliterator* result = + (UTransliterator*) ((Transliterator*) trans)->createInverse(*status); + + return result; +} + +U_CAPI UTransliterator* U_EXPORT2 +utrans_clone(const UTransliterator* trans, + UErrorCode* status) { + + utrans_ENTRY(status) NULL; + + if (trans == NULL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return NULL; + } + + Transliterator *t = ((Transliterator*) trans)->clone(); + if (t == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + } + return (UTransliterator*) t; +} + +U_CAPI void U_EXPORT2 +utrans_close(UTransliterator* trans) { + delete (Transliterator*) trans; +} + +U_CAPI const UChar * U_EXPORT2 +utrans_getUnicodeID(const UTransliterator *trans, + int32_t *resultLength) { + // Transliterator keeps its ID NUL-terminated + const UnicodeString &ID=((Transliterator*) trans)->getID(); + if(resultLength!=NULL) { + *resultLength=ID.length(); + } + return ID.getBuffer(); +} + +U_CAPI int32_t U_EXPORT2 +utrans_getID(const UTransliterator* trans, + char* buf, + int32_t bufCapacity) { + return ((Transliterator*) trans)->getID().extract(0, 0x7fffffff, buf, bufCapacity, US_INV); +} + +U_CAPI void U_EXPORT2 +utrans_register(UTransliterator* adoptedTrans, + UErrorCode* status) { + utrans_ENTRY(status); + // status currently ignored; may remove later + Transliterator::registerInstance((Transliterator*) adoptedTrans); +} + +U_CAPI void U_EXPORT2 +utrans_unregisterID(const UChar* id, int32_t idLength) { + UnicodeString ID(idLength<0, id, idLength); // r-o alias + Transliterator::unregister(ID); +} + +U_CAPI void U_EXPORT2 +utrans_unregister(const char* id) { + UnicodeString ID(id, -1, US_INV); // use invariant converter + Transliterator::unregister(ID); +} + +U_CAPI void U_EXPORT2 +utrans_setFilter(UTransliterator* trans, + const UChar* filterPattern, + int32_t filterPatternLen, + UErrorCode* status) { + + utrans_ENTRY(status); + UnicodeFilter* filter = NULL; + if (filterPattern != NULL && *filterPattern != 0) { + // Create read only alias of filterPattern: + UnicodeString pat(filterPatternLen < 0, filterPattern, filterPatternLen); + filter = new UnicodeSet(pat, *status); + /* test for NULL */ + if (filter == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + return; + } + if (U_FAILURE(*status)) { + delete filter; + filter = NULL; + } + } + ((Transliterator*) trans)->adoptFilter(filter); +} + +U_CAPI int32_t U_EXPORT2 +utrans_countAvailableIDs(void) { + return Transliterator::countAvailableIDs(); +} + +U_CAPI int32_t U_EXPORT2 +utrans_getAvailableID(int32_t index, + char* buf, // may be NULL + int32_t bufCapacity) { + return Transliterator::getAvailableID(index).extract(0, 0x7fffffff, buf, bufCapacity, US_INV); +} + +/* Transliterator UEnumeration ---------------------------------------------- */ + +typedef struct UTransEnumeration { + UEnumeration uenum; + int32_t index, count; +} UTransEnumeration; + +U_CDECL_BEGIN +static int32_t U_CALLCONV +utrans_enum_count(UEnumeration *uenum, UErrorCode *pErrorCode) { + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { + return 0; + } + return ((UTransEnumeration *)uenum)->count; +} + +static const UChar* U_CALLCONV +utrans_enum_unext(UEnumeration *uenum, + int32_t* resultLength, + UErrorCode *pErrorCode) { + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { + return 0; + } + + UTransEnumeration *ute=(UTransEnumeration *)uenum; + int32_t index=ute->index; + if(index<ute->count) { + const UnicodeString &ID=Transliterator::getAvailableID(index); + ute->index=index+1; + if(resultLength!=NULL) { + *resultLength=ID.length(); + } + // Transliterator keeps its ID NUL-terminated + return ID.getBuffer(); + } + + if(resultLength!=NULL) { + *resultLength=0; + } + return NULL; +} + +static void U_CALLCONV +utrans_enum_reset(UEnumeration *uenum, UErrorCode *pErrorCode) { + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { + return; + } + + UTransEnumeration *ute=(UTransEnumeration *)uenum; + ute->index=0; + ute->count=Transliterator::countAvailableIDs(); +} + +static void U_CALLCONV +utrans_enum_close(UEnumeration *uenum) { + uprv_free(uenum); +} +U_CDECL_END + +static const UEnumeration utransEnumeration={ + NULL, + NULL, + utrans_enum_close, + utrans_enum_count, + utrans_enum_unext, + uenum_nextDefault, + utrans_enum_reset +}; + +U_CAPI UEnumeration * U_EXPORT2 +utrans_openIDs(UErrorCode *pErrorCode) { + UTransEnumeration *ute; + + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { + return NULL; + } + + ute=(UTransEnumeration *)uprv_malloc(sizeof(UTransEnumeration)); + if(ute==NULL) { + *pErrorCode=U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + + ute->uenum=utransEnumeration; + ute->index=0; + ute->count=Transliterator::countAvailableIDs(); + return (UEnumeration *)ute; +} + +/******************************************************************** + * Transliteration API + ********************************************************************/ + +U_CAPI void U_EXPORT2 +utrans_trans(const UTransliterator* trans, + UReplaceable* rep, + const UReplaceableCallbacks* repFunc, + int32_t start, + int32_t* limit, + UErrorCode* status) { + + utrans_ENTRY(status); + + if (trans == 0 || rep == 0 || repFunc == 0 || limit == 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + ReplaceableGlue r(rep, repFunc); + + *limit = ((Transliterator*) trans)->transliterate(r, start, *limit); +} + +U_CAPI void U_EXPORT2 +utrans_transIncremental(const UTransliterator* trans, + UReplaceable* rep, + const UReplaceableCallbacks* repFunc, + UTransPosition* pos, + UErrorCode* status) { + + utrans_ENTRY(status); + + if (trans == 0 || rep == 0 || repFunc == 0 || pos == 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + ReplaceableGlue r(rep, repFunc); + + ((Transliterator*) trans)->transliterate(r, *pos, *status); +} + +U_CAPI void U_EXPORT2 +utrans_transUChars(const UTransliterator* trans, + UChar* text, + int32_t* textLength, + int32_t textCapacity, + int32_t start, + int32_t* limit, + UErrorCode* status) { + + utrans_ENTRY(status); + + if (trans == 0 || text == 0 || limit == 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + int32_t textLen = (textLength == NULL || *textLength < 0) + ? u_strlen(text) : *textLength; + // writeable alias: for this ct, len CANNOT be -1 (why?) + UnicodeString str(text, textLen, textCapacity); + + *limit = ((Transliterator*) trans)->transliterate(str, start, *limit); + + // Copy the string buffer back to text (only if necessary) + // and fill in *neededCapacity (if neededCapacity != NULL). + textLen = str.extract(text, textCapacity, *status); + if(textLength != NULL) { + *textLength = textLen; + } +} + +U_CAPI void U_EXPORT2 +utrans_transIncrementalUChars(const UTransliterator* trans, + UChar* text, + int32_t* textLength, + int32_t textCapacity, + UTransPosition* pos, + UErrorCode* status) { + + utrans_ENTRY(status); + + if (trans == 0 || text == 0 || pos == 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + int32_t textLen = (textLength == NULL || *textLength < 0) + ? u_strlen(text) : *textLength; + // writeable alias: for this ct, len CANNOT be -1 (why?) + UnicodeString str(text, textLen, textCapacity); + + ((Transliterator*) trans)->transliterate(str, *pos, *status); + + // Copy the string buffer back to text (only if necessary) + // and fill in *neededCapacity (if neededCapacity != NULL). + textLen = str.extract(text, textCapacity, *status); + if(textLength != NULL) { + *textLength = textLen; + } +} + +U_CAPI int32_t U_EXPORT2 +utrans_toRules( const UTransliterator* trans, + UBool escapeUnprintable, + UChar* result, int32_t resultLength, + UErrorCode* status) { + utrans_ENTRY(status) 0; + if ( (result==NULL)? resultLength!=0: resultLength<0 ) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + UnicodeString res; + res.setTo(result, 0, resultLength); + ((Transliterator*) trans)->toRules(res, escapeUnprintable); + return res.extract(result, resultLength, *status); +} + +U_CAPI USet* U_EXPORT2 +utrans_getSourceSet(const UTransliterator* trans, + UBool ignoreFilter, + USet* fillIn, + UErrorCode* status) { + utrans_ENTRY(status) fillIn; + + if (fillIn == NULL) { + fillIn = uset_openEmpty(); + } + if (ignoreFilter) { + ((Transliterator*) trans)->handleGetSourceSet(*((UnicodeSet*)fillIn)); + } else { + ((Transliterator*) trans)->getSourceSet(*((UnicodeSet*)fillIn)); + } + return fillIn; +} + +#endif /* #if !UCONFIG_NO_TRANSLITERATION */ |