intl/icu/source/i18n/umsg.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 *******************************************************************************
michael@0 3 *
michael@0 4 * Copyright (C) 1999-2012, International Business Machines
michael@0 5 * Corporation and others. All Rights Reserved.
michael@0 6 *
michael@0 7 *******************************************************************************
michael@0 8 * file name: umsg.cpp
michael@0 9 * encoding: US-ASCII
michael@0 10 * tab size: 8 (not used)
michael@0 11 * indentation:4
michael@0 12 *
michael@0 13 * This is a C wrapper to MessageFormat C++ API.
michael@0 14 *
michael@0 15 * Change history:
michael@0 16 *
michael@0 17 * 08/5/2001 Ram Added C wrappers for C++ API. Changed implementation of old API's
michael@0 18 * Removed pattern parser.
michael@0 19 *
michael@0 20 */
michael@0 21
michael@0 22 #include "unicode/utypes.h"
michael@0 23
michael@0 24 #if !UCONFIG_NO_FORMATTING
michael@0 25
michael@0 26 #include "unicode/umsg.h"
michael@0 27 #include "unicode/ustring.h"
michael@0 28 #include "unicode/fmtable.h"
michael@0 29 #include "unicode/msgfmt.h"
michael@0 30 #include "unicode/unistr.h"
michael@0 31 #include "cpputils.h"
michael@0 32 #include "uassert.h"
michael@0 33 #include "ustr_imp.h"
michael@0 34
michael@0 35 U_NAMESPACE_BEGIN
michael@0 36 /**
michael@0 37 * This class isolates our access to private internal methods of
michael@0 38 * MessageFormat. It is never instantiated; it exists only for C++
michael@0 39 * access management.
michael@0 40 */
michael@0 41 class MessageFormatAdapter {
michael@0 42 public:
michael@0 43 static const Formattable::Type* getArgTypeList(const MessageFormat& m,
michael@0 44 int32_t& count);
michael@0 45 static UBool hasArgTypeConflicts(const MessageFormat& m) {
michael@0 46 return m.hasArgTypeConflicts;
michael@0 47 }
michael@0 48 };
michael@0 49 const Formattable::Type*
michael@0 50 MessageFormatAdapter::getArgTypeList(const MessageFormat& m,
michael@0 51 int32_t& count) {
michael@0 52 return m.getArgTypeList(count);
michael@0 53 }
michael@0 54 U_NAMESPACE_END
michael@0 55
michael@0 56 U_NAMESPACE_USE
michael@0 57
michael@0 58 U_CAPI int32_t
michael@0 59 u_formatMessage(const char *locale,
michael@0 60 const UChar *pattern,
michael@0 61 int32_t patternLength,
michael@0 62 UChar *result,
michael@0 63 int32_t resultLength,
michael@0 64 UErrorCode *status,
michael@0 65 ...)
michael@0 66 {
michael@0 67 va_list ap;
michael@0 68 int32_t actLen;
michael@0 69 //argument checking defered to subsequent method calls
michael@0 70 // start vararg processing
michael@0 71 va_start(ap, status);
michael@0 72
michael@0 73 actLen = u_vformatMessage(locale,pattern,patternLength,result,resultLength,ap,status);
michael@0 74 // end vararg processing
michael@0 75 va_end(ap);
michael@0 76
michael@0 77 return actLen;
michael@0 78 }
michael@0 79
michael@0 80 U_CAPI int32_t U_EXPORT2
michael@0 81 u_vformatMessage( const char *locale,
michael@0 82 const UChar *pattern,
michael@0 83 int32_t patternLength,
michael@0 84 UChar *result,
michael@0 85 int32_t resultLength,
michael@0 86 va_list ap,
michael@0 87 UErrorCode *status)
michael@0 88
michael@0 89 {
michael@0 90 //argument checking defered to subsequent method calls
michael@0 91 UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,NULL,status);
michael@0 92 int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status);
michael@0 93 umsg_close(fmt);
michael@0 94 return retVal;
michael@0 95 }
michael@0 96
michael@0 97 U_CAPI int32_t
michael@0 98 u_formatMessageWithError(const char *locale,
michael@0 99 const UChar *pattern,
michael@0 100 int32_t patternLength,
michael@0 101 UChar *result,
michael@0 102 int32_t resultLength,
michael@0 103 UParseError *parseError,
michael@0 104 UErrorCode *status,
michael@0 105 ...)
michael@0 106 {
michael@0 107 va_list ap;
michael@0 108 int32_t actLen;
michael@0 109 //argument checking defered to subsequent method calls
michael@0 110 // start vararg processing
michael@0 111 va_start(ap, status);
michael@0 112
michael@0 113 actLen = u_vformatMessageWithError(locale,pattern,patternLength,result,resultLength,parseError,ap,status);
michael@0 114
michael@0 115 // end vararg processing
michael@0 116 va_end(ap);
michael@0 117 return actLen;
michael@0 118 }
michael@0 119
michael@0 120 U_CAPI int32_t U_EXPORT2
michael@0 121 u_vformatMessageWithError( const char *locale,
michael@0 122 const UChar *pattern,
michael@0 123 int32_t patternLength,
michael@0 124 UChar *result,
michael@0 125 int32_t resultLength,
michael@0 126 UParseError *parseError,
michael@0 127 va_list ap,
michael@0 128 UErrorCode *status)
michael@0 129
michael@0 130 {
michael@0 131 //argument checking defered to subsequent method calls
michael@0 132 UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,parseError,status);
michael@0 133 int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status);
michael@0 134 umsg_close(fmt);
michael@0 135 return retVal;
michael@0 136 }
michael@0 137
michael@0 138
michael@0 139 // For parse, do the reverse of format:
michael@0 140 // 1. Call through to the C++ APIs
michael@0 141 // 2. Just assume the user passed in enough arguments.
michael@0 142 // 3. Iterate through each formattable returned, and assign to the arguments
michael@0 143 U_CAPI void
michael@0 144 u_parseMessage( const char *locale,
michael@0 145 const UChar *pattern,
michael@0 146 int32_t patternLength,
michael@0 147 const UChar *source,
michael@0 148 int32_t sourceLength,
michael@0 149 UErrorCode *status,
michael@0 150 ...)
michael@0 151 {
michael@0 152 va_list ap;
michael@0 153 //argument checking defered to subsequent method calls
michael@0 154
michael@0 155 // start vararg processing
michael@0 156 va_start(ap, status);
michael@0 157
michael@0 158 u_vparseMessage(locale,pattern,patternLength,source,sourceLength,ap,status);
michael@0 159 // end vararg processing
michael@0 160 va_end(ap);
michael@0 161 }
michael@0 162
michael@0 163 U_CAPI void U_EXPORT2
michael@0 164 u_vparseMessage(const char *locale,
michael@0 165 const UChar *pattern,
michael@0 166 int32_t patternLength,
michael@0 167 const UChar *source,
michael@0 168 int32_t sourceLength,
michael@0 169 va_list ap,
michael@0 170 UErrorCode *status)
michael@0 171 {
michael@0 172 //argument checking defered to subsequent method calls
michael@0 173 UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,NULL,status);
michael@0 174 int32_t count = 0;
michael@0 175 umsg_vparse(fmt,source,sourceLength,&count,ap,status);
michael@0 176 umsg_close(fmt);
michael@0 177 }
michael@0 178
michael@0 179 U_CAPI void
michael@0 180 u_parseMessageWithError(const char *locale,
michael@0 181 const UChar *pattern,
michael@0 182 int32_t patternLength,
michael@0 183 const UChar *source,
michael@0 184 int32_t sourceLength,
michael@0 185 UParseError *error,
michael@0 186 UErrorCode *status,
michael@0 187 ...)
michael@0 188 {
michael@0 189 va_list ap;
michael@0 190
michael@0 191 //argument checking defered to subsequent method calls
michael@0 192
michael@0 193 // start vararg processing
michael@0 194 va_start(ap, status);
michael@0 195
michael@0 196 u_vparseMessageWithError(locale,pattern,patternLength,source,sourceLength,ap,error,status);
michael@0 197 // end vararg processing
michael@0 198 va_end(ap);
michael@0 199 }
michael@0 200 U_CAPI void U_EXPORT2
michael@0 201 u_vparseMessageWithError(const char *locale,
michael@0 202 const UChar *pattern,
michael@0 203 int32_t patternLength,
michael@0 204 const UChar *source,
michael@0 205 int32_t sourceLength,
michael@0 206 va_list ap,
michael@0 207 UParseError *error,
michael@0 208 UErrorCode* status)
michael@0 209 {
michael@0 210 //argument checking defered to subsequent method calls
michael@0 211 UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,error,status);
michael@0 212 int32_t count = 0;
michael@0 213 umsg_vparse(fmt,source,sourceLength,&count,ap,status);
michael@0 214 umsg_close(fmt);
michael@0 215 }
michael@0 216 //////////////////////////////////////////////////////////////////////////////////
michael@0 217 //
michael@0 218 // Message format C API
michael@0 219 //
michael@0 220 /////////////////////////////////////////////////////////////////////////////////
michael@0 221
michael@0 222
michael@0 223 U_CAPI UMessageFormat* U_EXPORT2
michael@0 224 umsg_open( const UChar *pattern,
michael@0 225 int32_t patternLength,
michael@0 226 const char *locale,
michael@0 227 UParseError *parseError,
michael@0 228 UErrorCode *status)
michael@0 229 {
michael@0 230 //check arguments
michael@0 231 if(status==NULL || U_FAILURE(*status))
michael@0 232 {
michael@0 233 return 0;
michael@0 234 }
michael@0 235 if(pattern==NULL||patternLength<-1){
michael@0 236 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 237 return 0;
michael@0 238 }
michael@0 239
michael@0 240 UParseError tErr;
michael@0 241 if(parseError==NULL)
michael@0 242 {
michael@0 243 parseError = &tErr;
michael@0 244 }
michael@0 245
michael@0 246 int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
michael@0 247 UnicodeString patString(patternLength == -1, pattern, len);
michael@0 248
michael@0 249 MessageFormat* retVal = new MessageFormat(patString,Locale(locale),*parseError,*status);
michael@0 250 if(retVal == NULL) {
michael@0 251 *status = U_MEMORY_ALLOCATION_ERROR;
michael@0 252 return NULL;
michael@0 253 }
michael@0 254 if (U_SUCCESS(*status) && MessageFormatAdapter::hasArgTypeConflicts(*retVal)) {
michael@0 255 *status = U_ARGUMENT_TYPE_MISMATCH;
michael@0 256 }
michael@0 257 return (UMessageFormat*)retVal;
michael@0 258 }
michael@0 259
michael@0 260 U_CAPI void U_EXPORT2
michael@0 261 umsg_close(UMessageFormat* format)
michael@0 262 {
michael@0 263 //check arguments
michael@0 264 if(format==NULL){
michael@0 265 return;
michael@0 266 }
michael@0 267 delete (MessageFormat*) format;
michael@0 268 }
michael@0 269
michael@0 270 U_CAPI UMessageFormat U_EXPORT2
michael@0 271 umsg_clone(const UMessageFormat *fmt,
michael@0 272 UErrorCode *status)
michael@0 273 {
michael@0 274 //check arguments
michael@0 275 if(status==NULL || U_FAILURE(*status)){
michael@0 276 return NULL;
michael@0 277 }
michael@0 278 if(fmt==NULL){
michael@0 279 *status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 280 return NULL;
michael@0 281 }
michael@0 282 UMessageFormat retVal = (UMessageFormat)((MessageFormat*)fmt)->clone();
michael@0 283 if(retVal == 0) {
michael@0 284 *status = U_MEMORY_ALLOCATION_ERROR;
michael@0 285 return 0;
michael@0 286 }
michael@0 287 return retVal;
michael@0 288 }
michael@0 289
michael@0 290 U_CAPI void U_EXPORT2
michael@0 291 umsg_setLocale(UMessageFormat *fmt, const char* locale)
michael@0 292 {
michael@0 293 //check arguments
michael@0 294 if(fmt==NULL){
michael@0 295 return;
michael@0 296 }
michael@0 297 ((MessageFormat*)fmt)->setLocale(Locale(locale));
michael@0 298 }
michael@0 299
michael@0 300 U_CAPI const char* U_EXPORT2
michael@0 301 umsg_getLocale(const UMessageFormat *fmt)
michael@0 302 {
michael@0 303 //check arguments
michael@0 304 if(fmt==NULL){
michael@0 305 return "";
michael@0 306 }
michael@0 307 return ((const MessageFormat*)fmt)->getLocale().getName();
michael@0 308 }
michael@0 309
michael@0 310 U_CAPI void U_EXPORT2
michael@0 311 umsg_applyPattern(UMessageFormat *fmt,
michael@0 312 const UChar* pattern,
michael@0 313 int32_t patternLength,
michael@0 314 UParseError* parseError,
michael@0 315 UErrorCode* status)
michael@0 316 {
michael@0 317 //check arguments
michael@0 318 UParseError tErr;
michael@0 319 if(status ==NULL||U_FAILURE(*status)){
michael@0 320 return ;
michael@0 321 }
michael@0 322 if(fmt==NULL||pattern==NULL||patternLength<-1){
michael@0 323 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 324 return ;
michael@0 325 }
michael@0 326
michael@0 327 if(parseError==NULL){
michael@0 328 parseError = &tErr;
michael@0 329 }
michael@0 330 if(patternLength<-1){
michael@0 331 patternLength=u_strlen(pattern);
michael@0 332 }
michael@0 333
michael@0 334 ((MessageFormat*)fmt)->applyPattern(UnicodeString(pattern,patternLength),*parseError,*status);
michael@0 335 }
michael@0 336
michael@0 337 U_CAPI int32_t U_EXPORT2
michael@0 338 umsg_toPattern(const UMessageFormat *fmt,
michael@0 339 UChar* result,
michael@0 340 int32_t resultLength,
michael@0 341 UErrorCode* status)
michael@0 342 {
michael@0 343 //check arguments
michael@0 344 if(status ==NULL||U_FAILURE(*status)){
michael@0 345 return -1;
michael@0 346 }
michael@0 347 if(fmt==NULL||resultLength<0 || (resultLength>0 && result==0)){
michael@0 348 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 349 return -1;
michael@0 350 }
michael@0 351
michael@0 352
michael@0 353 UnicodeString res;
michael@0 354 if(!(result==NULL && resultLength==0)) {
michael@0 355 // NULL destination for pure preflighting: empty dummy string
michael@0 356 // otherwise, alias the destination buffer
michael@0 357 res.setTo(result, 0, resultLength);
michael@0 358 }
michael@0 359 ((const MessageFormat*)fmt)->toPattern(res);
michael@0 360 return res.extract(result, resultLength, *status);
michael@0 361 }
michael@0 362
michael@0 363 U_CAPI int32_t
michael@0 364 umsg_format( const UMessageFormat *fmt,
michael@0 365 UChar *result,
michael@0 366 int32_t resultLength,
michael@0 367 UErrorCode *status,
michael@0 368 ...)
michael@0 369 {
michael@0 370 va_list ap;
michael@0 371 int32_t actLen;
michael@0 372 //argument checking defered to last method call umsg_vformat which
michael@0 373 //saves time when arguments are valid and we dont care when arguments are not
michael@0 374 //since we return an error anyway
michael@0 375
michael@0 376
michael@0 377 // start vararg processing
michael@0 378 va_start(ap, status);
michael@0 379
michael@0 380 actLen = umsg_vformat(fmt,result,resultLength,ap,status);
michael@0 381
michael@0 382 // end vararg processing
michael@0 383 va_end(ap);
michael@0 384
michael@0 385 return actLen;
michael@0 386 }
michael@0 387
michael@0 388 U_CAPI int32_t U_EXPORT2
michael@0 389 umsg_vformat( const UMessageFormat *fmt,
michael@0 390 UChar *result,
michael@0 391 int32_t resultLength,
michael@0 392 va_list ap,
michael@0 393 UErrorCode *status)
michael@0 394 {
michael@0 395 //check arguments
michael@0 396 if(status==0 || U_FAILURE(*status))
michael@0 397 {
michael@0 398 return -1;
michael@0 399 }
michael@0 400 if(fmt==NULL||resultLength<0 || (resultLength>0 && result==0)) {
michael@0 401 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 402 return -1;
michael@0 403 }
michael@0 404
michael@0 405 int32_t count =0;
michael@0 406 const Formattable::Type* argTypes =
michael@0 407 MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, count);
michael@0 408 // Allocate at least one element. Allocating an array of length
michael@0 409 // zero causes problems on some platforms (e.g. Win32).
michael@0 410 Formattable* args = new Formattable[count ? count : 1];
michael@0 411
michael@0 412 // iterate through the vararg list, and get the arguments out
michael@0 413 for(int32_t i = 0; i < count; ++i) {
michael@0 414
michael@0 415 UChar *stringVal;
michael@0 416 double tDouble=0;
michael@0 417 int32_t tInt =0;
michael@0 418 int64_t tInt64 = 0;
michael@0 419 UDate tempDate = 0;
michael@0 420 switch(argTypes[i]) {
michael@0 421 case Formattable::kDate:
michael@0 422 tempDate = va_arg(ap, UDate);
michael@0 423 args[i].setDate(tempDate);
michael@0 424 break;
michael@0 425
michael@0 426 case Formattable::kDouble:
michael@0 427 tDouble =va_arg(ap, double);
michael@0 428 args[i].setDouble(tDouble);
michael@0 429 break;
michael@0 430
michael@0 431 case Formattable::kLong:
michael@0 432 tInt = va_arg(ap, int32_t);
michael@0 433 args[i].setLong(tInt);
michael@0 434 break;
michael@0 435
michael@0 436 case Formattable::kInt64:
michael@0 437 tInt64 = va_arg(ap, int64_t);
michael@0 438 args[i].setInt64(tInt64);
michael@0 439 break;
michael@0 440
michael@0 441 case Formattable::kString:
michael@0 442 // For some reason, a temporary is needed
michael@0 443 stringVal = va_arg(ap, UChar*);
michael@0 444 if(stringVal){
michael@0 445 args[i].setString(UnicodeString(stringVal));
michael@0 446 }else{
michael@0 447 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 448 }
michael@0 449 break;
michael@0 450
michael@0 451 case Formattable::kArray:
michael@0 452 // throw away this argument
michael@0 453 // this is highly platform-dependent, and probably won't work
michael@0 454 // so, if you try to skip arguments in the list (and not use them)
michael@0 455 // you'll probably crash
michael@0 456 va_arg(ap, int);
michael@0 457 break;
michael@0 458
michael@0 459 case Formattable::kObject:
michael@0 460 // Unused argument number. Read and ignore a pointer argument.
michael@0 461 va_arg(ap, void*);
michael@0 462 break;
michael@0 463
michael@0 464 default:
michael@0 465 // Unknown/unsupported argument type.
michael@0 466 U_ASSERT(FALSE);
michael@0 467 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 468 break;
michael@0 469 }
michael@0 470 }
michael@0 471 UnicodeString resultStr;
michael@0 472 FieldPosition fieldPosition(0);
michael@0 473
michael@0 474 /* format the message */
michael@0 475 ((const MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status);
michael@0 476
michael@0 477 delete[] args;
michael@0 478
michael@0 479 if(U_FAILURE(*status)){
michael@0 480 return -1;
michael@0 481 }
michael@0 482
michael@0 483 return resultStr.extract(result, resultLength, *status);
michael@0 484 }
michael@0 485
michael@0 486 U_CAPI void
michael@0 487 umsg_parse( const UMessageFormat *fmt,
michael@0 488 const UChar *source,
michael@0 489 int32_t sourceLength,
michael@0 490 int32_t *count,
michael@0 491 UErrorCode *status,
michael@0 492 ...)
michael@0 493 {
michael@0 494 va_list ap;
michael@0 495 //argument checking defered to last method call umsg_vparse which
michael@0 496 //saves time when arguments are valid and we dont care when arguments are not
michael@0 497 //since we return an error anyway
michael@0 498
michael@0 499 // start vararg processing
michael@0 500 va_start(ap, status);
michael@0 501
michael@0 502 umsg_vparse(fmt,source,sourceLength,count,ap,status);
michael@0 503
michael@0 504 // end vararg processing
michael@0 505 va_end(ap);
michael@0 506 }
michael@0 507
michael@0 508 U_CAPI void U_EXPORT2
michael@0 509 umsg_vparse(const UMessageFormat *fmt,
michael@0 510 const UChar *source,
michael@0 511 int32_t sourceLength,
michael@0 512 int32_t *count,
michael@0 513 va_list ap,
michael@0 514 UErrorCode *status)
michael@0 515 {
michael@0 516 //check arguments
michael@0 517 if(status==NULL||U_FAILURE(*status))
michael@0 518 {
michael@0 519 return;
michael@0 520 }
michael@0 521 if(fmt==NULL||source==NULL || sourceLength<-1 || count==NULL){
michael@0 522 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 523 return;
michael@0 524 }
michael@0 525 if(sourceLength==-1){
michael@0 526 sourceLength=u_strlen(source);
michael@0 527 }
michael@0 528
michael@0 529 UnicodeString srcString(source,sourceLength);
michael@0 530 Formattable *args = ((const MessageFormat*)fmt)->parse(srcString,*count,*status);
michael@0 531 UDate *aDate;
michael@0 532 double *aDouble;
michael@0 533 UChar *aString;
michael@0 534 int32_t* aInt;
michael@0 535 int64_t* aInt64;
michael@0 536 UnicodeString temp;
michael@0 537 int len =0;
michael@0 538 // assign formattables to varargs
michael@0 539 for(int32_t i = 0; i < *count; i++) {
michael@0 540 switch(args[i].getType()) {
michael@0 541
michael@0 542 case Formattable::kDate:
michael@0 543 aDate = va_arg(ap, UDate*);
michael@0 544 if(aDate){
michael@0 545 *aDate = args[i].getDate();
michael@0 546 }else{
michael@0 547 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 548 }
michael@0 549 break;
michael@0 550
michael@0 551 case Formattable::kDouble:
michael@0 552 aDouble = va_arg(ap, double*);
michael@0 553 if(aDouble){
michael@0 554 *aDouble = args[i].getDouble();
michael@0 555 }else{
michael@0 556 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 557 }
michael@0 558 break;
michael@0 559
michael@0 560 case Formattable::kLong:
michael@0 561 aInt = va_arg(ap, int32_t*);
michael@0 562 if(aInt){
michael@0 563 *aInt = (int32_t) args[i].getLong();
michael@0 564 }else{
michael@0 565 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 566 }
michael@0 567 break;
michael@0 568
michael@0 569 case Formattable::kInt64:
michael@0 570 aInt64 = va_arg(ap, int64_t*);
michael@0 571 if(aInt64){
michael@0 572 *aInt64 = args[i].getInt64();
michael@0 573 }else{
michael@0 574 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 575 }
michael@0 576 break;
michael@0 577
michael@0 578 case Formattable::kString:
michael@0 579 aString = va_arg(ap, UChar*);
michael@0 580 if(aString){
michael@0 581 args[i].getString(temp);
michael@0 582 len = temp.length();
michael@0 583 temp.extract(0,len,aString);
michael@0 584 aString[len]=0;
michael@0 585 }else{
michael@0 586 *status= U_ILLEGAL_ARGUMENT_ERROR;
michael@0 587 }
michael@0 588 break;
michael@0 589
michael@0 590 case Formattable::kObject:
michael@0 591 // This will never happen because MessageFormat doesn't
michael@0 592 // support kObject. When MessageFormat is changed to
michael@0 593 // understand MeasureFormats, modify this code to do the
michael@0 594 // right thing. [alan]
michael@0 595 U_ASSERT(FALSE);
michael@0 596 break;
michael@0 597
michael@0 598 // better not happen!
michael@0 599 case Formattable::kArray:
michael@0 600 U_ASSERT(FALSE);
michael@0 601 break;
michael@0 602 }
michael@0 603 }
michael@0 604
michael@0 605 // clean up
michael@0 606 delete [] args;
michael@0 607 }
michael@0 608
michael@0 609 #define SINGLE_QUOTE ((UChar)0x0027)
michael@0 610 #define CURLY_BRACE_LEFT ((UChar)0x007B)
michael@0 611 #define CURLY_BRACE_RIGHT ((UChar)0x007D)
michael@0 612
michael@0 613 #define STATE_INITIAL 0
michael@0 614 #define STATE_SINGLE_QUOTE 1
michael@0 615 #define STATE_IN_QUOTE 2
michael@0 616 #define STATE_MSG_ELEMENT 3
michael@0 617
michael@0 618 #define MAppend(c) if (len < destCapacity) dest[len++] = c; else len++
michael@0 619
michael@0 620 int32_t umsg_autoQuoteApostrophe(const UChar* pattern,
michael@0 621 int32_t patternLength,
michael@0 622 UChar* dest,
michael@0 623 int32_t destCapacity,
michael@0 624 UErrorCode* ec)
michael@0 625 {
michael@0 626 int32_t state = STATE_INITIAL;
michael@0 627 int32_t braceCount = 0;
michael@0 628 int32_t len = 0;
michael@0 629
michael@0 630 if (ec == NULL || U_FAILURE(*ec)) {
michael@0 631 return -1;
michael@0 632 }
michael@0 633
michael@0 634 if (pattern == NULL || patternLength < -1 || (dest == NULL && destCapacity > 0)) {
michael@0 635 *ec = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 636 return -1;
michael@0 637 }
michael@0 638 U_ASSERT(destCapacity >= 0);
michael@0 639
michael@0 640 if (patternLength == -1) {
michael@0 641 patternLength = u_strlen(pattern);
michael@0 642 }
michael@0 643
michael@0 644 for (int i = 0; i < patternLength; ++i) {
michael@0 645 UChar c = pattern[i];
michael@0 646 switch (state) {
michael@0 647 case STATE_INITIAL:
michael@0 648 switch (c) {
michael@0 649 case SINGLE_QUOTE:
michael@0 650 state = STATE_SINGLE_QUOTE;
michael@0 651 break;
michael@0 652 case CURLY_BRACE_LEFT:
michael@0 653 state = STATE_MSG_ELEMENT;
michael@0 654 ++braceCount;
michael@0 655 break;
michael@0 656 }
michael@0 657 break;
michael@0 658
michael@0 659 case STATE_SINGLE_QUOTE:
michael@0 660 switch (c) {
michael@0 661 case SINGLE_QUOTE:
michael@0 662 state = STATE_INITIAL;
michael@0 663 break;
michael@0 664 case CURLY_BRACE_LEFT:
michael@0 665 case CURLY_BRACE_RIGHT:
michael@0 666 state = STATE_IN_QUOTE;
michael@0 667 break;
michael@0 668 default:
michael@0 669 MAppend(SINGLE_QUOTE);
michael@0 670 state = STATE_INITIAL;
michael@0 671 break;
michael@0 672 }
michael@0 673 break;
michael@0 674
michael@0 675 case STATE_IN_QUOTE:
michael@0 676 switch (c) {
michael@0 677 case SINGLE_QUOTE:
michael@0 678 state = STATE_INITIAL;
michael@0 679 break;
michael@0 680 }
michael@0 681 break;
michael@0 682
michael@0 683 case STATE_MSG_ELEMENT:
michael@0 684 switch (c) {
michael@0 685 case CURLY_BRACE_LEFT:
michael@0 686 ++braceCount;
michael@0 687 break;
michael@0 688 case CURLY_BRACE_RIGHT:
michael@0 689 if (--braceCount == 0) {
michael@0 690 state = STATE_INITIAL;
michael@0 691 }
michael@0 692 break;
michael@0 693 }
michael@0 694 break;
michael@0 695
michael@0 696 default: // Never happens.
michael@0 697 break;
michael@0 698 }
michael@0 699
michael@0 700 U_ASSERT(len >= 0);
michael@0 701 MAppend(c);
michael@0 702 }
michael@0 703
michael@0 704 // End of scan
michael@0 705 if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) {
michael@0 706 MAppend(SINGLE_QUOTE);
michael@0 707 }
michael@0 708
michael@0 709 return u_terminateUChars(dest, destCapacity, len, ec);
michael@0 710 }
michael@0 711
michael@0 712 #endif /* #if !UCONFIG_NO_FORMATTING */

mercurial