intl/icu/source/i18n/utrans.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  *******************************************************************************
     3  *   Copyright (C) 1997-2009, International Business Machines
     4  *   Corporation and others.  All Rights Reserved.
     5  *******************************************************************************
     6  *   Date        Name        Description
     7  *   06/21/00    aliu        Creation.
     8  *******************************************************************************
     9  */
    11 #include "unicode/utypes.h"
    13 #if !UCONFIG_NO_TRANSLITERATION
    15 #include "unicode/utrans.h"
    16 #include "unicode/putil.h"
    17 #include "unicode/rep.h"
    18 #include "unicode/translit.h"
    19 #include "unicode/unifilt.h"
    20 #include "unicode/uniset.h"
    21 #include "unicode/ustring.h"
    22 #include "unicode/uenum.h"
    23 #include "uenumimp.h"
    24 #include "cpputils.h"
    25 #include "rbt.h"
    27 // Following macro is to be followed by <return value>';' or just ';'
    28 #define utrans_ENTRY(s) if ((s)==NULL || U_FAILURE(*(s))) return
    30 /********************************************************************
    31  * Replaceable-UReplaceableCallbacks glue
    32  ********************************************************************/
    34 /**
    35  * Make a UReplaceable + UReplaceableCallbacks into a Replaceable object.
    36  */
    37 U_NAMESPACE_BEGIN
    38 class ReplaceableGlue : public Replaceable {
    40     UReplaceable *rep;
    41     UReplaceableCallbacks *func;
    43 public:
    45     ReplaceableGlue(UReplaceable *replaceable,
    46                     UReplaceableCallbacks *funcCallback);
    48     virtual ~ReplaceableGlue();
    50     virtual void handleReplaceBetween(int32_t start,
    51                                       int32_t limit,
    52                                       const UnicodeString& text);
    54     virtual void extractBetween(int32_t start,
    55                                 int32_t limit,
    56                                 UnicodeString& target) const;
    58     virtual void copy(int32_t start, int32_t limit, int32_t dest);
    60     // virtual Replaceable *clone() const { return NULL; } same as default
    62     /**
    63      * ICU "poor man's RTTI", returns a UClassID for the actual class.
    64      *
    65      * @draft ICU 2.2
    66      */
    67     virtual UClassID getDynamicClassID() const;
    69     /**
    70      * ICU "poor man's RTTI", returns a UClassID for this class.
    71      *
    72      * @draft ICU 2.2
    73      */
    74     static UClassID U_EXPORT2 getStaticClassID();
    76 protected:
    78     virtual int32_t getLength() const;
    80     virtual UChar getCharAt(int32_t offset) const;
    82     virtual UChar32 getChar32At(int32_t offset) const;
    83 };
    85 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue)
    87 ReplaceableGlue::ReplaceableGlue(UReplaceable *replaceable,
    88                                  UReplaceableCallbacks *funcCallback)
    89   : Replaceable()
    90 {
    91     this->rep = replaceable;
    92     this->func = funcCallback;
    93 }
    95 ReplaceableGlue::~ReplaceableGlue() {}
    97 int32_t ReplaceableGlue::getLength() const {
    98     return (*func->length)(rep);
    99 }
   101 UChar ReplaceableGlue::getCharAt(int32_t offset) const {
   102     return (*func->charAt)(rep, offset);
   103 }
   105 UChar32 ReplaceableGlue::getChar32At(int32_t offset) const {
   106     return (*func->char32At)(rep, offset);
   107 }
   109 void ReplaceableGlue::handleReplaceBetween(int32_t start,
   110                           int32_t limit,
   111                           const UnicodeString& text) {
   112     (*func->replace)(rep, start, limit, text.getBuffer(), text.length());
   113 }
   115 void ReplaceableGlue::extractBetween(int32_t start,
   116                                      int32_t limit,
   117                                      UnicodeString& target) const {
   118     (*func->extract)(rep, start, limit, target.getBuffer(limit-start));
   119     target.releaseBuffer(limit-start);
   120 }
   122 void ReplaceableGlue::copy(int32_t start, int32_t limit, int32_t dest) {
   123     (*func->copy)(rep, start, limit, dest);
   124 }
   125 U_NAMESPACE_END
   126 /********************************************************************
   127  * General API
   128  ********************************************************************/
   129 U_NAMESPACE_USE
   131 U_CAPI UTransliterator* U_EXPORT2
   132 utrans_openU(const UChar *id,
   133              int32_t idLength,
   134              UTransDirection dir,
   135              const UChar *rules,
   136              int32_t rulesLength,
   137              UParseError *parseError,
   138              UErrorCode *status) {
   139     if(status==NULL || U_FAILURE(*status)) {
   140         return NULL;
   141     }
   142     if (id == NULL) {
   143         *status = U_ILLEGAL_ARGUMENT_ERROR;
   144         return NULL;
   145     }
   146     UParseError temp;
   148     if(parseError == NULL){
   149         parseError = &temp;
   150     }
   152     UnicodeString ID(idLength<0, id, idLength); // r-o alias
   154     if(rules==NULL){
   156         Transliterator *trans = NULL;
   158         trans = Transliterator::createInstance(ID, dir, *parseError, *status);
   160         if(U_FAILURE(*status)){
   161             return NULL;
   162         }
   163         return (UTransliterator*) trans;
   164     }else{
   165         UnicodeString ruleStr(rulesLength < 0,
   166                               rules,
   167                               rulesLength); // r-o alias
   169         Transliterator *trans = NULL;
   170         trans = Transliterator::createFromRules(ID, ruleStr, dir, *parseError, *status); 
   171         if(U_FAILURE(*status)) { 
   172             return NULL;
   173         }
   175         return (UTransliterator*) trans;
   176     }
   177 }
   179 U_CAPI UTransliterator* U_EXPORT2
   180 utrans_open(const char* id,
   181             UTransDirection dir,
   182             const UChar* rules,         /* may be Null */
   183             int32_t rulesLength,        /* -1 if null-terminated */ 
   184             UParseError* parseError,    /* may be Null */
   185             UErrorCode* status) {
   186     UnicodeString ID(id, -1, US_INV); // use invariant converter
   187     return utrans_openU(ID.getBuffer(), ID.length(), dir,
   188                         rules, rulesLength,
   189                         parseError, status);
   190 }
   192 U_CAPI UTransliterator* U_EXPORT2
   193 utrans_openInverse(const UTransliterator* trans,
   194                    UErrorCode* status) {
   196     utrans_ENTRY(status) NULL;
   198     UTransliterator* result =
   199         (UTransliterator*) ((Transliterator*) trans)->createInverse(*status);
   201     return result;
   202 }
   204 U_CAPI UTransliterator* U_EXPORT2
   205 utrans_clone(const UTransliterator* trans,
   206              UErrorCode* status) {
   208     utrans_ENTRY(status) NULL;
   210     if (trans == NULL) {
   211         *status = U_ILLEGAL_ARGUMENT_ERROR;
   212         return NULL;
   213     }
   215     Transliterator *t = ((Transliterator*) trans)->clone();
   216     if (t == NULL) {
   217         *status = U_MEMORY_ALLOCATION_ERROR;
   218     }
   219     return (UTransliterator*) t;
   220 }
   222 U_CAPI void U_EXPORT2
   223 utrans_close(UTransliterator* trans) {
   224     delete (Transliterator*) trans;
   225 }
   227 U_CAPI const UChar * U_EXPORT2
   228 utrans_getUnicodeID(const UTransliterator *trans,
   229                     int32_t *resultLength) {
   230     // Transliterator keeps its ID NUL-terminated
   231     const UnicodeString &ID=((Transliterator*) trans)->getID();
   232     if(resultLength!=NULL) {
   233         *resultLength=ID.length();
   234     }
   235     return ID.getBuffer();
   236 }
   238 U_CAPI int32_t U_EXPORT2
   239 utrans_getID(const UTransliterator* trans,
   240              char* buf,
   241              int32_t bufCapacity) {
   242     return ((Transliterator*) trans)->getID().extract(0, 0x7fffffff, buf, bufCapacity, US_INV);
   243 }
   245 U_CAPI void U_EXPORT2
   246 utrans_register(UTransliterator* adoptedTrans,
   247                 UErrorCode* status) {
   248     utrans_ENTRY(status);
   249     // status currently ignored; may remove later
   250     Transliterator::registerInstance((Transliterator*) adoptedTrans);
   251 }
   253 U_CAPI void U_EXPORT2
   254 utrans_unregisterID(const UChar* id, int32_t idLength) {
   255     UnicodeString ID(idLength<0, id, idLength); // r-o alias
   256     Transliterator::unregister(ID);
   257 }
   259 U_CAPI void U_EXPORT2
   260 utrans_unregister(const char* id) {
   261     UnicodeString ID(id, -1, US_INV); // use invariant converter
   262     Transliterator::unregister(ID);
   263 }
   265 U_CAPI void U_EXPORT2
   266 utrans_setFilter(UTransliterator* trans,
   267                  const UChar* filterPattern,
   268                  int32_t filterPatternLen,
   269                  UErrorCode* status) {
   271     utrans_ENTRY(status);
   272     UnicodeFilter* filter = NULL;
   273     if (filterPattern != NULL && *filterPattern != 0) {
   274         // Create read only alias of filterPattern:
   275         UnicodeString pat(filterPatternLen < 0, filterPattern, filterPatternLen);
   276         filter = new UnicodeSet(pat, *status);
   277         /* test for NULL */
   278         if (filter == NULL) {
   279             *status = U_MEMORY_ALLOCATION_ERROR;
   280             return;
   281         }
   282         if (U_FAILURE(*status)) {
   283             delete filter;
   284             filter = NULL;
   285         }
   286     }
   287     ((Transliterator*) trans)->adoptFilter(filter);
   288 }
   290 U_CAPI int32_t U_EXPORT2
   291 utrans_countAvailableIDs(void) {
   292     return Transliterator::countAvailableIDs();
   293 }
   295 U_CAPI int32_t U_EXPORT2
   296 utrans_getAvailableID(int32_t index,
   297                       char* buf, // may be NULL
   298                       int32_t bufCapacity) {
   299     return Transliterator::getAvailableID(index).extract(0, 0x7fffffff, buf, bufCapacity, US_INV);
   300 }
   302 /* Transliterator UEnumeration ---------------------------------------------- */
   304 typedef struct UTransEnumeration {
   305     UEnumeration uenum;
   306     int32_t index, count;
   307 } UTransEnumeration;
   309 U_CDECL_BEGIN
   310 static int32_t U_CALLCONV
   311 utrans_enum_count(UEnumeration *uenum, UErrorCode *pErrorCode) {
   312     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
   313         return 0;
   314     }
   315     return ((UTransEnumeration *)uenum)->count;
   316 }
   318 static const UChar* U_CALLCONV
   319 utrans_enum_unext(UEnumeration *uenum,
   320                   int32_t* resultLength,
   321                   UErrorCode *pErrorCode) {
   322     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
   323         return 0;
   324     }
   326     UTransEnumeration *ute=(UTransEnumeration *)uenum;
   327     int32_t index=ute->index;
   328     if(index<ute->count) {
   329         const UnicodeString &ID=Transliterator::getAvailableID(index);
   330         ute->index=index+1;
   331         if(resultLength!=NULL) {
   332             *resultLength=ID.length();
   333         }
   334         // Transliterator keeps its ID NUL-terminated
   335         return ID.getBuffer();
   336     }
   338     if(resultLength!=NULL) {
   339         *resultLength=0;
   340     }
   341     return NULL;
   342 }
   344 static void U_CALLCONV
   345 utrans_enum_reset(UEnumeration *uenum, UErrorCode *pErrorCode) {
   346     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
   347         return;
   348     }
   350     UTransEnumeration *ute=(UTransEnumeration *)uenum;
   351     ute->index=0;
   352     ute->count=Transliterator::countAvailableIDs();
   353 }
   355 static void U_CALLCONV
   356 utrans_enum_close(UEnumeration *uenum) {
   357     uprv_free(uenum);
   358 }
   359 U_CDECL_END
   361 static const UEnumeration utransEnumeration={
   362     NULL,
   363     NULL,
   364     utrans_enum_close,
   365     utrans_enum_count,
   366     utrans_enum_unext,
   367     uenum_nextDefault,
   368     utrans_enum_reset
   369 };
   371 U_CAPI UEnumeration * U_EXPORT2
   372 utrans_openIDs(UErrorCode *pErrorCode) {
   373     UTransEnumeration *ute;
   375     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
   376         return NULL;
   377     }
   379     ute=(UTransEnumeration *)uprv_malloc(sizeof(UTransEnumeration));
   380     if(ute==NULL) {
   381         *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
   382         return NULL;
   383     }
   385     ute->uenum=utransEnumeration;
   386     ute->index=0;
   387     ute->count=Transliterator::countAvailableIDs();
   388     return (UEnumeration *)ute;
   389 }
   391 /********************************************************************
   392  * Transliteration API
   393  ********************************************************************/
   395 U_CAPI void U_EXPORT2
   396 utrans_trans(const UTransliterator* trans,
   397              UReplaceable* rep,
   398              UReplaceableCallbacks* repFunc,
   399              int32_t start,
   400              int32_t* limit,
   401              UErrorCode* status) {
   403     utrans_ENTRY(status);
   405     if (trans == 0 || rep == 0 || repFunc == 0 || limit == 0) {
   406         *status = U_ILLEGAL_ARGUMENT_ERROR;
   407         return;
   408     }
   410     ReplaceableGlue r(rep, repFunc);
   412     *limit = ((Transliterator*) trans)->transliterate(r, start, *limit);
   413 }
   415 U_CAPI void U_EXPORT2
   416 utrans_transIncremental(const UTransliterator* trans,
   417                         UReplaceable* rep,
   418                         UReplaceableCallbacks* repFunc,
   419                         UTransPosition* pos,
   420                         UErrorCode* status) {
   422     utrans_ENTRY(status);
   424     if (trans == 0 || rep == 0 || repFunc == 0 || pos == 0) {
   425         *status = U_ILLEGAL_ARGUMENT_ERROR;
   426         return;
   427     }
   429     ReplaceableGlue r(rep, repFunc);
   431     ((Transliterator*) trans)->transliterate(r, *pos, *status);
   432 }
   434 U_CAPI void U_EXPORT2
   435 utrans_transUChars(const UTransliterator* trans,
   436                    UChar* text,
   437                    int32_t* textLength,
   438                    int32_t textCapacity,
   439                    int32_t start,
   440                    int32_t* limit,
   441                    UErrorCode* status) {
   443     utrans_ENTRY(status);
   445     if (trans == 0 || text == 0 || limit == 0) {
   446         *status = U_ILLEGAL_ARGUMENT_ERROR;
   447         return;
   448     }
   450     int32_t textLen = (textLength == NULL || *textLength < 0)
   451         ? u_strlen(text) : *textLength;
   452     // writeable alias: for this ct, len CANNOT be -1 (why?)
   453     UnicodeString str(text, textLen, textCapacity);
   455     *limit = ((Transliterator*) trans)->transliterate(str, start, *limit);
   457     // Copy the string buffer back to text (only if necessary)
   458     // and fill in *neededCapacity (if neededCapacity != NULL).
   459     textLen = str.extract(text, textCapacity, *status);
   460     if(textLength != NULL) {
   461         *textLength = textLen;
   462     }
   463 }
   465 U_CAPI void U_EXPORT2
   466 utrans_transIncrementalUChars(const UTransliterator* trans,
   467                               UChar* text,
   468                               int32_t* textLength,
   469                               int32_t textCapacity,
   470                               UTransPosition* pos,
   471                               UErrorCode* status) {
   473     utrans_ENTRY(status);
   475     if (trans == 0 || text == 0 || pos == 0) {
   476         *status = U_ILLEGAL_ARGUMENT_ERROR;
   477         return;
   478     }
   480     int32_t textLen = (textLength == NULL || *textLength < 0)
   481         ? u_strlen(text) : *textLength;
   482     // writeable alias: for this ct, len CANNOT be -1 (why?)
   483     UnicodeString str(text, textLen, textCapacity);
   485     ((Transliterator*) trans)->transliterate(str, *pos, *status);
   487     // Copy the string buffer back to text (only if necessary)
   488     // and fill in *neededCapacity (if neededCapacity != NULL).
   489     textLen = str.extract(text, textCapacity, *status);
   490     if(textLength != NULL) {
   491         *textLength = textLen;
   492     }
   493 }
   495 #endif /* #if !UCONFIG_NO_TRANSLITERATION */

mercurial