2 *******************************************************************************
3 * Copyright (C) 1997-2009,2014 International Business Machines
4 * Corporation and others. All Rights Reserved.
5 *******************************************************************************
6 * Date Name Description
7 * 06/21/00 aliu Creation.
8 *******************************************************************************
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 "unicode/uset.h"
28 // Following macro is to be followed by <return value>';' or just ';'
29 #define utrans_ENTRY(s) if ((s)==NULL || U_FAILURE(*(s))) return
31 /********************************************************************
32 * Replaceable-UReplaceableCallbacks glue
33 ********************************************************************/
36 * Make a UReplaceable + UReplaceableCallbacks into a Replaceable object.
39 class ReplaceableGlue
: public Replaceable
{
42 UReplaceableCallbacks
*func
;
46 ReplaceableGlue(UReplaceable
*replaceable
,
47 UReplaceableCallbacks
*funcCallback
);
49 virtual ~ReplaceableGlue();
51 virtual void handleReplaceBetween(int32_t start
,
53 const UnicodeString
& text
);
55 virtual void extractBetween(int32_t start
,
57 UnicodeString
& target
) const;
59 virtual void copy(int32_t start
, int32_t limit
, int32_t dest
);
61 // virtual Replaceable *clone() const { return NULL; } same as default
64 * ICU "poor man's RTTI", returns a UClassID for the actual class.
68 virtual UClassID
getDynamicClassID() const;
71 * ICU "poor man's RTTI", returns a UClassID for this class.
75 static UClassID U_EXPORT2
getStaticClassID();
79 virtual int32_t getLength() const;
81 virtual UChar
getCharAt(int32_t offset
) const;
83 virtual UChar32
getChar32At(int32_t offset
) const;
86 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue
)
88 ReplaceableGlue::ReplaceableGlue(UReplaceable
*replaceable
,
89 UReplaceableCallbacks
*funcCallback
)
92 this->rep
= replaceable
;
93 this->func
= funcCallback
;
96 ReplaceableGlue::~ReplaceableGlue() {}
98 int32_t ReplaceableGlue::getLength() const {
99 return (*func
->length
)(rep
);
102 UChar
ReplaceableGlue::getCharAt(int32_t offset
) const {
103 return (*func
->charAt
)(rep
, offset
);
106 UChar32
ReplaceableGlue::getChar32At(int32_t offset
) const {
107 return (*func
->char32At
)(rep
, offset
);
110 void ReplaceableGlue::handleReplaceBetween(int32_t start
,
112 const UnicodeString
& text
) {
113 (*func
->replace
)(rep
, start
, limit
, text
.getBuffer(), text
.length());
116 void ReplaceableGlue::extractBetween(int32_t start
,
118 UnicodeString
& target
) const {
119 (*func
->extract
)(rep
, start
, limit
, target
.getBuffer(limit
-start
));
120 target
.releaseBuffer(limit
-start
);
123 void ReplaceableGlue::copy(int32_t start
, int32_t limit
, int32_t dest
) {
124 (*func
->copy
)(rep
, start
, limit
, dest
);
127 /********************************************************************
129 ********************************************************************/
132 U_CAPI UTransliterator
* U_EXPORT2
133 utrans_openU(const UChar
*id
,
138 UParseError
*parseError
,
139 UErrorCode
*status
) {
140 if(status
==NULL
|| U_FAILURE(*status
)) {
144 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
149 if(parseError
== NULL
){
153 UnicodeString
ID(idLength
<0, id
, idLength
); // r-o alias
157 Transliterator
*trans
= NULL
;
159 trans
= Transliterator::createInstance(ID
, dir
, *parseError
, *status
);
161 if(U_FAILURE(*status
)){
164 return (UTransliterator
*) trans
;
166 UnicodeString
ruleStr(rulesLength
< 0,
168 rulesLength
); // r-o alias
170 Transliterator
*trans
= NULL
;
171 trans
= Transliterator::createFromRules(ID
, ruleStr
, dir
, *parseError
, *status
);
172 if(U_FAILURE(*status
)) {
176 return (UTransliterator
*) trans
;
180 U_CAPI UTransliterator
* U_EXPORT2
181 utrans_open(const char* id
,
183 const UChar
* rules
, /* may be Null */
184 int32_t rulesLength
, /* -1 if null-terminated */
185 UParseError
* parseError
, /* may be Null */
186 UErrorCode
* status
) {
187 UnicodeString
ID(id
, -1, US_INV
); // use invariant converter
188 return utrans_openU(ID
.getBuffer(), ID
.length(), dir
,
193 U_CAPI UTransliterator
* U_EXPORT2
194 utrans_openInverse(const UTransliterator
* trans
,
195 UErrorCode
* status
) {
197 utrans_ENTRY(status
) NULL
;
199 UTransliterator
* result
=
200 (UTransliterator
*) ((Transliterator
*) trans
)->createInverse(*status
);
205 U_CAPI UTransliterator
* U_EXPORT2
206 utrans_clone(const UTransliterator
* trans
,
207 UErrorCode
* status
) {
209 utrans_ENTRY(status
) NULL
;
212 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
216 Transliterator
*t
= ((Transliterator
*) trans
)->clone();
218 *status
= U_MEMORY_ALLOCATION_ERROR
;
220 return (UTransliterator
*) t
;
223 U_CAPI
void U_EXPORT2
224 utrans_close(UTransliterator
* trans
) {
225 delete (Transliterator
*) trans
;
228 U_CAPI
const UChar
* U_EXPORT2
229 utrans_getUnicodeID(const UTransliterator
*trans
,
230 int32_t *resultLength
) {
231 // Transliterator keeps its ID NUL-terminated
232 const UnicodeString
&ID
=((Transliterator
*) trans
)->getID();
233 if(resultLength
!=NULL
) {
234 *resultLength
=ID
.length();
236 return ID
.getBuffer();
239 U_CAPI
int32_t U_EXPORT2
240 utrans_getID(const UTransliterator
* trans
,
242 int32_t bufCapacity
) {
243 return ((Transliterator
*) trans
)->getID().extract(0, 0x7fffffff, buf
, bufCapacity
, US_INV
);
246 U_CAPI
void U_EXPORT2
247 utrans_register(UTransliterator
* adoptedTrans
,
248 UErrorCode
* status
) {
249 utrans_ENTRY(status
);
250 // status currently ignored; may remove later
251 Transliterator::registerInstance((Transliterator
*) adoptedTrans
);
254 U_CAPI
void U_EXPORT2
255 utrans_unregisterID(const UChar
* id
, int32_t idLength
) {
256 UnicodeString
ID(idLength
<0, id
, idLength
); // r-o alias
257 Transliterator::unregister(ID
);
260 U_CAPI
void U_EXPORT2
261 utrans_unregister(const char* id
) {
262 UnicodeString
ID(id
, -1, US_INV
); // use invariant converter
263 Transliterator::unregister(ID
);
266 U_CAPI
void U_EXPORT2
267 utrans_setFilter(UTransliterator
* trans
,
268 const UChar
* filterPattern
,
269 int32_t filterPatternLen
,
270 UErrorCode
* status
) {
272 utrans_ENTRY(status
);
273 UnicodeFilter
* filter
= NULL
;
274 if (filterPattern
!= NULL
&& *filterPattern
!= 0) {
275 // Create read only alias of filterPattern:
276 UnicodeString
pat(filterPatternLen
< 0, filterPattern
, filterPatternLen
);
277 filter
= new UnicodeSet(pat
, *status
);
279 if (filter
== NULL
) {
280 *status
= U_MEMORY_ALLOCATION_ERROR
;
283 if (U_FAILURE(*status
)) {
288 ((Transliterator
*) trans
)->adoptFilter(filter
);
291 U_CAPI
int32_t U_EXPORT2
292 utrans_countAvailableIDs(void) {
293 return Transliterator::countAvailableIDs();
296 U_CAPI
int32_t U_EXPORT2
297 utrans_getAvailableID(int32_t index
,
298 char* buf
, // may be NULL
299 int32_t bufCapacity
) {
300 return Transliterator::getAvailableID(index
).extract(0, 0x7fffffff, buf
, bufCapacity
, US_INV
);
303 /* Transliterator UEnumeration ---------------------------------------------- */
305 typedef struct UTransEnumeration
{
307 int32_t index
, count
;
311 static int32_t U_CALLCONV
312 utrans_enum_count(UEnumeration
*uenum
, UErrorCode
*pErrorCode
) {
313 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
316 return ((UTransEnumeration
*)uenum
)->count
;
319 static const UChar
* U_CALLCONV
320 utrans_enum_unext(UEnumeration
*uenum
,
321 int32_t* resultLength
,
322 UErrorCode
*pErrorCode
) {
323 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
327 UTransEnumeration
*ute
=(UTransEnumeration
*)uenum
;
328 int32_t index
=ute
->index
;
329 if(index
<ute
->count
) {
330 const UnicodeString
&ID
=Transliterator::getAvailableID(index
);
332 if(resultLength
!=NULL
) {
333 *resultLength
=ID
.length();
335 // Transliterator keeps its ID NUL-terminated
336 return ID
.getBuffer();
339 if(resultLength
!=NULL
) {
345 static void U_CALLCONV
346 utrans_enum_reset(UEnumeration
*uenum
, UErrorCode
*pErrorCode
) {
347 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
351 UTransEnumeration
*ute
=(UTransEnumeration
*)uenum
;
353 ute
->count
=Transliterator::countAvailableIDs();
356 static void U_CALLCONV
357 utrans_enum_close(UEnumeration
*uenum
) {
362 static const UEnumeration utransEnumeration
={
372 U_CAPI UEnumeration
* U_EXPORT2
373 utrans_openIDs(UErrorCode
*pErrorCode
) {
374 UTransEnumeration
*ute
;
376 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
380 ute
=(UTransEnumeration
*)uprv_malloc(sizeof(UTransEnumeration
));
382 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
386 ute
->uenum
=utransEnumeration
;
388 ute
->count
=Transliterator::countAvailableIDs();
389 return (UEnumeration
*)ute
;
392 /********************************************************************
393 * Transliteration API
394 ********************************************************************/
396 U_CAPI
void U_EXPORT2
397 utrans_trans(const UTransliterator
* trans
,
399 UReplaceableCallbacks
* repFunc
,
402 UErrorCode
* status
) {
404 utrans_ENTRY(status
);
406 if (trans
== 0 || rep
== 0 || repFunc
== 0 || limit
== 0) {
407 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
411 ReplaceableGlue
r(rep
, repFunc
);
413 *limit
= ((Transliterator
*) trans
)->transliterate(r
, start
, *limit
);
416 U_CAPI
void U_EXPORT2
417 utrans_transIncremental(const UTransliterator
* trans
,
419 UReplaceableCallbacks
* repFunc
,
421 UErrorCode
* status
) {
423 utrans_ENTRY(status
);
425 if (trans
== 0 || rep
== 0 || repFunc
== 0 || pos
== 0) {
426 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
430 ReplaceableGlue
r(rep
, repFunc
);
432 ((Transliterator
*) trans
)->transliterate(r
, *pos
, *status
);
435 U_CAPI
void U_EXPORT2
436 utrans_transUChars(const UTransliterator
* trans
,
439 int32_t textCapacity
,
442 UErrorCode
* status
) {
444 utrans_ENTRY(status
);
446 if (trans
== 0 || text
== 0 || limit
== 0) {
447 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
451 int32_t textLen
= (textLength
== NULL
|| *textLength
< 0)
452 ? u_strlen(text
) : *textLength
;
453 // writeable alias: for this ct, len CANNOT be -1 (why?)
454 UnicodeString
str(text
, textLen
, textCapacity
);
456 *limit
= ((Transliterator
*) trans
)->transliterate(str
, start
, *limit
);
458 // Copy the string buffer back to text (only if necessary)
459 // and fill in *neededCapacity (if neededCapacity != NULL).
460 textLen
= str
.extract(text
, textCapacity
, *status
);
461 if(textLength
!= NULL
) {
462 *textLength
= textLen
;
466 U_CAPI
void U_EXPORT2
467 utrans_transIncrementalUChars(const UTransliterator
* trans
,
470 int32_t textCapacity
,
472 UErrorCode
* status
) {
474 utrans_ENTRY(status
);
476 if (trans
== 0 || text
== 0 || pos
== 0) {
477 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
481 int32_t textLen
= (textLength
== NULL
|| *textLength
< 0)
482 ? u_strlen(text
) : *textLength
;
483 // writeable alias: for this ct, len CANNOT be -1 (why?)
484 UnicodeString
str(text
, textLen
, textCapacity
);
486 ((Transliterator
*) trans
)->transliterate(str
, *pos
, *status
);
488 // Copy the string buffer back to text (only if necessary)
489 // and fill in *neededCapacity (if neededCapacity != NULL).
490 textLen
= str
.extract(text
, textCapacity
, *status
);
491 if(textLength
!= NULL
) {
492 *textLength
= textLen
;
496 U_CAPI
int32_t U_EXPORT2
497 utrans_toRules( const UTransliterator
* trans
,
498 UBool escapeUnprintable
,
499 UChar
* result
, int32_t resultLength
,
500 UErrorCode
* status
) {
501 utrans_ENTRY(status
) 0;
502 if ( (result
==NULL
)? resultLength
!=0: resultLength
<0 ) {
503 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
508 res
.setTo(result
, 0, resultLength
);
509 ((Transliterator
*) trans
)->toRules(res
, escapeUnprintable
);
510 return res
.extract(result
, resultLength
, *status
);
513 U_CAPI USet
* U_EXPORT2
514 utrans_getSourceSet(const UTransliterator
* trans
,
517 UErrorCode
* status
) {
518 utrans_ENTRY(status
) fillIn
;
520 if (fillIn
== NULL
) {
521 fillIn
= uset_openEmpty();
524 ((Transliterator
*) trans
)->handleGetSourceSet(*((UnicodeSet
*)fillIn
));
526 ((Transliterator
*) trans
)->getSourceSet(*((UnicodeSet
*)fillIn
));
531 #endif /* #if !UCONFIG_NO_TRANSLITERATION */