• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   */
10  
11  #include "unicode/utypes.h"
12  
13  #if !UCONFIG_NO_TRANSLITERATION
14  
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"
26  
27  // Following macro is to be followed by <return value>';' or just ';'
28  #define utrans_ENTRY(s) if ((s)==NULL || U_FAILURE(*(s))) return
29  
30  /********************************************************************
31   * Replaceable-UReplaceableCallbacks glue
32   ********************************************************************/
33  
34  /**
35   * Make a UReplaceable + UReplaceableCallbacks into a Replaceable object.
36   */
37  U_NAMESPACE_BEGIN
38  class ReplaceableGlue : public Replaceable {
39  
40      UReplaceable *rep;
41      UReplaceableCallbacks *func;
42  
43  public:
44  
45      ReplaceableGlue(UReplaceable *replaceable,
46                      UReplaceableCallbacks *funcCallback);
47  
48      virtual ~ReplaceableGlue();
49  
50      virtual void handleReplaceBetween(int32_t start,
51                                        int32_t limit,
52                                        const UnicodeString& text);
53  
54      virtual void extractBetween(int32_t start,
55                                  int32_t limit,
56                                  UnicodeString& target) const;
57  
58      virtual void copy(int32_t start, int32_t limit, int32_t dest);
59  
60      // virtual Replaceable *clone() const { return NULL; } same as default
61  
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;
68  
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();
75  
76  protected:
77  
78      virtual int32_t getLength() const;
79  
80      virtual UChar getCharAt(int32_t offset) const;
81  
82      virtual UChar32 getChar32At(int32_t offset) const;
83  };
84  
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue)85  UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue)
86  
87  ReplaceableGlue::ReplaceableGlue(UReplaceable *replaceable,
88                                   UReplaceableCallbacks *funcCallback)
89    : Replaceable()
90  {
91      this->rep = replaceable;
92      this->func = funcCallback;
93  }
94  
~ReplaceableGlue()95  ReplaceableGlue::~ReplaceableGlue() {}
96  
getLength() const97  int32_t ReplaceableGlue::getLength() const {
98      return (*func->length)(rep);
99  }
100  
getCharAt(int32_t offset) const101  UChar ReplaceableGlue::getCharAt(int32_t offset) const {
102      return (*func->charAt)(rep, offset);
103  }
104  
getChar32At(int32_t offset) const105  UChar32 ReplaceableGlue::getChar32At(int32_t offset) const {
106      return (*func->char32At)(rep, offset);
107  }
108  
handleReplaceBetween(int32_t start,int32_t limit,const UnicodeString & text)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  }
114  
extractBetween(int32_t start,int32_t limit,UnicodeString & target) const115  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  }
121  
copy(int32_t start,int32_t limit,int32_t dest)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
130  
131  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)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;
147  
148      if(parseError == NULL){
149          parseError = &temp;
150      }
151  
152      UnicodeString ID(idLength<0, id, idLength); // r-o alias
153  
154      if(rules==NULL){
155  
156          Transliterator *trans = NULL;
157  
158          trans = Transliterator::createInstance(ID, dir, *parseError, *status);
159  
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
168  
169          Transliterator *trans = NULL;
170          trans = Transliterator::createFromRules(ID, ruleStr, dir, *parseError, *status);
171          if(U_FAILURE(*status)) {
172              return NULL;
173          }
174  
175          return (UTransliterator*) trans;
176      }
177  }
178  
179  U_CAPI UTransliterator* U_EXPORT2
utrans_open(const char * id,UTransDirection dir,const UChar * rules,int32_t rulesLength,UParseError * parseError,UErrorCode * status)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  }
191  
192  U_CAPI UTransliterator* U_EXPORT2
utrans_openInverse(const UTransliterator * trans,UErrorCode * status)193  utrans_openInverse(const UTransliterator* trans,
194                     UErrorCode* status) {
195  
196      utrans_ENTRY(status) NULL;
197  
198      UTransliterator* result =
199          (UTransliterator*) ((Transliterator*) trans)->createInverse(*status);
200  
201      return result;
202  }
203  
204  U_CAPI UTransliterator* U_EXPORT2
utrans_clone(const UTransliterator * trans,UErrorCode * status)205  utrans_clone(const UTransliterator* trans,
206               UErrorCode* status) {
207  
208      utrans_ENTRY(status) NULL;
209  
210      if (trans == NULL) {
211          *status = U_ILLEGAL_ARGUMENT_ERROR;
212          return NULL;
213      }
214  
215      Transliterator *t = ((Transliterator*) trans)->clone();
216      if (t == NULL) {
217          *status = U_MEMORY_ALLOCATION_ERROR;
218      }
219      return (UTransliterator*) t;
220  }
221  
222  U_CAPI void U_EXPORT2
utrans_close(UTransliterator * trans)223  utrans_close(UTransliterator* trans) {
224      delete (Transliterator*) trans;
225  }
226  
227  U_CAPI const UChar * U_EXPORT2
utrans_getUnicodeID(const UTransliterator * trans,int32_t * resultLength)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  }
237  
238  U_CAPI int32_t U_EXPORT2
utrans_getID(const UTransliterator * trans,char * buf,int32_t bufCapacity)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  }
244  
245  U_CAPI void U_EXPORT2
utrans_register(UTransliterator * adoptedTrans,UErrorCode * status)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  }
252  
253  U_CAPI void U_EXPORT2
utrans_unregisterID(const UChar * id,int32_t idLength)254  utrans_unregisterID(const UChar* id, int32_t idLength) {
255      UnicodeString ID(idLength<0, id, idLength); // r-o alias
256      Transliterator::unregister(ID);
257  }
258  
259  U_CAPI void U_EXPORT2
utrans_unregister(const char * id)260  utrans_unregister(const char* id) {
261      UnicodeString ID(id, -1, US_INV); // use invariant converter
262      Transliterator::unregister(ID);
263  }
264  
265  U_CAPI void U_EXPORT2
utrans_setFilter(UTransliterator * trans,const UChar * filterPattern,int32_t filterPatternLen,UErrorCode * status)266  utrans_setFilter(UTransliterator* trans,
267                   const UChar* filterPattern,
268                   int32_t filterPatternLen,
269                   UErrorCode* status) {
270  
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  }
289  
290  U_CAPI int32_t U_EXPORT2
utrans_countAvailableIDs(void)291  utrans_countAvailableIDs(void) {
292      return Transliterator::countAvailableIDs();
293  }
294  
295  U_CAPI int32_t U_EXPORT2
utrans_getAvailableID(int32_t index,char * buf,int32_t bufCapacity)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  }
301  
302  /* Transliterator UEnumeration ---------------------------------------------- */
303  
304  typedef struct UTransEnumeration {
305      UEnumeration uenum;
306      int32_t index, count;
307  } UTransEnumeration;
308  
309  U_CDECL_BEGIN
310  static int32_t U_CALLCONV
utrans_enum_count(UEnumeration * uenum,UErrorCode * pErrorCode)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  }
317  
318  static const UChar* U_CALLCONV
utrans_enum_unext(UEnumeration * uenum,int32_t * resultLength,UErrorCode * pErrorCode)319  utrans_enum_unext(UEnumeration *uenum,
320                    int32_t* resultLength,
321                    UErrorCode *pErrorCode) {
322      if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
323          return 0;
324      }
325  
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      }
337  
338      if(resultLength!=NULL) {
339          *resultLength=0;
340      }
341      return NULL;
342  }
343  
344  static void U_CALLCONV
utrans_enum_reset(UEnumeration * uenum,UErrorCode * pErrorCode)345  utrans_enum_reset(UEnumeration *uenum, UErrorCode *pErrorCode) {
346      if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
347          return;
348      }
349  
350      UTransEnumeration *ute=(UTransEnumeration *)uenum;
351      ute->index=0;
352      ute->count=Transliterator::countAvailableIDs();
353  }
354  
355  static void U_CALLCONV
utrans_enum_close(UEnumeration * uenum)356  utrans_enum_close(UEnumeration *uenum) {
357      uprv_free(uenum);
358  }
359  U_CDECL_END
360  
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  };
370  
371  U_CAPI UEnumeration * U_EXPORT2
utrans_openIDs(UErrorCode * pErrorCode)372  utrans_openIDs(UErrorCode *pErrorCode) {
373      UTransEnumeration *ute;
374  
375      if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
376          return NULL;
377      }
378  
379      ute=(UTransEnumeration *)uprv_malloc(sizeof(UTransEnumeration));
380      if(ute==NULL) {
381          *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
382          return NULL;
383      }
384  
385      ute->uenum=utransEnumeration;
386      ute->index=0;
387      ute->count=Transliterator::countAvailableIDs();
388      return (UEnumeration *)ute;
389  }
390  
391  /********************************************************************
392   * Transliteration API
393   ********************************************************************/
394  
395  U_CAPI void U_EXPORT2
utrans_trans(const UTransliterator * trans,UReplaceable * rep,UReplaceableCallbacks * repFunc,int32_t start,int32_t * limit,UErrorCode * status)396  utrans_trans(const UTransliterator* trans,
397               UReplaceable* rep,
398               UReplaceableCallbacks* repFunc,
399               int32_t start,
400               int32_t* limit,
401               UErrorCode* status) {
402  
403      utrans_ENTRY(status);
404  
405      if (trans == 0 || rep == 0 || repFunc == 0 || limit == 0) {
406          *status = U_ILLEGAL_ARGUMENT_ERROR;
407          return;
408      }
409  
410      ReplaceableGlue r(rep, repFunc);
411  
412      *limit = ((Transliterator*) trans)->transliterate(r, start, *limit);
413  }
414  
415  U_CAPI void U_EXPORT2
utrans_transIncremental(const UTransliterator * trans,UReplaceable * rep,UReplaceableCallbacks * repFunc,UTransPosition * pos,UErrorCode * status)416  utrans_transIncremental(const UTransliterator* trans,
417                          UReplaceable* rep,
418                          UReplaceableCallbacks* repFunc,
419                          UTransPosition* pos,
420                          UErrorCode* status) {
421  
422      utrans_ENTRY(status);
423  
424      if (trans == 0 || rep == 0 || repFunc == 0 || pos == 0) {
425          *status = U_ILLEGAL_ARGUMENT_ERROR;
426          return;
427      }
428  
429      ReplaceableGlue r(rep, repFunc);
430  
431      ((Transliterator*) trans)->transliterate(r, *pos, *status);
432  }
433  
434  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)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) {
442  
443      utrans_ENTRY(status);
444  
445      if (trans == 0 || text == 0 || limit == 0) {
446          *status = U_ILLEGAL_ARGUMENT_ERROR;
447          return;
448      }
449  
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);
454  
455      *limit = ((Transliterator*) trans)->transliterate(str, start, *limit);
456  
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  }
464  
465  U_CAPI void U_EXPORT2
utrans_transIncrementalUChars(const UTransliterator * trans,UChar * text,int32_t * textLength,int32_t textCapacity,UTransPosition * pos,UErrorCode * status)466  utrans_transIncrementalUChars(const UTransliterator* trans,
467                                UChar* text,
468                                int32_t* textLength,
469                                int32_t textCapacity,
470                                UTransPosition* pos,
471                                UErrorCode* status) {
472  
473      utrans_ENTRY(status);
474  
475      if (trans == 0 || text == 0 || pos == 0) {
476          *status = U_ILLEGAL_ARGUMENT_ERROR;
477          return;
478      }
479  
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);
484  
485      ((Transliterator*) trans)->transliterate(str, *pos, *status);
486  
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  }
494  
495  #endif /* #if !UCONFIG_NO_TRANSLITERATION */
496