intl/icu/source/i18n/utrans.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial