1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 1997-2009,2014 International Business Machines
6 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * Date Name Description
9 * 06/21/00 aliu Creation.
10 *******************************************************************************
13 #include "unicode/utypes.h"
15 #if !UCONFIG_NO_TRANSLITERATION
17 #include "unicode/utrans.h"
18 #include "unicode/putil.h"
19 #include "unicode/rep.h"
20 #include "unicode/translit.h"
21 #include "unicode/unifilt.h"
22 #include "unicode/uniset.h"
23 #include "unicode/ustring.h"
24 #include "unicode/uenum.h"
25 #include "unicode/uset.h"
30 // Following macro is to be followed by <return value>';' or just ';'
31 #define utrans_ENTRY(s) if ((s)==NULL || U_FAILURE(*(s))) return
33 /********************************************************************
34 * Replaceable-UReplaceableCallbacks glue
35 ********************************************************************/
38 * Make a UReplaceable + UReplaceableCallbacks into a Replaceable object.
41 class ReplaceableGlue : public Replaceable {
44 UReplaceableCallbacks *func;
48 ReplaceableGlue(UReplaceable *replaceable,
49 UReplaceableCallbacks *funcCallback);
51 virtual ~ReplaceableGlue();
53 virtual void handleReplaceBetween(int32_t start,
55 const UnicodeString& text);
57 virtual void extractBetween(int32_t start,
59 UnicodeString& target) const;
61 virtual void copy(int32_t start, int32_t limit, int32_t dest);
63 // virtual Replaceable *clone() const { return NULL; } same as default
66 * ICU "poor man's RTTI", returns a UClassID for the actual class.
70 virtual UClassID getDynamicClassID() const;
73 * ICU "poor man's RTTI", returns a UClassID for this class.
77 static UClassID U_EXPORT2 getStaticClassID();
81 virtual int32_t getLength() const;
83 virtual UChar getCharAt(int32_t offset) const;
85 virtual UChar32 getChar32At(int32_t offset) const;
88 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue)
90 ReplaceableGlue::ReplaceableGlue(UReplaceable *replaceable,
91 UReplaceableCallbacks *funcCallback)
94 this->rep = replaceable;
95 this->func = funcCallback;
98 ReplaceableGlue::~ReplaceableGlue() {}
100 int32_t ReplaceableGlue::getLength() const {
101 return (*func->length)(rep);
104 UChar ReplaceableGlue::getCharAt(int32_t offset) const {
105 return (*func->charAt)(rep, offset);
108 UChar32 ReplaceableGlue::getChar32At(int32_t offset) const {
109 return (*func->char32At)(rep, offset);
112 void ReplaceableGlue::handleReplaceBetween(int32_t start,
114 const UnicodeString& text) {
115 (*func->replace)(rep, start, limit, text.getBuffer(), text.length());
118 void ReplaceableGlue::extractBetween(int32_t start,
120 UnicodeString& target) const {
121 (*func->extract)(rep, start, limit, target.getBuffer(limit-start));
122 target.releaseBuffer(limit-start);
125 void ReplaceableGlue::copy(int32_t start, int32_t limit, int32_t dest) {
126 (*func->copy)(rep, start, limit, dest);
129 /********************************************************************
131 ********************************************************************/
134 U_CAPI UTransliterator* U_EXPORT2
135 utrans_openU(const UChar *id,
140 UParseError *parseError,
141 UErrorCode *status) {
142 if(status==NULL || U_FAILURE(*status)) {
146 *status = U_ILLEGAL_ARGUMENT_ERROR;
151 if(parseError == NULL){
155 UnicodeString ID(idLength<0, id, idLength); // r-o alias
159 Transliterator *trans = NULL;
161 trans = Transliterator::createInstance(ID, dir, *parseError, *status);
163 if(U_FAILURE(*status)){
166 return (UTransliterator*) trans;
168 UnicodeString ruleStr(rulesLength < 0,
170 rulesLength); // r-o alias
172 Transliterator *trans = NULL;
173 trans = Transliterator::createFromRules(ID, ruleStr, dir, *parseError, *status);
174 if(U_FAILURE(*status)) {
178 return (UTransliterator*) trans;
182 U_CAPI UTransliterator* U_EXPORT2
183 utrans_open(const char* id,
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,
195 U_CAPI UTransliterator* U_EXPORT2
196 utrans_openInverse(const UTransliterator* trans,
197 UErrorCode* status) {
199 utrans_ENTRY(status) NULL;
201 UTransliterator* result =
202 (UTransliterator*) ((Transliterator*) trans)->createInverse(*status);
207 U_CAPI UTransliterator* U_EXPORT2
208 utrans_clone(const UTransliterator* trans,
209 UErrorCode* status) {
211 utrans_ENTRY(status) NULL;
214 *status = U_ILLEGAL_ARGUMENT_ERROR;
218 Transliterator *t = ((Transliterator*) trans)->clone();
220 *status = U_MEMORY_ALLOCATION_ERROR;
222 return (UTransliterator*) t;
225 U_CAPI void U_EXPORT2
226 utrans_close(UTransliterator* trans) {
227 delete (Transliterator*) trans;
230 U_CAPI const UChar * U_EXPORT2
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();
238 return ID.getBuffer();
241 U_CAPI int32_t U_EXPORT2
242 utrans_getID(const UTransliterator* trans,
244 int32_t bufCapacity) {
245 return ((Transliterator*) trans)->getID().extract(0, 0x7fffffff, buf, bufCapacity, US_INV);
248 U_CAPI void U_EXPORT2
249 utrans_register(UTransliterator* adoptedTrans,
250 UErrorCode* status) {
251 utrans_ENTRY(status);
252 // status currently ignored; may remove later
253 Transliterator::registerInstance((Transliterator*) adoptedTrans);
256 U_CAPI void U_EXPORT2
257 utrans_unregisterID(const UChar* id, int32_t idLength) {
258 UnicodeString ID(idLength<0, id, idLength); // r-o alias
259 Transliterator::unregister(ID);
262 U_CAPI void U_EXPORT2
263 utrans_unregister(const char* id) {
264 UnicodeString ID(id, -1, US_INV); // use invariant converter
265 Transliterator::unregister(ID);
268 U_CAPI void U_EXPORT2
269 utrans_setFilter(UTransliterator* trans,
270 const UChar* filterPattern,
271 int32_t filterPatternLen,
272 UErrorCode* status) {
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);
281 if (filter == NULL) {
282 *status = U_MEMORY_ALLOCATION_ERROR;
285 if (U_FAILURE(*status)) {
290 ((Transliterator*) trans)->adoptFilter(filter);
293 U_CAPI int32_t U_EXPORT2
294 utrans_countAvailableIDs(void) {
295 return Transliterator::countAvailableIDs();
298 U_CAPI int32_t U_EXPORT2
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);
305 /* Transliterator UEnumeration ---------------------------------------------- */
307 typedef struct UTransEnumeration {
309 int32_t index, count;
313 static int32_t U_CALLCONV
314 utrans_enum_count(UEnumeration *uenum, UErrorCode *pErrorCode) {
315 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
318 return ((UTransEnumeration *)uenum)->count;
321 static const UChar* U_CALLCONV
322 utrans_enum_unext(UEnumeration *uenum,
323 int32_t* resultLength,
324 UErrorCode *pErrorCode) {
325 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
329 UTransEnumeration *ute=(UTransEnumeration *)uenum;
330 int32_t index=ute->index;
331 if(index<ute->count) {
332 const UnicodeString &ID=Transliterator::getAvailableID(index);
334 if(resultLength!=NULL) {
335 *resultLength=ID.length();
337 // Transliterator keeps its ID NUL-terminated
338 return ID.getBuffer();
341 if(resultLength!=NULL) {
347 static void U_CALLCONV
348 utrans_enum_reset(UEnumeration *uenum, UErrorCode *pErrorCode) {
349 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
353 UTransEnumeration *ute=(UTransEnumeration *)uenum;
355 ute->count=Transliterator::countAvailableIDs();
358 static void U_CALLCONV
359 utrans_enum_close(UEnumeration *uenum) {
364 static const UEnumeration utransEnumeration={
374 U_CAPI UEnumeration * U_EXPORT2
375 utrans_openIDs(UErrorCode *pErrorCode) {
376 UTransEnumeration *ute;
378 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
382 ute=(UTransEnumeration *)uprv_malloc(sizeof(UTransEnumeration));
384 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
388 ute->uenum=utransEnumeration;
390 ute->count=Transliterator::countAvailableIDs();
391 return (UEnumeration *)ute;
394 /********************************************************************
395 * Transliteration API
396 ********************************************************************/
398 U_CAPI void U_EXPORT2
399 utrans_trans(const UTransliterator* trans,
401 UReplaceableCallbacks* repFunc,
404 UErrorCode* status) {
406 utrans_ENTRY(status);
408 if (trans == 0 || rep == 0 || repFunc == 0 || limit == 0) {
409 *status = U_ILLEGAL_ARGUMENT_ERROR;
413 ReplaceableGlue r(rep, repFunc);
415 *limit = ((Transliterator*) trans)->transliterate(r, start, *limit);
418 U_CAPI void U_EXPORT2
419 utrans_transIncremental(const UTransliterator* trans,
421 UReplaceableCallbacks* repFunc,
423 UErrorCode* status) {
425 utrans_ENTRY(status);
427 if (trans == 0 || rep == 0 || repFunc == 0 || pos == 0) {
428 *status = U_ILLEGAL_ARGUMENT_ERROR;
432 ReplaceableGlue r(rep, repFunc);
434 ((Transliterator*) trans)->transliterate(r, *pos, *status);
437 U_CAPI void U_EXPORT2
438 utrans_transUChars(const UTransliterator* trans,
441 int32_t textCapacity,
444 UErrorCode* status) {
446 utrans_ENTRY(status);
448 if (trans == 0 || text == 0 || limit == 0) {
449 *status = U_ILLEGAL_ARGUMENT_ERROR;
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);
458 *limit = ((Transliterator*) trans)->transliterate(str, start, *limit);
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;
468 U_CAPI void U_EXPORT2
469 utrans_transIncrementalUChars(const UTransliterator* trans,
472 int32_t textCapacity,
474 UErrorCode* status) {
476 utrans_ENTRY(status);
478 if (trans == 0 || text == 0 || pos == 0) {
479 *status = U_ILLEGAL_ARGUMENT_ERROR;
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);
488 ((Transliterator*) trans)->transliterate(str, *pos, *status);
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;
498 U_CAPI int32_t U_EXPORT2
499 utrans_toRules( const UTransliterator* trans,
500 UBool escapeUnprintable,
501 UChar* result, int32_t resultLength,
502 UErrorCode* status) {
503 utrans_ENTRY(status) 0;
504 if ( (result==NULL)? resultLength!=0: resultLength<0 ) {
505 *status = U_ILLEGAL_ARGUMENT_ERROR;
510 res.setTo(result, 0, resultLength);
511 ((Transliterator*) trans)->toRules(res, escapeUnprintable);
512 return res.extract(result, resultLength, *status);
515 U_CAPI USet* U_EXPORT2
516 utrans_getSourceSet(const UTransliterator* trans,
519 UErrorCode* status) {
520 utrans_ENTRY(status) fillIn;
522 if (fillIn == NULL) {
523 fillIn = uset_openEmpty();
526 ((Transliterator*) trans)->handleGetSourceSet(*((UnicodeSet*)fillIn));
528 ((Transliterator*) trans)->getSourceSet(*((UnicodeSet*)fillIn));
533 #endif /* #if !UCONFIG_NO_TRANSLITERATION */