OLD | NEW |
(Empty) | |
| 1 /* |
| 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 ******************************************************************************* |
| 9 */ |
| 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" |
| 22 #include "unicode/uenum.h" |
| 23 #include "uenumimp.h" |
| 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 */ |
| 37 U_NAMESPACE_BEGIN |
| 38 class ReplaceableGlue : public Replaceable { |
| 39 |
| 40 UReplaceable *rep; |
| 41 UReplaceableCallbacks *func; |
| 42 |
| 43 public: |
| 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 */ |
| 67 virtual UClassID getDynamicClassID() const; |
| 68 |
| 69 /** |
| 70 * ICU "poor man's RTTI", returns a UClassID for this class. |
| 71 * |
| 72 * @draft ICU 2.2 |
| 73 */ |
| 74 static UClassID U_EXPORT2 getStaticClassID(); |
| 75 |
| 76 protected: |
| 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 |
| 85 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue) |
| 86 |
| 87 ReplaceableGlue::ReplaceableGlue(UReplaceable *replaceable, |
| 88 UReplaceableCallbacks *funcCallback) |
| 89 : Replaceable() |
| 90 { |
| 91 this->rep = replaceable; |
| 92 this->func = funcCallback; |
| 93 } |
| 94 |
| 95 ReplaceableGlue::~ReplaceableGlue() {} |
| 96 |
| 97 int32_t ReplaceableGlue::getLength() const { |
| 98 return (*func->length)(rep); |
| 99 } |
| 100 |
| 101 UChar ReplaceableGlue::getCharAt(int32_t offset) const { |
| 102 return (*func->charAt)(rep, offset); |
| 103 } |
| 104 |
| 105 UChar32 ReplaceableGlue::getChar32At(int32_t offset) const { |
| 106 return (*func->char32At)(rep, offset); |
| 107 } |
| 108 |
| 109 void 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 |
| 115 void 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 |
| 122 void ReplaceableGlue::copy(int32_t start, int32_t limit, int32_t dest) { |
| 123 (*func->copy)(rep, start, limit, dest); |
| 124 } |
| 125 U_NAMESPACE_END |
| 126 /******************************************************************** |
| 127 * General API |
| 128 ********************************************************************/ |
| 129 U_NAMESPACE_USE |
| 130 |
| 131 U_CAPI UTransliterator* U_EXPORT2 |
| 132 utrans_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)) { |
| 140 return NULL; |
| 141 } |
| 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 |
| 152 UnicodeString ID(idLength<0, id, idLength); // r-o alias |
| 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 |
| 169 Transliterator *trans = NULL; |
| 170 trans = Transliterator::createFromRules(ID, ruleStr, dir, *parseError, *
status); |
| 171 if(U_FAILURE(*status)) { |
| 172 return NULL; |
| 173 } |
| 174 |
| 175 return (UTransliterator*) trans; |
| 176 } |
| 177 } |
| 178 |
| 179 U_CAPI UTransliterator* U_EXPORT2 |
| 180 utrans_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) { |
| 186 UnicodeString ID(id, -1, US_INV); // use invariant converter |
| 187 return utrans_openU(ID.getBuffer(), ID.length(), dir, |
| 188 rules, rulesLength, |
| 189 parseError, status); |
| 190 } |
| 191 |
| 192 U_CAPI UTransliterator* U_EXPORT2 |
| 193 utrans_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 |
| 204 U_CAPI UTransliterator* U_EXPORT2 |
| 205 utrans_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 |
| 222 U_CAPI void U_EXPORT2 |
| 223 utrans_close(UTransliterator* trans) { |
| 224 delete (Transliterator*) trans; |
| 225 } |
| 226 |
| 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(); |
| 234 } |
| 235 return ID.getBuffer(); |
| 236 } |
| 237 |
| 238 U_CAPI int32_t U_EXPORT2 |
| 239 utrans_getID(const UTransliterator* trans, |
| 240 char* buf, |
| 241 int32_t bufCapacity) { |
| 242 return ((Transliterator*) trans)->getID().extract(0, 0x7fffffff, buf, bufCap
acity, US_INV); |
| 243 } |
| 244 |
| 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); |
| 251 } |
| 252 |
| 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); |
| 257 } |
| 258 |
| 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); |
| 263 } |
| 264 |
| 265 U_CAPI void U_EXPORT2 |
| 266 utrans_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 |
| 290 U_CAPI int32_t U_EXPORT2 |
| 291 utrans_countAvailableIDs(void) { |
| 292 return Transliterator::countAvailableIDs(); |
| 293 } |
| 294 |
| 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, buf
Capacity, US_INV); |
| 300 } |
| 301 |
| 302 /* Transliterator UEnumeration ---------------------------------------------- */ |
| 303 |
| 304 typedef struct UTransEnumeration { |
| 305 UEnumeration uenum; |
| 306 int32_t index, count; |
| 307 } UTransEnumeration; |
| 308 |
| 309 U_CDECL_BEGIN |
| 310 static int32_t U_CALLCONV |
| 311 utrans_enum_count(UEnumeration *uenum, UErrorCode *pErrorCode) { |
| 312 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { |
| 313 return 0; |
| 314 } |
| 315 return ((UTransEnumeration *)uenum)->count; |
| 316 } |
| 317 |
| 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)) { |
| 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 |
| 344 static void U_CALLCONV |
| 345 utrans_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 |
| 355 static void U_CALLCONV |
| 356 utrans_enum_close(UEnumeration *uenum) { |
| 357 uprv_free(uenum); |
| 358 } |
| 359 U_CDECL_END |
| 360 |
| 361 static 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 |
| 371 U_CAPI UEnumeration * U_EXPORT2 |
| 372 utrans_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 |
| 391 /******************************************************************** |
| 392 * Transliteration API |
| 393 ********************************************************************/ |
| 394 |
| 395 U_CAPI void U_EXPORT2 |
| 396 utrans_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 |
| 415 U_CAPI void U_EXPORT2 |
| 416 utrans_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 |
| 434 U_CAPI void U_EXPORT2 |
| 435 utrans_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 |
| 465 U_CAPI void U_EXPORT2 |
| 466 utrans_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 */ |
OLD | NEW |