summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/i18n/utrans.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intl/icu/source/i18n/utrans.cpp')
-rw-r--r--intl/icu/source/i18n/utrans.cpp533
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 000000000..6a4c4a7d8
--- /dev/null
+++ b/intl/icu/source/i18n/utrans.cpp
@@ -0,0 +1,533 @@
+// Copyright (C) 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;
+ UReplaceableCallbacks *func;
+
+public:
+
+ ReplaceableGlue(UReplaceable *replaceable,
+ 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,
+ 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,
+ 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,
+ 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 */