]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/utrans.cpp
ICU-461.13.tar.gz
[apple/icu.git] / icuSources / i18n / utrans.cpp
CommitLineData
b75a7d8f 1/*
374ca955 2 *******************************************************************************
729e4ab9 3 * Copyright (C) 1997-2009, 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
A
22#include "unicode/uenum.h"
23#include "uenumimp.h"
b75a7d8f
A
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 */
37U_NAMESPACE_BEGIN
38class ReplaceableGlue : public Replaceable {
39
40 UReplaceable *rep;
41 UReplaceableCallbacks *func;
42
b75a7d8f
A
43public:
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 */
73c04bcf 67 virtual UClassID getDynamicClassID() const;
b75a7d8f
A
68
69 /**
70 * ICU "poor man's RTTI", returns a UClassID for this class.
71 *
72 * @draft ICU 2.2
73 */
73c04bcf 74 static UClassID U_EXPORT2 getStaticClassID();
b75a7d8f
A
75
76protected:
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
374ca955 85UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue)
b75a7d8f
A
86
87ReplaceableGlue::ReplaceableGlue(UReplaceable *replaceable,
88 UReplaceableCallbacks *funcCallback)
89 : Replaceable()
90{
91 this->rep = replaceable;
92 this->func = funcCallback;
93}
94
95ReplaceableGlue::~ReplaceableGlue() {}
96
97int32_t ReplaceableGlue::getLength() const {
98 return (*func->length)(rep);
99}
100
101UChar ReplaceableGlue::getCharAt(int32_t offset) const {
102 return (*func->charAt)(rep, offset);
103}
104
105UChar32 ReplaceableGlue::getChar32At(int32_t offset) const {
106 return (*func->char32At)(rep, offset);
107}
108
109void 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
115void 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
122void ReplaceableGlue::copy(int32_t start, int32_t limit, int32_t dest) {
123 (*func->copy)(rep, start, limit, dest);
124}
125U_NAMESPACE_END
126/********************************************************************
127 * General API
128 ********************************************************************/
129U_NAMESPACE_USE
b75a7d8f 130
374ca955
A
131U_CAPI UTransliterator* U_EXPORT2
132utrans_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)) {
b75a7d8f
A
140 return NULL;
141 }
b75a7d8f
A
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
374ca955 152 UnicodeString ID(idLength<0, id, idLength); // r-o alias
b75a7d8f
A
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
729e4ab9
A
169 Transliterator *trans = NULL;
170 trans = Transliterator::createFromRules(ID, ruleStr, dir, *parseError, *status);
171 if(U_FAILURE(*status)) {
172 return NULL;
b75a7d8f 173 }
729e4ab9 174
b75a7d8f
A
175 return (UTransliterator*) trans;
176 }
177}
178
374ca955
A
179U_CAPI UTransliterator* U_EXPORT2
180utrans_open(const char* id,
181 UTransDirection dir,
182 const UChar* rules, /* may be Null */
183 int32_t rulesLength, /* -1 if null-terminated */
184 UParseError* parseError, /* may be Null */
185 UErrorCode* status) {
73c04bcf 186 UnicodeString ID(id, -1, US_INV); // use invariant converter
374ca955
A
187 return utrans_openU(ID.getBuffer(), ID.length(), dir,
188 rules, rulesLength,
189 parseError, status);
190}
191
b75a7d8f
A
192U_CAPI UTransliterator* U_EXPORT2
193utrans_openInverse(const UTransliterator* trans,
194 UErrorCode* status) {
195
196 utrans_ENTRY(status) NULL;
197
198 UTransliterator* result =
199 (UTransliterator*) ((Transliterator*) trans)->createInverse(*status);
200
201 return result;
202}
203
204U_CAPI UTransliterator* U_EXPORT2
205utrans_clone(const UTransliterator* trans,
206 UErrorCode* status) {
207
208 utrans_ENTRY(status) NULL;
209
210 if (trans == NULL) {
211 *status = U_ILLEGAL_ARGUMENT_ERROR;
212 return NULL;
213 }
214
215 Transliterator *t = ((Transliterator*) trans)->clone();
216 if (t == NULL) {
217 *status = U_MEMORY_ALLOCATION_ERROR;
218 }
219 return (UTransliterator*) t;
220}
221
222U_CAPI void U_EXPORT2
223utrans_close(UTransliterator* trans) {
224 delete (Transliterator*) trans;
225}
226
374ca955
A
227U_CAPI const UChar * U_EXPORT2
228utrans_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();
234 }
235 return ID.getBuffer();
236}
237
b75a7d8f
A
238U_CAPI int32_t U_EXPORT2
239utrans_getID(const UTransliterator* trans,
240 char* buf,
241 int32_t bufCapacity) {
73c04bcf 242 return ((Transliterator*) trans)->getID().extract(0, 0x7fffffff, buf, bufCapacity, US_INV);
b75a7d8f
A
243}
244
245U_CAPI void U_EXPORT2
246utrans_register(UTransliterator* adoptedTrans,
247 UErrorCode* status) {
248 utrans_ENTRY(status);
249 // status currently ignored; may remove later
250 Transliterator::registerInstance((Transliterator*) adoptedTrans);
251}
252
374ca955
A
253U_CAPI void U_EXPORT2
254utrans_unregisterID(const UChar* id, int32_t idLength) {
255 UnicodeString ID(idLength<0, id, idLength); // r-o alias
256 Transliterator::unregister(ID);
257}
258
b75a7d8f
A
259U_CAPI void U_EXPORT2
260utrans_unregister(const char* id) {
73c04bcf 261 UnicodeString ID(id, -1, US_INV); // use invariant converter
b75a7d8f
A
262 Transliterator::unregister(ID);
263}
264
265U_CAPI void U_EXPORT2
266utrans_setFilter(UTransliterator* trans,
267 const UChar* filterPattern,
268 int32_t filterPatternLen,
269 UErrorCode* status) {
270
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);
277 /* test for NULL */
278 if (filter == NULL) {
279 *status = U_MEMORY_ALLOCATION_ERROR;
280 return;
281 }
282 if (U_FAILURE(*status)) {
283 delete filter;
284 filter = NULL;
285 }
286 }
287 ((Transliterator*) trans)->adoptFilter(filter);
288}
289
290U_CAPI int32_t U_EXPORT2
291utrans_countAvailableIDs(void) {
292 return Transliterator::countAvailableIDs();
293}
294
295U_CAPI int32_t U_EXPORT2
296utrans_getAvailableID(int32_t index,
297 char* buf, // may be NULL
298 int32_t bufCapacity) {
73c04bcf 299 return Transliterator::getAvailableID(index).extract(0, 0x7fffffff, buf, bufCapacity, US_INV);
b75a7d8f
A
300}
301
374ca955
A
302/* Transliterator UEnumeration ---------------------------------------------- */
303
304typedef struct UTransEnumeration {
305 UEnumeration uenum;
306 int32_t index, count;
307} UTransEnumeration;
308
309U_CDECL_BEGIN
310static int32_t U_CALLCONV
311utrans_enum_count(UEnumeration *uenum, UErrorCode *pErrorCode) {
312 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
313 return 0;
314 }
315 return ((UTransEnumeration *)uenum)->count;
316}
317
318static const UChar* U_CALLCONV
319utrans_enum_unext(UEnumeration *uenum,
320 int32_t* resultLength,
321 UErrorCode *pErrorCode) {
322 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
323 return 0;
324 }
325
326 UTransEnumeration *ute=(UTransEnumeration *)uenum;
327 int32_t index=ute->index;
328 if(index<ute->count) {
329 const UnicodeString &ID=Transliterator::getAvailableID(index);
330 ute->index=index+1;
331 if(resultLength!=NULL) {
332 *resultLength=ID.length();
333 }
334 // Transliterator keeps its ID NUL-terminated
335 return ID.getBuffer();
336 }
337
338 if(resultLength!=NULL) {
339 *resultLength=0;
340 }
341 return NULL;
342}
343
344static void U_CALLCONV
345utrans_enum_reset(UEnumeration *uenum, UErrorCode *pErrorCode) {
346 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
347 return;
348 }
349
350 UTransEnumeration *ute=(UTransEnumeration *)uenum;
351 ute->index=0;
352 ute->count=Transliterator::countAvailableIDs();
353}
354
355static void U_CALLCONV
356utrans_enum_close(UEnumeration *uenum) {
357 uprv_free(uenum);
358}
359U_CDECL_END
360
361static const UEnumeration utransEnumeration={
362 NULL,
363 NULL,
364 utrans_enum_close,
365 utrans_enum_count,
366 utrans_enum_unext,
367 uenum_nextDefault,
368 utrans_enum_reset
369};
370
371U_CAPI UEnumeration * U_EXPORT2
372utrans_openIDs(UErrorCode *pErrorCode) {
373 UTransEnumeration *ute;
374
375 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
376 return NULL;
377 }
378
379 ute=(UTransEnumeration *)uprv_malloc(sizeof(UTransEnumeration));
380 if(ute==NULL) {
381 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
382 return NULL;
383 }
384
385 ute->uenum=utransEnumeration;
386 ute->index=0;
387 ute->count=Transliterator::countAvailableIDs();
388 return (UEnumeration *)ute;
389}
390
b75a7d8f
A
391/********************************************************************
392 * Transliteration API
393 ********************************************************************/
394
395U_CAPI void U_EXPORT2
396utrans_trans(const UTransliterator* trans,
397 UReplaceable* rep,
398 UReplaceableCallbacks* repFunc,
399 int32_t start,
400 int32_t* limit,
401 UErrorCode* status) {
402
403 utrans_ENTRY(status);
404
405 if (trans == 0 || rep == 0 || repFunc == 0 || limit == 0) {
406 *status = U_ILLEGAL_ARGUMENT_ERROR;
407 return;
408 }
409
410 ReplaceableGlue r(rep, repFunc);
411
412 *limit = ((Transliterator*) trans)->transliterate(r, start, *limit);
413}
414
415U_CAPI void U_EXPORT2
416utrans_transIncremental(const UTransliterator* trans,
417 UReplaceable* rep,
418 UReplaceableCallbacks* repFunc,
419 UTransPosition* pos,
420 UErrorCode* status) {
421
422 utrans_ENTRY(status);
423
424 if (trans == 0 || rep == 0 || repFunc == 0 || pos == 0) {
425 *status = U_ILLEGAL_ARGUMENT_ERROR;
426 return;
427 }
428
429 ReplaceableGlue r(rep, repFunc);
430
431 ((Transliterator*) trans)->transliterate(r, *pos, *status);
432}
433
434U_CAPI void U_EXPORT2
435utrans_transUChars(const UTransliterator* trans,
436 UChar* text,
437 int32_t* textLength,
438 int32_t textCapacity,
439 int32_t start,
440 int32_t* limit,
441 UErrorCode* status) {
442
443 utrans_ENTRY(status);
444
445 if (trans == 0 || text == 0 || limit == 0) {
446 *status = U_ILLEGAL_ARGUMENT_ERROR;
447 return;
448 }
449
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);
454
455 *limit = ((Transliterator*) trans)->transliterate(str, start, *limit);
456
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;
462 }
463}
464
465U_CAPI void U_EXPORT2
466utrans_transIncrementalUChars(const UTransliterator* trans,
467 UChar* text,
468 int32_t* textLength,
469 int32_t textCapacity,
470 UTransPosition* pos,
471 UErrorCode* status) {
472
473 utrans_ENTRY(status);
474
475 if (trans == 0 || text == 0 || pos == 0) {
476 *status = U_ILLEGAL_ARGUMENT_ERROR;
477 return;
478 }
479
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);
484
485 ((Transliterator*) trans)->transliterate(str, *pos, *status);
486
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;
492 }
493}
494
495#endif /* #if !UCONFIG_NO_TRANSLITERATION */