1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/umsg.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,712 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* 1.7 +* Copyright (C) 1999-2012, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +******************************************************************************* 1.11 +* file name: umsg.cpp 1.12 +* encoding: US-ASCII 1.13 +* tab size: 8 (not used) 1.14 +* indentation:4 1.15 +* 1.16 +* This is a C wrapper to MessageFormat C++ API. 1.17 +* 1.18 +* Change history: 1.19 +* 1.20 +* 08/5/2001 Ram Added C wrappers for C++ API. Changed implementation of old API's 1.21 +* Removed pattern parser. 1.22 +* 1.23 +*/ 1.24 + 1.25 +#include "unicode/utypes.h" 1.26 + 1.27 +#if !UCONFIG_NO_FORMATTING 1.28 + 1.29 +#include "unicode/umsg.h" 1.30 +#include "unicode/ustring.h" 1.31 +#include "unicode/fmtable.h" 1.32 +#include "unicode/msgfmt.h" 1.33 +#include "unicode/unistr.h" 1.34 +#include "cpputils.h" 1.35 +#include "uassert.h" 1.36 +#include "ustr_imp.h" 1.37 + 1.38 +U_NAMESPACE_BEGIN 1.39 +/** 1.40 + * This class isolates our access to private internal methods of 1.41 + * MessageFormat. It is never instantiated; it exists only for C++ 1.42 + * access management. 1.43 + */ 1.44 +class MessageFormatAdapter { 1.45 +public: 1.46 + static const Formattable::Type* getArgTypeList(const MessageFormat& m, 1.47 + int32_t& count); 1.48 + static UBool hasArgTypeConflicts(const MessageFormat& m) { 1.49 + return m.hasArgTypeConflicts; 1.50 + } 1.51 +}; 1.52 +const Formattable::Type* 1.53 +MessageFormatAdapter::getArgTypeList(const MessageFormat& m, 1.54 + int32_t& count) { 1.55 + return m.getArgTypeList(count); 1.56 +} 1.57 +U_NAMESPACE_END 1.58 + 1.59 +U_NAMESPACE_USE 1.60 + 1.61 +U_CAPI int32_t 1.62 +u_formatMessage(const char *locale, 1.63 + const UChar *pattern, 1.64 + int32_t patternLength, 1.65 + UChar *result, 1.66 + int32_t resultLength, 1.67 + UErrorCode *status, 1.68 + ...) 1.69 +{ 1.70 + va_list ap; 1.71 + int32_t actLen; 1.72 + //argument checking defered to subsequent method calls 1.73 + // start vararg processing 1.74 + va_start(ap, status); 1.75 + 1.76 + actLen = u_vformatMessage(locale,pattern,patternLength,result,resultLength,ap,status); 1.77 + // end vararg processing 1.78 + va_end(ap); 1.79 + 1.80 + return actLen; 1.81 +} 1.82 + 1.83 +U_CAPI int32_t U_EXPORT2 1.84 +u_vformatMessage( const char *locale, 1.85 + const UChar *pattern, 1.86 + int32_t patternLength, 1.87 + UChar *result, 1.88 + int32_t resultLength, 1.89 + va_list ap, 1.90 + UErrorCode *status) 1.91 + 1.92 +{ 1.93 + //argument checking defered to subsequent method calls 1.94 + UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,NULL,status); 1.95 + int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status); 1.96 + umsg_close(fmt); 1.97 + return retVal; 1.98 +} 1.99 + 1.100 +U_CAPI int32_t 1.101 +u_formatMessageWithError(const char *locale, 1.102 + const UChar *pattern, 1.103 + int32_t patternLength, 1.104 + UChar *result, 1.105 + int32_t resultLength, 1.106 + UParseError *parseError, 1.107 + UErrorCode *status, 1.108 + ...) 1.109 +{ 1.110 + va_list ap; 1.111 + int32_t actLen; 1.112 + //argument checking defered to subsequent method calls 1.113 + // start vararg processing 1.114 + va_start(ap, status); 1.115 + 1.116 + actLen = u_vformatMessageWithError(locale,pattern,patternLength,result,resultLength,parseError,ap,status); 1.117 + 1.118 + // end vararg processing 1.119 + va_end(ap); 1.120 + return actLen; 1.121 +} 1.122 + 1.123 +U_CAPI int32_t U_EXPORT2 1.124 +u_vformatMessageWithError( const char *locale, 1.125 + const UChar *pattern, 1.126 + int32_t patternLength, 1.127 + UChar *result, 1.128 + int32_t resultLength, 1.129 + UParseError *parseError, 1.130 + va_list ap, 1.131 + UErrorCode *status) 1.132 + 1.133 +{ 1.134 + //argument checking defered to subsequent method calls 1.135 + UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,parseError,status); 1.136 + int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status); 1.137 + umsg_close(fmt); 1.138 + return retVal; 1.139 +} 1.140 + 1.141 + 1.142 +// For parse, do the reverse of format: 1.143 +// 1. Call through to the C++ APIs 1.144 +// 2. Just assume the user passed in enough arguments. 1.145 +// 3. Iterate through each formattable returned, and assign to the arguments 1.146 +U_CAPI void 1.147 +u_parseMessage( const char *locale, 1.148 + const UChar *pattern, 1.149 + int32_t patternLength, 1.150 + const UChar *source, 1.151 + int32_t sourceLength, 1.152 + UErrorCode *status, 1.153 + ...) 1.154 +{ 1.155 + va_list ap; 1.156 + //argument checking defered to subsequent method calls 1.157 + 1.158 + // start vararg processing 1.159 + va_start(ap, status); 1.160 + 1.161 + u_vparseMessage(locale,pattern,patternLength,source,sourceLength,ap,status); 1.162 + // end vararg processing 1.163 + va_end(ap); 1.164 +} 1.165 + 1.166 +U_CAPI void U_EXPORT2 1.167 +u_vparseMessage(const char *locale, 1.168 + const UChar *pattern, 1.169 + int32_t patternLength, 1.170 + const UChar *source, 1.171 + int32_t sourceLength, 1.172 + va_list ap, 1.173 + UErrorCode *status) 1.174 +{ 1.175 + //argument checking defered to subsequent method calls 1.176 + UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,NULL,status); 1.177 + int32_t count = 0; 1.178 + umsg_vparse(fmt,source,sourceLength,&count,ap,status); 1.179 + umsg_close(fmt); 1.180 +} 1.181 + 1.182 +U_CAPI void 1.183 +u_parseMessageWithError(const char *locale, 1.184 + const UChar *pattern, 1.185 + int32_t patternLength, 1.186 + const UChar *source, 1.187 + int32_t sourceLength, 1.188 + UParseError *error, 1.189 + UErrorCode *status, 1.190 + ...) 1.191 +{ 1.192 + va_list ap; 1.193 + 1.194 + //argument checking defered to subsequent method calls 1.195 + 1.196 + // start vararg processing 1.197 + va_start(ap, status); 1.198 + 1.199 + u_vparseMessageWithError(locale,pattern,patternLength,source,sourceLength,ap,error,status); 1.200 + // end vararg processing 1.201 + va_end(ap); 1.202 +} 1.203 +U_CAPI void U_EXPORT2 1.204 +u_vparseMessageWithError(const char *locale, 1.205 + const UChar *pattern, 1.206 + int32_t patternLength, 1.207 + const UChar *source, 1.208 + int32_t sourceLength, 1.209 + va_list ap, 1.210 + UParseError *error, 1.211 + UErrorCode* status) 1.212 +{ 1.213 + //argument checking defered to subsequent method calls 1.214 + UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,error,status); 1.215 + int32_t count = 0; 1.216 + umsg_vparse(fmt,source,sourceLength,&count,ap,status); 1.217 + umsg_close(fmt); 1.218 +} 1.219 +////////////////////////////////////////////////////////////////////////////////// 1.220 +// 1.221 +// Message format C API 1.222 +// 1.223 +///////////////////////////////////////////////////////////////////////////////// 1.224 + 1.225 + 1.226 +U_CAPI UMessageFormat* U_EXPORT2 1.227 +umsg_open( const UChar *pattern, 1.228 + int32_t patternLength, 1.229 + const char *locale, 1.230 + UParseError *parseError, 1.231 + UErrorCode *status) 1.232 +{ 1.233 + //check arguments 1.234 + if(status==NULL || U_FAILURE(*status)) 1.235 + { 1.236 + return 0; 1.237 + } 1.238 + if(pattern==NULL||patternLength<-1){ 1.239 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.240 + return 0; 1.241 + } 1.242 + 1.243 + UParseError tErr; 1.244 + if(parseError==NULL) 1.245 + { 1.246 + parseError = &tErr; 1.247 + } 1.248 + 1.249 + int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength); 1.250 + UnicodeString patString(patternLength == -1, pattern, len); 1.251 + 1.252 + MessageFormat* retVal = new MessageFormat(patString,Locale(locale),*parseError,*status); 1.253 + if(retVal == NULL) { 1.254 + *status = U_MEMORY_ALLOCATION_ERROR; 1.255 + return NULL; 1.256 + } 1.257 + if (U_SUCCESS(*status) && MessageFormatAdapter::hasArgTypeConflicts(*retVal)) { 1.258 + *status = U_ARGUMENT_TYPE_MISMATCH; 1.259 + } 1.260 + return (UMessageFormat*)retVal; 1.261 +} 1.262 + 1.263 +U_CAPI void U_EXPORT2 1.264 +umsg_close(UMessageFormat* format) 1.265 +{ 1.266 + //check arguments 1.267 + if(format==NULL){ 1.268 + return; 1.269 + } 1.270 + delete (MessageFormat*) format; 1.271 +} 1.272 + 1.273 +U_CAPI UMessageFormat U_EXPORT2 1.274 +umsg_clone(const UMessageFormat *fmt, 1.275 + UErrorCode *status) 1.276 +{ 1.277 + //check arguments 1.278 + if(status==NULL || U_FAILURE(*status)){ 1.279 + return NULL; 1.280 + } 1.281 + if(fmt==NULL){ 1.282 + *status = U_ILLEGAL_ARGUMENT_ERROR; 1.283 + return NULL; 1.284 + } 1.285 + UMessageFormat retVal = (UMessageFormat)((MessageFormat*)fmt)->clone(); 1.286 + if(retVal == 0) { 1.287 + *status = U_MEMORY_ALLOCATION_ERROR; 1.288 + return 0; 1.289 + } 1.290 + return retVal; 1.291 +} 1.292 + 1.293 +U_CAPI void U_EXPORT2 1.294 +umsg_setLocale(UMessageFormat *fmt, const char* locale) 1.295 +{ 1.296 + //check arguments 1.297 + if(fmt==NULL){ 1.298 + return; 1.299 + } 1.300 + ((MessageFormat*)fmt)->setLocale(Locale(locale)); 1.301 +} 1.302 + 1.303 +U_CAPI const char* U_EXPORT2 1.304 +umsg_getLocale(const UMessageFormat *fmt) 1.305 +{ 1.306 + //check arguments 1.307 + if(fmt==NULL){ 1.308 + return ""; 1.309 + } 1.310 + return ((const MessageFormat*)fmt)->getLocale().getName(); 1.311 +} 1.312 + 1.313 +U_CAPI void U_EXPORT2 1.314 +umsg_applyPattern(UMessageFormat *fmt, 1.315 + const UChar* pattern, 1.316 + int32_t patternLength, 1.317 + UParseError* parseError, 1.318 + UErrorCode* status) 1.319 +{ 1.320 + //check arguments 1.321 + UParseError tErr; 1.322 + if(status ==NULL||U_FAILURE(*status)){ 1.323 + return ; 1.324 + } 1.325 + if(fmt==NULL||pattern==NULL||patternLength<-1){ 1.326 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.327 + return ; 1.328 + } 1.329 + 1.330 + if(parseError==NULL){ 1.331 + parseError = &tErr; 1.332 + } 1.333 + if(patternLength<-1){ 1.334 + patternLength=u_strlen(pattern); 1.335 + } 1.336 + 1.337 + ((MessageFormat*)fmt)->applyPattern(UnicodeString(pattern,patternLength),*parseError,*status); 1.338 +} 1.339 + 1.340 +U_CAPI int32_t U_EXPORT2 1.341 +umsg_toPattern(const UMessageFormat *fmt, 1.342 + UChar* result, 1.343 + int32_t resultLength, 1.344 + UErrorCode* status) 1.345 +{ 1.346 + //check arguments 1.347 + if(status ==NULL||U_FAILURE(*status)){ 1.348 + return -1; 1.349 + } 1.350 + if(fmt==NULL||resultLength<0 || (resultLength>0 && result==0)){ 1.351 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.352 + return -1; 1.353 + } 1.354 + 1.355 + 1.356 + UnicodeString res; 1.357 + if(!(result==NULL && resultLength==0)) { 1.358 + // NULL destination for pure preflighting: empty dummy string 1.359 + // otherwise, alias the destination buffer 1.360 + res.setTo(result, 0, resultLength); 1.361 + } 1.362 + ((const MessageFormat*)fmt)->toPattern(res); 1.363 + return res.extract(result, resultLength, *status); 1.364 +} 1.365 + 1.366 +U_CAPI int32_t 1.367 +umsg_format( const UMessageFormat *fmt, 1.368 + UChar *result, 1.369 + int32_t resultLength, 1.370 + UErrorCode *status, 1.371 + ...) 1.372 +{ 1.373 + va_list ap; 1.374 + int32_t actLen; 1.375 + //argument checking defered to last method call umsg_vformat which 1.376 + //saves time when arguments are valid and we dont care when arguments are not 1.377 + //since we return an error anyway 1.378 + 1.379 + 1.380 + // start vararg processing 1.381 + va_start(ap, status); 1.382 + 1.383 + actLen = umsg_vformat(fmt,result,resultLength,ap,status); 1.384 + 1.385 + // end vararg processing 1.386 + va_end(ap); 1.387 + 1.388 + return actLen; 1.389 +} 1.390 + 1.391 +U_CAPI int32_t U_EXPORT2 1.392 +umsg_vformat( const UMessageFormat *fmt, 1.393 + UChar *result, 1.394 + int32_t resultLength, 1.395 + va_list ap, 1.396 + UErrorCode *status) 1.397 +{ 1.398 + //check arguments 1.399 + if(status==0 || U_FAILURE(*status)) 1.400 + { 1.401 + return -1; 1.402 + } 1.403 + if(fmt==NULL||resultLength<0 || (resultLength>0 && result==0)) { 1.404 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.405 + return -1; 1.406 + } 1.407 + 1.408 + int32_t count =0; 1.409 + const Formattable::Type* argTypes = 1.410 + MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, count); 1.411 + // Allocate at least one element. Allocating an array of length 1.412 + // zero causes problems on some platforms (e.g. Win32). 1.413 + Formattable* args = new Formattable[count ? count : 1]; 1.414 + 1.415 + // iterate through the vararg list, and get the arguments out 1.416 + for(int32_t i = 0; i < count; ++i) { 1.417 + 1.418 + UChar *stringVal; 1.419 + double tDouble=0; 1.420 + int32_t tInt =0; 1.421 + int64_t tInt64 = 0; 1.422 + UDate tempDate = 0; 1.423 + switch(argTypes[i]) { 1.424 + case Formattable::kDate: 1.425 + tempDate = va_arg(ap, UDate); 1.426 + args[i].setDate(tempDate); 1.427 + break; 1.428 + 1.429 + case Formattable::kDouble: 1.430 + tDouble =va_arg(ap, double); 1.431 + args[i].setDouble(tDouble); 1.432 + break; 1.433 + 1.434 + case Formattable::kLong: 1.435 + tInt = va_arg(ap, int32_t); 1.436 + args[i].setLong(tInt); 1.437 + break; 1.438 + 1.439 + case Formattable::kInt64: 1.440 + tInt64 = va_arg(ap, int64_t); 1.441 + args[i].setInt64(tInt64); 1.442 + break; 1.443 + 1.444 + case Formattable::kString: 1.445 + // For some reason, a temporary is needed 1.446 + stringVal = va_arg(ap, UChar*); 1.447 + if(stringVal){ 1.448 + args[i].setString(UnicodeString(stringVal)); 1.449 + }else{ 1.450 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.451 + } 1.452 + break; 1.453 + 1.454 + case Formattable::kArray: 1.455 + // throw away this argument 1.456 + // this is highly platform-dependent, and probably won't work 1.457 + // so, if you try to skip arguments in the list (and not use them) 1.458 + // you'll probably crash 1.459 + va_arg(ap, int); 1.460 + break; 1.461 + 1.462 + case Formattable::kObject: 1.463 + // Unused argument number. Read and ignore a pointer argument. 1.464 + va_arg(ap, void*); 1.465 + break; 1.466 + 1.467 + default: 1.468 + // Unknown/unsupported argument type. 1.469 + U_ASSERT(FALSE); 1.470 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.471 + break; 1.472 + } 1.473 + } 1.474 + UnicodeString resultStr; 1.475 + FieldPosition fieldPosition(0); 1.476 + 1.477 + /* format the message */ 1.478 + ((const MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status); 1.479 + 1.480 + delete[] args; 1.481 + 1.482 + if(U_FAILURE(*status)){ 1.483 + return -1; 1.484 + } 1.485 + 1.486 + return resultStr.extract(result, resultLength, *status); 1.487 +} 1.488 + 1.489 +U_CAPI void 1.490 +umsg_parse( const UMessageFormat *fmt, 1.491 + const UChar *source, 1.492 + int32_t sourceLength, 1.493 + int32_t *count, 1.494 + UErrorCode *status, 1.495 + ...) 1.496 +{ 1.497 + va_list ap; 1.498 + //argument checking defered to last method call umsg_vparse which 1.499 + //saves time when arguments are valid and we dont care when arguments are not 1.500 + //since we return an error anyway 1.501 + 1.502 + // start vararg processing 1.503 + va_start(ap, status); 1.504 + 1.505 + umsg_vparse(fmt,source,sourceLength,count,ap,status); 1.506 + 1.507 + // end vararg processing 1.508 + va_end(ap); 1.509 +} 1.510 + 1.511 +U_CAPI void U_EXPORT2 1.512 +umsg_vparse(const UMessageFormat *fmt, 1.513 + const UChar *source, 1.514 + int32_t sourceLength, 1.515 + int32_t *count, 1.516 + va_list ap, 1.517 + UErrorCode *status) 1.518 +{ 1.519 + //check arguments 1.520 + if(status==NULL||U_FAILURE(*status)) 1.521 + { 1.522 + return; 1.523 + } 1.524 + if(fmt==NULL||source==NULL || sourceLength<-1 || count==NULL){ 1.525 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.526 + return; 1.527 + } 1.528 + if(sourceLength==-1){ 1.529 + sourceLength=u_strlen(source); 1.530 + } 1.531 + 1.532 + UnicodeString srcString(source,sourceLength); 1.533 + Formattable *args = ((const MessageFormat*)fmt)->parse(srcString,*count,*status); 1.534 + UDate *aDate; 1.535 + double *aDouble; 1.536 + UChar *aString; 1.537 + int32_t* aInt; 1.538 + int64_t* aInt64; 1.539 + UnicodeString temp; 1.540 + int len =0; 1.541 + // assign formattables to varargs 1.542 + for(int32_t i = 0; i < *count; i++) { 1.543 + switch(args[i].getType()) { 1.544 + 1.545 + case Formattable::kDate: 1.546 + aDate = va_arg(ap, UDate*); 1.547 + if(aDate){ 1.548 + *aDate = args[i].getDate(); 1.549 + }else{ 1.550 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.551 + } 1.552 + break; 1.553 + 1.554 + case Formattable::kDouble: 1.555 + aDouble = va_arg(ap, double*); 1.556 + if(aDouble){ 1.557 + *aDouble = args[i].getDouble(); 1.558 + }else{ 1.559 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.560 + } 1.561 + break; 1.562 + 1.563 + case Formattable::kLong: 1.564 + aInt = va_arg(ap, int32_t*); 1.565 + if(aInt){ 1.566 + *aInt = (int32_t) args[i].getLong(); 1.567 + }else{ 1.568 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.569 + } 1.570 + break; 1.571 + 1.572 + case Formattable::kInt64: 1.573 + aInt64 = va_arg(ap, int64_t*); 1.574 + if(aInt64){ 1.575 + *aInt64 = args[i].getInt64(); 1.576 + }else{ 1.577 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.578 + } 1.579 + break; 1.580 + 1.581 + case Formattable::kString: 1.582 + aString = va_arg(ap, UChar*); 1.583 + if(aString){ 1.584 + args[i].getString(temp); 1.585 + len = temp.length(); 1.586 + temp.extract(0,len,aString); 1.587 + aString[len]=0; 1.588 + }else{ 1.589 + *status= U_ILLEGAL_ARGUMENT_ERROR; 1.590 + } 1.591 + break; 1.592 + 1.593 + case Formattable::kObject: 1.594 + // This will never happen because MessageFormat doesn't 1.595 + // support kObject. When MessageFormat is changed to 1.596 + // understand MeasureFormats, modify this code to do the 1.597 + // right thing. [alan] 1.598 + U_ASSERT(FALSE); 1.599 + break; 1.600 + 1.601 + // better not happen! 1.602 + case Formattable::kArray: 1.603 + U_ASSERT(FALSE); 1.604 + break; 1.605 + } 1.606 + } 1.607 + 1.608 + // clean up 1.609 + delete [] args; 1.610 +} 1.611 + 1.612 +#define SINGLE_QUOTE ((UChar)0x0027) 1.613 +#define CURLY_BRACE_LEFT ((UChar)0x007B) 1.614 +#define CURLY_BRACE_RIGHT ((UChar)0x007D) 1.615 + 1.616 +#define STATE_INITIAL 0 1.617 +#define STATE_SINGLE_QUOTE 1 1.618 +#define STATE_IN_QUOTE 2 1.619 +#define STATE_MSG_ELEMENT 3 1.620 + 1.621 +#define MAppend(c) if (len < destCapacity) dest[len++] = c; else len++ 1.622 + 1.623 +int32_t umsg_autoQuoteApostrophe(const UChar* pattern, 1.624 + int32_t patternLength, 1.625 + UChar* dest, 1.626 + int32_t destCapacity, 1.627 + UErrorCode* ec) 1.628 +{ 1.629 + int32_t state = STATE_INITIAL; 1.630 + int32_t braceCount = 0; 1.631 + int32_t len = 0; 1.632 + 1.633 + if (ec == NULL || U_FAILURE(*ec)) { 1.634 + return -1; 1.635 + } 1.636 + 1.637 + if (pattern == NULL || patternLength < -1 || (dest == NULL && destCapacity > 0)) { 1.638 + *ec = U_ILLEGAL_ARGUMENT_ERROR; 1.639 + return -1; 1.640 + } 1.641 + U_ASSERT(destCapacity >= 0); 1.642 + 1.643 + if (patternLength == -1) { 1.644 + patternLength = u_strlen(pattern); 1.645 + } 1.646 + 1.647 + for (int i = 0; i < patternLength; ++i) { 1.648 + UChar c = pattern[i]; 1.649 + switch (state) { 1.650 + case STATE_INITIAL: 1.651 + switch (c) { 1.652 + case SINGLE_QUOTE: 1.653 + state = STATE_SINGLE_QUOTE; 1.654 + break; 1.655 + case CURLY_BRACE_LEFT: 1.656 + state = STATE_MSG_ELEMENT; 1.657 + ++braceCount; 1.658 + break; 1.659 + } 1.660 + break; 1.661 + 1.662 + case STATE_SINGLE_QUOTE: 1.663 + switch (c) { 1.664 + case SINGLE_QUOTE: 1.665 + state = STATE_INITIAL; 1.666 + break; 1.667 + case CURLY_BRACE_LEFT: 1.668 + case CURLY_BRACE_RIGHT: 1.669 + state = STATE_IN_QUOTE; 1.670 + break; 1.671 + default: 1.672 + MAppend(SINGLE_QUOTE); 1.673 + state = STATE_INITIAL; 1.674 + break; 1.675 + } 1.676 + break; 1.677 + 1.678 + case STATE_IN_QUOTE: 1.679 + switch (c) { 1.680 + case SINGLE_QUOTE: 1.681 + state = STATE_INITIAL; 1.682 + break; 1.683 + } 1.684 + break; 1.685 + 1.686 + case STATE_MSG_ELEMENT: 1.687 + switch (c) { 1.688 + case CURLY_BRACE_LEFT: 1.689 + ++braceCount; 1.690 + break; 1.691 + case CURLY_BRACE_RIGHT: 1.692 + if (--braceCount == 0) { 1.693 + state = STATE_INITIAL; 1.694 + } 1.695 + break; 1.696 + } 1.697 + break; 1.698 + 1.699 + default: // Never happens. 1.700 + break; 1.701 + } 1.702 + 1.703 + U_ASSERT(len >= 0); 1.704 + MAppend(c); 1.705 + } 1.706 + 1.707 + // End of scan 1.708 + if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) { 1.709 + MAppend(SINGLE_QUOTE); 1.710 + } 1.711 + 1.712 + return u_terminateUChars(dest, destCapacity, len, ec); 1.713 +} 1.714 + 1.715 +#endif /* #if !UCONFIG_NO_FORMATTING */