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 *******************************************************************************
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"
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 ********************************************************************/
35 * Make a UReplaceable + UReplaceableCallbacks into a Replaceable object.
38 class ReplaceableGlue
: public Replaceable
{
41 UReplaceableCallbacks
*func
;
45 ReplaceableGlue(UReplaceable
*replaceable
,
46 UReplaceableCallbacks
*funcCallback
);
48 virtual ~ReplaceableGlue();
50 virtual void handleReplaceBetween(int32_t start
,
52 const UnicodeString
& text
);
54 virtual void extractBetween(int32_t start
,
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
63 * ICU "poor man's RTTI", returns a UClassID for the actual class.
67 virtual UClassID
getDynamicClassID() const;
70 * ICU "poor man's RTTI", returns a UClassID for this class.
74 static UClassID U_EXPORT2
getStaticClassID();
78 virtual int32_t getLength() const;
80 virtual UChar
getCharAt(int32_t offset
) const;
82 virtual UChar32
getChar32At(int32_t offset
) const;
85 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue
)
87 ReplaceableGlue::ReplaceableGlue(UReplaceable
*replaceable
,
88 UReplaceableCallbacks
*funcCallback
)
91 this->rep
= replaceable
;
92 this->func
= funcCallback
;
95 ReplaceableGlue::~ReplaceableGlue() {}
97 int32_t ReplaceableGlue::getLength() const {
98 return (*func
->length
)(rep
);
101 UChar
ReplaceableGlue::getCharAt(int32_t offset
) const {
102 return (*func
->charAt
)(rep
, offset
);
105 UChar32
ReplaceableGlue::getChar32At(int32_t offset
) const {
106 return (*func
->char32At
)(rep
, offset
);
109 void ReplaceableGlue::handleReplaceBetween(int32_t start
,
111 const UnicodeString
& text
) {
112 (*func
->replace
)(rep
, start
, limit
, text
.getBuffer(), text
.length());
115 void ReplaceableGlue::extractBetween(int32_t start
,
117 UnicodeString
& target
) const {
118 (*func
->extract
)(rep
, start
, limit
, target
.getBuffer(limit
-start
));
119 target
.releaseBuffer(limit
-start
);
122 void ReplaceableGlue::copy(int32_t start
, int32_t limit
, int32_t dest
) {
123 (*func
->copy
)(rep
, start
, limit
, dest
);
126 /********************************************************************
128 ********************************************************************/
131 U_CAPI UTransliterator
* U_EXPORT2
132 utrans_openU(const UChar
*id
,
137 UParseError
*parseError
,
138 UErrorCode
*status
) {
139 if(status
==NULL
|| U_FAILURE(*status
)) {
143 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
148 if(parseError
== NULL
){
152 UnicodeString
ID(idLength
<0, id
, idLength
); // r-o alias
156 Transliterator
*trans
= NULL
;
158 trans
= Transliterator::createInstance(ID
, dir
, *parseError
, *status
);
160 if(U_FAILURE(*status
)){
163 return (UTransliterator
*) trans
;
165 UnicodeString
ruleStr(rulesLength
< 0,
167 rulesLength
); // r-o alias
169 Transliterator
*trans
= NULL
;
170 trans
= Transliterator::createFromRules(ID
, ruleStr
, dir
, *parseError
, *status
);
171 if(U_FAILURE(*status
)) {
175 return (UTransliterator
*) trans
;
179 U_CAPI UTransliterator
* U_EXPORT2
180 utrans_open(const char* id
,
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
,
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
);
204 U_CAPI UTransliterator
* U_EXPORT2
205 utrans_clone(const UTransliterator
* trans
,
206 UErrorCode
* status
) {
208 utrans_ENTRY(status
) NULL
;
211 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
215 Transliterator
*t
= ((Transliterator
*) trans
)->clone();
217 *status
= U_MEMORY_ALLOCATION_ERROR
;
219 return (UTransliterator
*) t
;
222 U_CAPI
void U_EXPORT2
223 utrans_close(UTransliterator
* trans
) {
224 delete (Transliterator
*) trans
;
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();
235 return ID
.getBuffer();
238 U_CAPI
int32_t U_EXPORT2
239 utrans_getID(const UTransliterator
* trans
,
241 int32_t bufCapacity
) {
242 return ((Transliterator
*) trans
)->getID().extract(0, 0x7fffffff, buf
, bufCapacity
, US_INV
);
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
);
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
);
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
);
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
);
278 if (filter
== NULL
) {
279 *status
= U_MEMORY_ALLOCATION_ERROR
;
282 if (U_FAILURE(*status
)) {
287 ((Transliterator
*) trans
)->adoptFilter(filter
);
290 U_CAPI
int32_t U_EXPORT2
291 utrans_countAvailableIDs(void) {
292 return Transliterator::countAvailableIDs();
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
);
302 /* Transliterator UEnumeration ---------------------------------------------- */
304 typedef struct UTransEnumeration
{
306 int32_t index
, count
;
310 static int32_t U_CALLCONV
311 utrans_enum_count(UEnumeration
*uenum
, UErrorCode
*pErrorCode
) {
312 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
315 return ((UTransEnumeration
*)uenum
)->count
;
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
)) {
326 UTransEnumeration
*ute
=(UTransEnumeration
*)uenum
;
327 int32_t index
=ute
->index
;
328 if(index
<ute
->count
) {
329 const UnicodeString
&ID
=Transliterator::getAvailableID(index
);
331 if(resultLength
!=NULL
) {
332 *resultLength
=ID
.length();
334 // Transliterator keeps its ID NUL-terminated
335 return ID
.getBuffer();
338 if(resultLength
!=NULL
) {
344 static void U_CALLCONV
345 utrans_enum_reset(UEnumeration
*uenum
, UErrorCode
*pErrorCode
) {
346 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
350 UTransEnumeration
*ute
=(UTransEnumeration
*)uenum
;
352 ute
->count
=Transliterator::countAvailableIDs();
355 static void U_CALLCONV
356 utrans_enum_close(UEnumeration
*uenum
) {
361 static const UEnumeration utransEnumeration
={
371 U_CAPI UEnumeration
* U_EXPORT2
372 utrans_openIDs(UErrorCode
*pErrorCode
) {
373 UTransEnumeration
*ute
;
375 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
379 ute
=(UTransEnumeration
*)uprv_malloc(sizeof(UTransEnumeration
));
381 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
385 ute
->uenum
=utransEnumeration
;
387 ute
->count
=Transliterator::countAvailableIDs();
388 return (UEnumeration
*)ute
;
391 /********************************************************************
392 * Transliteration API
393 ********************************************************************/
395 U_CAPI
void U_EXPORT2
396 utrans_trans(const UTransliterator
* trans
,
398 UReplaceableCallbacks
* repFunc
,
401 UErrorCode
* status
) {
403 utrans_ENTRY(status
);
405 if (trans
== 0 || rep
== 0 || repFunc
== 0 || limit
== 0) {
406 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
410 ReplaceableGlue
r(rep
, repFunc
);
412 *limit
= ((Transliterator
*) trans
)->transliterate(r
, start
, *limit
);
415 U_CAPI
void U_EXPORT2
416 utrans_transIncremental(const UTransliterator
* trans
,
418 UReplaceableCallbacks
* repFunc
,
420 UErrorCode
* status
) {
422 utrans_ENTRY(status
);
424 if (trans
== 0 || rep
== 0 || repFunc
== 0 || pos
== 0) {
425 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
429 ReplaceableGlue
r(rep
, repFunc
);
431 ((Transliterator
*) trans
)->transliterate(r
, *pos
, *status
);
434 U_CAPI
void U_EXPORT2
435 utrans_transUChars(const UTransliterator
* trans
,
438 int32_t textCapacity
,
441 UErrorCode
* status
) {
443 utrans_ENTRY(status
);
445 if (trans
== 0 || text
== 0 || limit
== 0) {
446 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
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
;
465 U_CAPI
void U_EXPORT2
466 utrans_transIncrementalUChars(const UTransliterator
* trans
,
469 int32_t textCapacity
,
471 UErrorCode
* status
) {
473 utrans_ENTRY(status
);
475 if (trans
== 0 || text
== 0 || pos
== 0) {
476 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
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
;
495 #endif /* #if !UCONFIG_NO_TRANSLITERATION */