LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - umsg.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 255 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13