• 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