1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2005, 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 RuleBasedTransliterator *trans = NULL;
170 trans = new RuleBasedTransliterator(ID, ruleStr, dir,
171 NULL, *parseError, *status);
172 if (trans == NULL) {
173 *status = U_MEMORY_ALLOCATION_ERROR;
174 } else if (U_FAILURE(*status)) {
175 delete trans;
176 trans = NULL;
177 }
178 return (UTransliterator*) trans;
179 }
180 }
181
182 U_CAPI UTransliterator* U_EXPORT2
utrans_open(const char * id,UTransDirection dir,const UChar * rules,int32_t rulesLength,UParseError * parseError,UErrorCode * status)183 utrans_open(const char* id,
184 UTransDirection dir,
185 const UChar* rules, /* may be Null */
186 int32_t rulesLength, /* -1 if null-terminated */
187 UParseError* parseError, /* may be Null */
188 UErrorCode* status) {
189 UnicodeString ID(id, -1, US_INV); // use invariant converter
190 return utrans_openU(ID.getBuffer(), ID.length(), dir,
191 rules, rulesLength,
192 parseError, status);
193 }
194
195 U_CAPI UTransliterator* U_EXPORT2
utrans_openInverse(const UTransliterator * trans,UErrorCode * status)196 utrans_openInverse(const UTransliterator* trans,
197 UErrorCode* status) {
198
199 utrans_ENTRY(status) NULL;
200
201 UTransliterator* result =
202 (UTransliterator*) ((Transliterator*) trans)->createInverse(*status);
203
204 return result;
205 }
206
207 U_CAPI UTransliterator* U_EXPORT2
utrans_clone(const UTransliterator * trans,UErrorCode * status)208 utrans_clone(const UTransliterator* trans,
209 UErrorCode* status) {
210
211 utrans_ENTRY(status) NULL;
212
213 if (trans == NULL) {
214 *status = U_ILLEGAL_ARGUMENT_ERROR;
215 return NULL;
216 }
217
218 Transliterator *t = ((Transliterator*) trans)->clone();
219 if (t == NULL) {
220 *status = U_MEMORY_ALLOCATION_ERROR;
221 }
222 return (UTransliterator*) t;
223 }
224
225 U_CAPI void U_EXPORT2
utrans_close(UTransliterator * trans)226 utrans_close(UTransliterator* trans) {
227 delete (Transliterator*) trans;
228 }
229
230 U_CAPI const UChar * U_EXPORT2
utrans_getUnicodeID(const UTransliterator * trans,int32_t * resultLength)231 utrans_getUnicodeID(const UTransliterator *trans,
232 int32_t *resultLength) {
233 // Transliterator keeps its ID NUL-terminated
234 const UnicodeString &ID=((Transliterator*) trans)->getID();
235 if(resultLength!=NULL) {
236 *resultLength=ID.length();
237 }
238 return ID.getBuffer();
239 }
240
241 U_CAPI int32_t U_EXPORT2
utrans_getID(const UTransliterator * trans,char * buf,int32_t bufCapacity)242 utrans_getID(const UTransliterator* trans,
243 char* buf,
244 int32_t bufCapacity) {
245 return ((Transliterator*) trans)->getID().extract(0, 0x7fffffff, buf, bufCapacity, US_INV);
246 }
247
248 U_CAPI void U_EXPORT2
utrans_register(UTransliterator * adoptedTrans,UErrorCode * status)249 utrans_register(UTransliterator* adoptedTrans,
250 UErrorCode* status) {
251 utrans_ENTRY(status);
252 // status currently ignored; may remove later
253 Transliterator::registerInstance((Transliterator*) adoptedTrans);
254 }
255
256 U_CAPI void U_EXPORT2
utrans_unregisterID(const UChar * id,int32_t idLength)257 utrans_unregisterID(const UChar* id, int32_t idLength) {
258 UnicodeString ID(idLength<0, id, idLength); // r-o alias
259 Transliterator::unregister(ID);
260 }
261
262 U_CAPI void U_EXPORT2
utrans_unregister(const char * id)263 utrans_unregister(const char* id) {
264 UnicodeString ID(id, -1, US_INV); // use invariant converter
265 Transliterator::unregister(ID);
266 }
267
268 U_CAPI void U_EXPORT2
utrans_setFilter(UTransliterator * trans,const UChar * filterPattern,int32_t filterPatternLen,UErrorCode * status)269 utrans_setFilter(UTransliterator* trans,
270 const UChar* filterPattern,
271 int32_t filterPatternLen,
272 UErrorCode* status) {
273
274 utrans_ENTRY(status);
275 UnicodeFilter* filter = NULL;
276 if (filterPattern != NULL && *filterPattern != 0) {
277 // Create read only alias of filterPattern:
278 UnicodeString pat(filterPatternLen < 0, filterPattern, filterPatternLen);
279 filter = new UnicodeSet(pat, *status);
280 /* test for NULL */
281 if (filter == NULL) {
282 *status = U_MEMORY_ALLOCATION_ERROR;
283 return;
284 }
285 if (U_FAILURE(*status)) {
286 delete filter;
287 filter = NULL;
288 }
289 }
290 ((Transliterator*) trans)->adoptFilter(filter);
291 }
292
293 U_CAPI int32_t U_EXPORT2
utrans_countAvailableIDs(void)294 utrans_countAvailableIDs(void) {
295 return Transliterator::countAvailableIDs();
296 }
297
298 U_CAPI int32_t U_EXPORT2
utrans_getAvailableID(int32_t index,char * buf,int32_t bufCapacity)299 utrans_getAvailableID(int32_t index,
300 char* buf, // may be NULL
301 int32_t bufCapacity) {
302 return Transliterator::getAvailableID(index).extract(0, 0x7fffffff, buf, bufCapacity, US_INV);
303 }
304
305 /* Transliterator UEnumeration ---------------------------------------------- */
306
307 typedef struct UTransEnumeration {
308 UEnumeration uenum;
309 int32_t index, count;
310 } UTransEnumeration;
311
312 U_CDECL_BEGIN
313 static int32_t U_CALLCONV
utrans_enum_count(UEnumeration * uenum,UErrorCode * pErrorCode)314 utrans_enum_count(UEnumeration *uenum, UErrorCode *pErrorCode) {
315 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
316 return 0;
317 }
318 return ((UTransEnumeration *)uenum)->count;
319 }
320
321 static const UChar* U_CALLCONV
utrans_enum_unext(UEnumeration * uenum,int32_t * resultLength,UErrorCode * pErrorCode)322 utrans_enum_unext(UEnumeration *uenum,
323 int32_t* resultLength,
324 UErrorCode *pErrorCode) {
325 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
326 return 0;
327 }
328
329 UTransEnumeration *ute=(UTransEnumeration *)uenum;
330 int32_t index=ute->index;
331 if(index<ute->count) {
332 const UnicodeString &ID=Transliterator::getAvailableID(index);
333 ute->index=index+1;
334 if(resultLength!=NULL) {
335 *resultLength=ID.length();
336 }
337 // Transliterator keeps its ID NUL-terminated
338 return ID.getBuffer();
339 }
340
341 if(resultLength!=NULL) {
342 *resultLength=0;
343 }
344 return NULL;
345 }
346
347 static void U_CALLCONV
utrans_enum_reset(UEnumeration * uenum,UErrorCode * pErrorCode)348 utrans_enum_reset(UEnumeration *uenum, UErrorCode *pErrorCode) {
349 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
350 return;
351 }
352
353 UTransEnumeration *ute=(UTransEnumeration *)uenum;
354 ute->index=0;
355 ute->count=Transliterator::countAvailableIDs();
356 }
357
358 static void U_CALLCONV
utrans_enum_close(UEnumeration * uenum)359 utrans_enum_close(UEnumeration *uenum) {
360 uprv_free(uenum);
361 }
362 U_CDECL_END
363
364 static const UEnumeration utransEnumeration={
365 NULL,
366 NULL,
367 utrans_enum_close,
368 utrans_enum_count,
369 utrans_enum_unext,
370 uenum_nextDefault,
371 utrans_enum_reset
372 };
373
374 U_CAPI UEnumeration * U_EXPORT2
utrans_openIDs(UErrorCode * pErrorCode)375 utrans_openIDs(UErrorCode *pErrorCode) {
376 UTransEnumeration *ute;
377
378 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
379 return NULL;
380 }
381
382 ute=(UTransEnumeration *)uprv_malloc(sizeof(UTransEnumeration));
383 if(ute==NULL) {
384 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
385 return NULL;
386 }
387
388 ute->uenum=utransEnumeration;
389 ute->index=0;
390 ute->count=Transliterator::countAvailableIDs();
391 return (UEnumeration *)ute;
392 }
393
394 /********************************************************************
395 * Transliteration API
396 ********************************************************************/
397
398 U_CAPI void U_EXPORT2
utrans_trans(const UTransliterator * trans,UReplaceable * rep,UReplaceableCallbacks * repFunc,int32_t start,int32_t * limit,UErrorCode * status)399 utrans_trans(const UTransliterator* trans,
400 UReplaceable* rep,
401 UReplaceableCallbacks* repFunc,
402 int32_t start,
403 int32_t* limit,
404 UErrorCode* status) {
405
406 utrans_ENTRY(status);
407
408 if (trans == 0 || rep == 0 || repFunc == 0 || limit == 0) {
409 *status = U_ILLEGAL_ARGUMENT_ERROR;
410 return;
411 }
412
413 ReplaceableGlue r(rep, repFunc);
414
415 *limit = ((Transliterator*) trans)->transliterate(r, start, *limit);
416 }
417
418 U_CAPI void U_EXPORT2
utrans_transIncremental(const UTransliterator * trans,UReplaceable * rep,UReplaceableCallbacks * repFunc,UTransPosition * pos,UErrorCode * status)419 utrans_transIncremental(const UTransliterator* trans,
420 UReplaceable* rep,
421 UReplaceableCallbacks* repFunc,
422 UTransPosition* pos,
423 UErrorCode* status) {
424
425 utrans_ENTRY(status);
426
427 if (trans == 0 || rep == 0 || repFunc == 0 || pos == 0) {
428 *status = U_ILLEGAL_ARGUMENT_ERROR;
429 return;
430 }
431
432 ReplaceableGlue r(rep, repFunc);
433
434 ((Transliterator*) trans)->transliterate(r, *pos, *status);
435 }
436
437 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)438 utrans_transUChars(const UTransliterator* trans,
439 UChar* text,
440 int32_t* textLength,
441 int32_t textCapacity,
442 int32_t start,
443 int32_t* limit,
444 UErrorCode* status) {
445
446 utrans_ENTRY(status);
447
448 if (trans == 0 || text == 0 || limit == 0) {
449 *status = U_ILLEGAL_ARGUMENT_ERROR;
450 return;
451 }
452
453 int32_t textLen = (textLength == NULL || *textLength < 0)
454 ? u_strlen(text) : *textLength;
455 // writeable alias: for this ct, len CANNOT be -1 (why?)
456 UnicodeString str(text, textLen, textCapacity);
457
458 *limit = ((Transliterator*) trans)->transliterate(str, start, *limit);
459
460 // Copy the string buffer back to text (only if necessary)
461 // and fill in *neededCapacity (if neededCapacity != NULL).
462 textLen = str.extract(text, textCapacity, *status);
463 if(textLength != NULL) {
464 *textLength = textLen;
465 }
466 }
467
468 U_CAPI void U_EXPORT2
utrans_transIncrementalUChars(const UTransliterator * trans,UChar * text,int32_t * textLength,int32_t textCapacity,UTransPosition * pos,UErrorCode * status)469 utrans_transIncrementalUChars(const UTransliterator* trans,
470 UChar* text,
471 int32_t* textLength,
472 int32_t textCapacity,
473 UTransPosition* pos,
474 UErrorCode* status) {
475
476 utrans_ENTRY(status);
477
478 if (trans == 0 || text == 0 || pos == 0) {
479 *status = U_ILLEGAL_ARGUMENT_ERROR;
480 return;
481 }
482
483 int32_t textLen = (textLength == NULL || *textLength < 0)
484 ? u_strlen(text) : *textLength;
485 // writeable alias: for this ct, len CANNOT be -1 (why?)
486 UnicodeString str(text, textLen, textCapacity);
487
488 ((Transliterator*) trans)->transliterate(str, *pos, *status);
489
490 // Copy the string buffer back to text (only if necessary)
491 // and fill in *neededCapacity (if neededCapacity != NULL).
492 textLen = str.extract(text, textCapacity, *status);
493 if(textLength != NULL) {
494 *textLength = textLen;
495 }
496 }
497
498 #endif /* #if !UCONFIG_NO_TRANSLITERATION */
499