]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/utrans.cpp
ICU-551.51.4.tar.gz
[apple/icu.git] / icuSources / i18n / utrans.cpp
CommitLineData
b75a7d8f 1/*
374ca955 2 *******************************************************************************
57a6839d 3 * Copyright (C) 1997-2009,2014 International Business Machines
374ca955
A
4 * Corporation and others. All Rights Reserved.
5 *******************************************************************************
6 * Date Name Description
7 * 06/21/00 aliu Creation.
8 *******************************************************************************
9 */
b75a7d8f
A
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"
374ca955 22#include "unicode/uenum.h"
57a6839d 23#include "unicode/uset.h"
374ca955 24#include "uenumimp.h"
b75a7d8f
A
25#include "cpputils.h"
26#include "rbt.h"
27
28// Following macro is to be followed by <return value>';' or just ';'
29#define utrans_ENTRY(s) if ((s)==NULL || U_FAILURE(*(s))) return
30
31/********************************************************************
32 * Replaceable-UReplaceableCallbacks glue
33 ********************************************************************/
34
35/**
36 * Make a UReplaceable + UReplaceableCallbacks into a Replaceable object.
37 */
38U_NAMESPACE_BEGIN
39class ReplaceableGlue : public Replaceable {
40
41 UReplaceable *rep;
42 UReplaceableCallbacks *func;
43
b75a7d8f
A
44public:
45
46 ReplaceableGlue(UReplaceable *replaceable,
47 UReplaceableCallbacks *funcCallback);
48
49 virtual ~ReplaceableGlue();
50
51 virtual void handleReplaceBetween(int32_t start,
52 int32_t limit,
53 const UnicodeString& text);
54
55 virtual void extractBetween(int32_t start,
56 int32_t limit,
57 UnicodeString& target) const;
58
59 virtual void copy(int32_t start, int32_t limit, int32_t dest);
60
61 // virtual Replaceable *clone() const { return NULL; } same as default
62
63 /**
64 * ICU "poor man's RTTI", returns a UClassID for the actual class.
65 *
66 * @draft ICU 2.2
67 */
73c04bcf 68 virtual UClassID getDynamicClassID() const;
b75a7d8f
A
69
70 /**
71 * ICU "poor man's RTTI", returns a UClassID for this class.
72 *
73 * @draft ICU 2.2
74 */
73c04bcf 75 static UClassID U_EXPORT2 getStaticClassID();
b75a7d8f
A
76
77protected:
78
79 virtual int32_t getLength() const;
80
81 virtual UChar getCharAt(int32_t offset) const;
82
83 virtual UChar32 getChar32At(int32_t offset) const;
84};
85
374ca955 86UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue)
b75a7d8f
A
87
88ReplaceableGlue::ReplaceableGlue(UReplaceable *replaceable,
89 UReplaceableCallbacks *funcCallback)
90 : Replaceable()
91{
92 this->rep = replaceable;
93 this->func = funcCallback;
94}
95
96ReplaceableGlue::~ReplaceableGlue() {}
97
98int32_t ReplaceableGlue::getLength() const {
99 return (*func->length)(rep);
100}
101
102UChar ReplaceableGlue::getCharAt(int32_t offset) const {
103 return (*func->charAt)(rep, offset);
104}
105
106UChar32 ReplaceableGlue::getChar32At(int32_t offset) const {
107 return (*func->char32At)(rep, offset);
108}
109
110void ReplaceableGlue::handleReplaceBetween(int32_t start,
111 int32_t limit,
112 const UnicodeString& text) {
113 (*func->replace)(rep, start, limit, text.getBuffer(), text.length());
114}
115
116void ReplaceableGlue::extractBetween(int32_t start,
117 int32_t limit,
118 UnicodeString& target) const {
119 (*func->extract)(rep, start, limit, target.getBuffer(limit-start));
120 target.releaseBuffer(limit-start);
121}
122
123void ReplaceableGlue::copy(int32_t start, int32_t limit, int32_t dest) {
124 (*func->copy)(rep, start, limit, dest);
125}
126U_NAMESPACE_END
127/********************************************************************
128 * General API
129 ********************************************************************/
130U_NAMESPACE_USE
b75a7d8f 131
374ca955
A
132U_CAPI UTransliterator* U_EXPORT2
133utrans_openU(const UChar *id,
134 int32_t idLength,
135 UTransDirection dir,
136 const UChar *rules,
137 int32_t rulesLength,
138 UParseError *parseError,
139 UErrorCode *status) {
140 if(status==NULL || U_FAILURE(*status)) {
b75a7d8f
A
141 return NULL;
142 }
b75a7d8f
A
143 if (id == NULL) {
144 *status = U_ILLEGAL_ARGUMENT_ERROR;
145 return NULL;
146 }
147 UParseError temp;
148
149 if(parseError == NULL){
150 parseError = &temp;
151 }
152
374ca955 153 UnicodeString ID(idLength<0, id, idLength); // r-o alias
b75a7d8f
A
154
155 if(rules==NULL){
156
157 Transliterator *trans = NULL;
158
159 trans = Transliterator::createInstance(ID, dir, *parseError, *status);
160
161 if(U_FAILURE(*status)){
162 return NULL;
163 }
164 return (UTransliterator*) trans;
165 }else{
166 UnicodeString ruleStr(rulesLength < 0,
167 rules,
168 rulesLength); // r-o alias
169
729e4ab9
A
170 Transliterator *trans = NULL;
171 trans = Transliterator::createFromRules(ID, ruleStr, dir, *parseError, *status);
172 if(U_FAILURE(*status)) {
173 return NULL;
b75a7d8f 174 }
729e4ab9 175
b75a7d8f
A
176 return (UTransliterator*) trans;
177 }
178}
179
374ca955
A
180U_CAPI UTransliterator* U_EXPORT2
181utrans_open(const char* id,
182 UTransDirection dir,
183 const UChar* rules, /* may be Null */
184 int32_t rulesLength, /* -1 if null-terminated */
185 UParseError* parseError, /* may be Null */
186 UErrorCode* status) {
73c04bcf 187 UnicodeString ID(id, -1, US_INV); // use invariant converter
374ca955
A
188 return utrans_openU(ID.getBuffer(), ID.length(), dir,
189 rules, rulesLength,
190 parseError, status);
191}
192
b75a7d8f
A
193U_CAPI UTransliterator* U_EXPORT2
194utrans_openInverse(const UTransliterator* trans,
195 UErrorCode* status) {
196
197 utrans_ENTRY(status) NULL;
198
199 UTransliterator* result =
200 (UTransliterator*) ((Transliterator*) trans)->createInverse(*status);
201
202 return result;
203}
204
205U_CAPI UTransliterator* U_EXPORT2
206utrans_clone(const UTransliterator* trans,
207 UErrorCode* status) {
208
209 utrans_ENTRY(status) NULL;
210
211 if (trans == NULL) {
212 *status = U_ILLEGAL_ARGUMENT_ERROR;
213 return NULL;
214 }
215
216 Transliterator *t = ((Transliterator*) trans)->clone();
217 if (t == NULL) {
218 *status = U_MEMORY_ALLOCATION_ERROR;
219 }
220 return (UTransliterator*) t;
221}
222
223U_CAPI void U_EXPORT2
224utrans_close(UTransliterator* trans) {
225 delete (Transliterator*) trans;
226}
227
374ca955
A
228U_CAPI const UChar * U_EXPORT2
229utrans_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();
235 }
236 return ID.getBuffer();
237}
238
b75a7d8f
A
239U_CAPI int32_t U_EXPORT2
240utrans_getID(const UTransliterator* trans,
241 char* buf,
242 int32_t bufCapacity) {
73c04bcf 243 return ((Transliterator*) trans)->getID().extract(0, 0x7fffffff, buf, bufCapacity, US_INV);
b75a7d8f
A
244}
245
246U_CAPI void U_EXPORT2
247utrans_register(UTransliterator* adoptedTrans,
248 UErrorCode* status) {
249 utrans_ENTRY(status);
250 // status currently ignored; may remove later
251 Transliterator::registerInstance((Transliterator*) adoptedTrans);
252}
253
374ca955
A
254U_CAPI void U_EXPORT2
255utrans_unregisterID(const UChar* id, int32_t idLength) {
256 UnicodeString ID(idLength<0, id, idLength); // r-o alias
257 Transliterator::unregister(ID);
258}
259
b75a7d8f
A
260U_CAPI void U_EXPORT2
261utrans_unregister(const char* id) {
73c04bcf 262 UnicodeString ID(id, -1, US_INV); // use invariant converter
b75a7d8f
A
263 Transliterator::unregister(ID);
264}
265
266U_CAPI void U_EXPORT2
267utrans_setFilter(UTransliterator* trans,
268 const UChar* filterPattern,
269 int32_t filterPatternLen,
270 UErrorCode* status) {
271
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);
278 /* test for NULL */
279 if (filter == NULL) {
280 *status = U_MEMORY_ALLOCATION_ERROR;
281 return;
282 }
283 if (U_FAILURE(*status)) {
284 delete filter;
285 filter = NULL;
286 }
287 }
288 ((Transliterator*) trans)->adoptFilter(filter);
289}
290
291U_CAPI int32_t U_EXPORT2
292utrans_countAvailableIDs(void) {
293 return Transliterator::countAvailableIDs();
294}
295
296U_CAPI int32_t U_EXPORT2
297utrans_getAvailableID(int32_t index,
298 char* buf, // may be NULL
299 int32_t bufCapacity) {
73c04bcf 300 return Transliterator::getAvailableID(index).extract(0, 0x7fffffff, buf, bufCapacity, US_INV);
b75a7d8f
A
301}
302
374ca955
A
303/* Transliterator UEnumeration ---------------------------------------------- */
304
305typedef struct UTransEnumeration {
306 UEnumeration uenum;
307 int32_t index, count;
308} UTransEnumeration;
309
310U_CDECL_BEGIN
311static int32_t U_CALLCONV
312utrans_enum_count(UEnumeration *uenum, UErrorCode *pErrorCode) {
313 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
314 return 0;
315 }
316 return ((UTransEnumeration *)uenum)->count;
317}
318
319static const UChar* U_CALLCONV
320utrans_enum_unext(UEnumeration *uenum,
321 int32_t* resultLength,
322 UErrorCode *pErrorCode) {
323 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
324 return 0;
325 }
326
327 UTransEnumeration *ute=(UTransEnumeration *)uenum;
328 int32_t index=ute->index;
329 if(index<ute->count) {
330 const UnicodeString &ID=Transliterator::getAvailableID(index);
331 ute->index=index+1;
332 if(resultLength!=NULL) {
333 *resultLength=ID.length();
334 }
335 // Transliterator keeps its ID NUL-terminated
336 return ID.getBuffer();
337 }
338
339 if(resultLength!=NULL) {
340 *resultLength=0;
341 }
342 return NULL;
343}
344
345static void U_CALLCONV
346utrans_enum_reset(UEnumeration *uenum, UErrorCode *pErrorCode) {
347 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
348 return;
349 }
350
351 UTransEnumeration *ute=(UTransEnumeration *)uenum;
352 ute->index=0;
353 ute->count=Transliterator::countAvailableIDs();
354}
355
356static void U_CALLCONV
357utrans_enum_close(UEnumeration *uenum) {
358 uprv_free(uenum);
359}
360U_CDECL_END
361
362static const UEnumeration utransEnumeration={
363 NULL,
364 NULL,
365 utrans_enum_close,
366 utrans_enum_count,
367 utrans_enum_unext,
368 uenum_nextDefault,
369 utrans_enum_reset
370};
371
372U_CAPI UEnumeration * U_EXPORT2
373utrans_openIDs(UErrorCode *pErrorCode) {
374 UTransEnumeration *ute;
375
376 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
377 return NULL;
378 }
379
380 ute=(UTransEnumeration *)uprv_malloc(sizeof(UTransEnumeration));
381 if(ute==NULL) {
382 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
383 return NULL;
384 }
385
386 ute->uenum=utransEnumeration;
387 ute->index=0;
388 ute->count=Transliterator::countAvailableIDs();
389 return (UEnumeration *)ute;
390}
391
b75a7d8f
A
392/********************************************************************
393 * Transliteration API
394 ********************************************************************/
395
396U_CAPI void U_EXPORT2
397utrans_trans(const UTransliterator* trans,
398 UReplaceable* rep,
399 UReplaceableCallbacks* repFunc,
400 int32_t start,
401 int32_t* limit,
402 UErrorCode* status) {
403
404 utrans_ENTRY(status);
405
406 if (trans == 0 || rep == 0 || repFunc == 0 || limit == 0) {
407 *status = U_ILLEGAL_ARGUMENT_ERROR;
408 return;
409 }
410
411 ReplaceableGlue r(rep, repFunc);
412
413 *limit = ((Transliterator*) trans)->transliterate(r, start, *limit);
414}
415
416U_CAPI void U_EXPORT2
417utrans_transIncremental(const UTransliterator* trans,
418 UReplaceable* rep,
419 UReplaceableCallbacks* repFunc,
420 UTransPosition* pos,
421 UErrorCode* status) {
422
423 utrans_ENTRY(status);
424
425 if (trans == 0 || rep == 0 || repFunc == 0 || pos == 0) {
426 *status = U_ILLEGAL_ARGUMENT_ERROR;
427 return;
428 }
429
430 ReplaceableGlue r(rep, repFunc);
431
432 ((Transliterator*) trans)->transliterate(r, *pos, *status);
433}
434
435U_CAPI void U_EXPORT2
436utrans_transUChars(const UTransliterator* trans,
437 UChar* text,
438 int32_t* textLength,
439 int32_t textCapacity,
440 int32_t start,
441 int32_t* limit,
442 UErrorCode* status) {
443
444 utrans_ENTRY(status);
445
446 if (trans == 0 || text == 0 || limit == 0) {
447 *status = U_ILLEGAL_ARGUMENT_ERROR;
448 return;
449 }
450
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);
455
456 *limit = ((Transliterator*) trans)->transliterate(str, start, *limit);
457
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;
463 }
464}
465
466U_CAPI void U_EXPORT2
467utrans_transIncrementalUChars(const UTransliterator* trans,
468 UChar* text,
469 int32_t* textLength,
470 int32_t textCapacity,
471 UTransPosition* pos,
472 UErrorCode* status) {
473
474 utrans_ENTRY(status);
475
476 if (trans == 0 || text == 0 || pos == 0) {
477 *status = U_ILLEGAL_ARGUMENT_ERROR;
478 return;
479 }
480
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);
485
486 ((Transliterator*) trans)->transliterate(str, *pos, *status);
487
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;
493 }
494}
495
57a6839d
A
496U_CAPI int32_t U_EXPORT2
497utrans_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;
504 return 0;
505 }
506
507 UnicodeString res;
508 res.setTo(result, 0, resultLength);
509 ((Transliterator*) trans)->toRules(res, escapeUnprintable);
510 return res.extract(result, resultLength, *status);
511}
512
513U_CAPI USet* U_EXPORT2
514utrans_getSourceSet(const UTransliterator* trans,
515 UBool ignoreFilter,
516 USet* fillIn,
517 UErrorCode* status) {
518 utrans_ENTRY(status) fillIn;
519
520 if (fillIn == NULL) {
521 fillIn = uset_openEmpty();
522 }
523 if (ignoreFilter) {
524 ((Transliterator*) trans)->handleGetSourceSet(*((UnicodeSet*)fillIn));
525 } else {
526 ((Transliterator*) trans)->getSourceSet(*((UnicodeSet*)fillIn));
527 }
528 return fillIn;
529}
530
b75a7d8f 531#endif /* #if !UCONFIG_NO_TRANSLITERATION */