11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
31cb0ef41Sopenharmony_ci/*
41cb0ef41Sopenharmony_ci*******************************************************************************
51cb0ef41Sopenharmony_ci*
61cb0ef41Sopenharmony_ci*   Copyright (C) 1999-2012, International Business Machines
71cb0ef41Sopenharmony_ci*   Corporation and others.  All Rights Reserved.
81cb0ef41Sopenharmony_ci*
91cb0ef41Sopenharmony_ci*******************************************************************************
101cb0ef41Sopenharmony_ci*   file name:  umsg.cpp
111cb0ef41Sopenharmony_ci*   encoding:   UTF-8
121cb0ef41Sopenharmony_ci*   tab size:   8 (not used)
131cb0ef41Sopenharmony_ci*   indentation:4
141cb0ef41Sopenharmony_ci*
151cb0ef41Sopenharmony_ci* This is a C wrapper to MessageFormat C++ API.
161cb0ef41Sopenharmony_ci*
171cb0ef41Sopenharmony_ci*   Change history:
181cb0ef41Sopenharmony_ci*
191cb0ef41Sopenharmony_ci*   08/5/2001  Ram         Added C wrappers for C++ API. Changed implementation of old API's
201cb0ef41Sopenharmony_ci*                          Removed pattern parser.
211cb0ef41Sopenharmony_ci*
221cb0ef41Sopenharmony_ci*/
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci#include "unicode/utypes.h"
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci#if !UCONFIG_NO_FORMATTING
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci#include "unicode/umsg.h"
291cb0ef41Sopenharmony_ci#include "unicode/ustring.h"
301cb0ef41Sopenharmony_ci#include "unicode/fmtable.h"
311cb0ef41Sopenharmony_ci#include "unicode/msgfmt.h"
321cb0ef41Sopenharmony_ci#include "unicode/unistr.h"
331cb0ef41Sopenharmony_ci#include "cpputils.h"
341cb0ef41Sopenharmony_ci#include "uassert.h"
351cb0ef41Sopenharmony_ci#include "ustr_imp.h"
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ciU_NAMESPACE_BEGIN
381cb0ef41Sopenharmony_ci/**
391cb0ef41Sopenharmony_ci * This class isolates our access to private internal methods of
401cb0ef41Sopenharmony_ci * MessageFormat.  It is never instantiated; it exists only for C++
411cb0ef41Sopenharmony_ci * access management.
421cb0ef41Sopenharmony_ci */
431cb0ef41Sopenharmony_ciclass MessageFormatAdapter {
441cb0ef41Sopenharmony_cipublic:
451cb0ef41Sopenharmony_ci    static const Formattable::Type* getArgTypeList(const MessageFormat& m,
461cb0ef41Sopenharmony_ci                                                   int32_t& count);
471cb0ef41Sopenharmony_ci    static UBool hasArgTypeConflicts(const MessageFormat& m) {
481cb0ef41Sopenharmony_ci        return m.hasArgTypeConflicts;
491cb0ef41Sopenharmony_ci    }
501cb0ef41Sopenharmony_ci};
511cb0ef41Sopenharmony_ciconst Formattable::Type*
521cb0ef41Sopenharmony_ciMessageFormatAdapter::getArgTypeList(const MessageFormat& m,
531cb0ef41Sopenharmony_ci                                     int32_t& count) {
541cb0ef41Sopenharmony_ci    return m.getArgTypeList(count);
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ciU_NAMESPACE_END
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ciU_NAMESPACE_USE
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ciU_CAPI int32_t
611cb0ef41Sopenharmony_ciu_formatMessage(const char  *locale,
621cb0ef41Sopenharmony_ci                const char16_t *pattern,
631cb0ef41Sopenharmony_ci                int32_t     patternLength,
641cb0ef41Sopenharmony_ci                char16_t    *result,
651cb0ef41Sopenharmony_ci                int32_t     resultLength,
661cb0ef41Sopenharmony_ci                UErrorCode  *status,
671cb0ef41Sopenharmony_ci                ...)
681cb0ef41Sopenharmony_ci{
691cb0ef41Sopenharmony_ci    va_list    ap;
701cb0ef41Sopenharmony_ci    int32_t actLen;
711cb0ef41Sopenharmony_ci    //argument checking deferred to subsequent method calls
721cb0ef41Sopenharmony_ci    // start vararg processing
731cb0ef41Sopenharmony_ci    va_start(ap, status);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci    actLen = u_vformatMessage(locale,pattern,patternLength,result,resultLength,ap,status);
761cb0ef41Sopenharmony_ci    // end vararg processing
771cb0ef41Sopenharmony_ci    va_end(ap);
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci    return actLen;
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
831cb0ef41Sopenharmony_ciu_vformatMessage(   const char  *locale,
841cb0ef41Sopenharmony_ci                    const char16_t *pattern,
851cb0ef41Sopenharmony_ci                    int32_t     patternLength,
861cb0ef41Sopenharmony_ci                    char16_t    *result,
871cb0ef41Sopenharmony_ci                    int32_t     resultLength,
881cb0ef41Sopenharmony_ci                    va_list     ap,
891cb0ef41Sopenharmony_ci                    UErrorCode  *status)
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci{
921cb0ef41Sopenharmony_ci    //argument checking deferred to subsequent method calls
931cb0ef41Sopenharmony_ci    UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,nullptr,status);
941cb0ef41Sopenharmony_ci    int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status);
951cb0ef41Sopenharmony_ci    umsg_close(fmt);
961cb0ef41Sopenharmony_ci    return retVal;
971cb0ef41Sopenharmony_ci}
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ciU_CAPI int32_t
1001cb0ef41Sopenharmony_ciu_formatMessageWithError(const char *locale,
1011cb0ef41Sopenharmony_ci                        const char16_t *pattern,
1021cb0ef41Sopenharmony_ci                        int32_t     patternLength,
1031cb0ef41Sopenharmony_ci                        char16_t    *result,
1041cb0ef41Sopenharmony_ci                        int32_t     resultLength,
1051cb0ef41Sopenharmony_ci                        UParseError *parseError,
1061cb0ef41Sopenharmony_ci                        UErrorCode  *status,
1071cb0ef41Sopenharmony_ci                        ...)
1081cb0ef41Sopenharmony_ci{
1091cb0ef41Sopenharmony_ci    va_list    ap;
1101cb0ef41Sopenharmony_ci    int32_t actLen;
1111cb0ef41Sopenharmony_ci    //argument checking deferred to subsequent method calls
1121cb0ef41Sopenharmony_ci    // start vararg processing
1131cb0ef41Sopenharmony_ci    va_start(ap, status);
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci    actLen = u_vformatMessageWithError(locale,pattern,patternLength,result,resultLength,parseError,ap,status);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci    // end vararg processing
1181cb0ef41Sopenharmony_ci    va_end(ap);
1191cb0ef41Sopenharmony_ci    return actLen;
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
1231cb0ef41Sopenharmony_ciu_vformatMessageWithError(  const char  *locale,
1241cb0ef41Sopenharmony_ci                            const char16_t *pattern,
1251cb0ef41Sopenharmony_ci                            int32_t     patternLength,
1261cb0ef41Sopenharmony_ci                            char16_t    *result,
1271cb0ef41Sopenharmony_ci                            int32_t     resultLength,
1281cb0ef41Sopenharmony_ci                            UParseError *parseError,
1291cb0ef41Sopenharmony_ci                            va_list     ap,
1301cb0ef41Sopenharmony_ci                            UErrorCode  *status)
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci{
1331cb0ef41Sopenharmony_ci    //argument checking deferred to subsequent method calls
1341cb0ef41Sopenharmony_ci    UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,parseError,status);
1351cb0ef41Sopenharmony_ci    int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status);
1361cb0ef41Sopenharmony_ci    umsg_close(fmt);
1371cb0ef41Sopenharmony_ci    return retVal;
1381cb0ef41Sopenharmony_ci}
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci// For parse, do the reverse of format:
1421cb0ef41Sopenharmony_ci//  1. Call through to the C++ APIs
1431cb0ef41Sopenharmony_ci//  2. Just assume the user passed in enough arguments.
1441cb0ef41Sopenharmony_ci//  3. Iterate through each formattable returned, and assign to the arguments
1451cb0ef41Sopenharmony_ciU_CAPI void
1461cb0ef41Sopenharmony_ciu_parseMessage( const char   *locale,
1471cb0ef41Sopenharmony_ci                const char16_t  *pattern,
1481cb0ef41Sopenharmony_ci                int32_t      patternLength,
1491cb0ef41Sopenharmony_ci                const char16_t  *source,
1501cb0ef41Sopenharmony_ci                int32_t      sourceLength,
1511cb0ef41Sopenharmony_ci                UErrorCode   *status,
1521cb0ef41Sopenharmony_ci                ...)
1531cb0ef41Sopenharmony_ci{
1541cb0ef41Sopenharmony_ci    va_list    ap;
1551cb0ef41Sopenharmony_ci    //argument checking deferred to subsequent method calls
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci    // start vararg processing
1581cb0ef41Sopenharmony_ci    va_start(ap, status);
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci    u_vparseMessage(locale,pattern,patternLength,source,sourceLength,ap,status);
1611cb0ef41Sopenharmony_ci    // end vararg processing
1621cb0ef41Sopenharmony_ci    va_end(ap);
1631cb0ef41Sopenharmony_ci}
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
1661cb0ef41Sopenharmony_ciu_vparseMessage(const char  *locale,
1671cb0ef41Sopenharmony_ci                const char16_t *pattern,
1681cb0ef41Sopenharmony_ci                int32_t     patternLength,
1691cb0ef41Sopenharmony_ci                const char16_t *source,
1701cb0ef41Sopenharmony_ci                int32_t     sourceLength,
1711cb0ef41Sopenharmony_ci                va_list     ap,
1721cb0ef41Sopenharmony_ci                UErrorCode  *status)
1731cb0ef41Sopenharmony_ci{
1741cb0ef41Sopenharmony_ci    //argument checking deferred to subsequent method calls
1751cb0ef41Sopenharmony_ci    UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,nullptr,status);
1761cb0ef41Sopenharmony_ci    int32_t count = 0;
1771cb0ef41Sopenharmony_ci    umsg_vparse(fmt,source,sourceLength,&count,ap,status);
1781cb0ef41Sopenharmony_ci    umsg_close(fmt);
1791cb0ef41Sopenharmony_ci}
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ciU_CAPI void
1821cb0ef41Sopenharmony_ciu_parseMessageWithError(const char  *locale,
1831cb0ef41Sopenharmony_ci                        const char16_t *pattern,
1841cb0ef41Sopenharmony_ci                        int32_t     patternLength,
1851cb0ef41Sopenharmony_ci                        const char16_t *source,
1861cb0ef41Sopenharmony_ci                        int32_t     sourceLength,
1871cb0ef41Sopenharmony_ci                        UParseError *error,
1881cb0ef41Sopenharmony_ci                        UErrorCode  *status,
1891cb0ef41Sopenharmony_ci                        ...)
1901cb0ef41Sopenharmony_ci{
1911cb0ef41Sopenharmony_ci    va_list    ap;
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci    //argument checking deferred to subsequent method calls
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci    // start vararg processing
1961cb0ef41Sopenharmony_ci    va_start(ap, status);
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci    u_vparseMessageWithError(locale,pattern,patternLength,source,sourceLength,ap,error,status);
1991cb0ef41Sopenharmony_ci    // end vararg processing
2001cb0ef41Sopenharmony_ci    va_end(ap);
2011cb0ef41Sopenharmony_ci}
2021cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
2031cb0ef41Sopenharmony_ciu_vparseMessageWithError(const char  *locale,
2041cb0ef41Sopenharmony_ci                         const char16_t *pattern,
2051cb0ef41Sopenharmony_ci                         int32_t     patternLength,
2061cb0ef41Sopenharmony_ci                         const char16_t *source,
2071cb0ef41Sopenharmony_ci                         int32_t     sourceLength,
2081cb0ef41Sopenharmony_ci                         va_list     ap,
2091cb0ef41Sopenharmony_ci                         UParseError *error,
2101cb0ef41Sopenharmony_ci                         UErrorCode* status)
2111cb0ef41Sopenharmony_ci{
2121cb0ef41Sopenharmony_ci    //argument checking deferred to subsequent method calls
2131cb0ef41Sopenharmony_ci    UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,error,status);
2141cb0ef41Sopenharmony_ci    int32_t count = 0;
2151cb0ef41Sopenharmony_ci    umsg_vparse(fmt,source,sourceLength,&count,ap,status);
2161cb0ef41Sopenharmony_ci    umsg_close(fmt);
2171cb0ef41Sopenharmony_ci}
2181cb0ef41Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////
2191cb0ef41Sopenharmony_ci//
2201cb0ef41Sopenharmony_ci//  Message format C API
2211cb0ef41Sopenharmony_ci//
2221cb0ef41Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ciU_CAPI UMessageFormat* U_EXPORT2
2261cb0ef41Sopenharmony_ciumsg_open(  const char16_t  *pattern,
2271cb0ef41Sopenharmony_ci            int32_t         patternLength,
2281cb0ef41Sopenharmony_ci            const  char     *locale,
2291cb0ef41Sopenharmony_ci            UParseError     *parseError,
2301cb0ef41Sopenharmony_ci            UErrorCode      *status)
2311cb0ef41Sopenharmony_ci{
2321cb0ef41Sopenharmony_ci    //check arguments
2331cb0ef41Sopenharmony_ci    if(status==nullptr || U_FAILURE(*status))
2341cb0ef41Sopenharmony_ci    {
2351cb0ef41Sopenharmony_ci      return 0;
2361cb0ef41Sopenharmony_ci    }
2371cb0ef41Sopenharmony_ci    if(pattern==nullptr||patternLength<-1){
2381cb0ef41Sopenharmony_ci        *status=U_ILLEGAL_ARGUMENT_ERROR;
2391cb0ef41Sopenharmony_ci        return 0;
2401cb0ef41Sopenharmony_ci    }
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci    UParseError tErr;
2431cb0ef41Sopenharmony_ci    if(parseError==nullptr)
2441cb0ef41Sopenharmony_ci    {
2451cb0ef41Sopenharmony_ci        parseError = &tErr;
2461cb0ef41Sopenharmony_ci    }
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci    int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
2491cb0ef41Sopenharmony_ci    UnicodeString patString(patternLength == -1, pattern, len);
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci    MessageFormat* retVal = new MessageFormat(patString,Locale(locale),*parseError,*status);
2521cb0ef41Sopenharmony_ci    if(retVal == nullptr) {
2531cb0ef41Sopenharmony_ci        *status = U_MEMORY_ALLOCATION_ERROR;
2541cb0ef41Sopenharmony_ci        return nullptr;
2551cb0ef41Sopenharmony_ci    }
2561cb0ef41Sopenharmony_ci    if (U_SUCCESS(*status) && MessageFormatAdapter::hasArgTypeConflicts(*retVal)) {
2571cb0ef41Sopenharmony_ci        *status = U_ARGUMENT_TYPE_MISMATCH;
2581cb0ef41Sopenharmony_ci    }
2591cb0ef41Sopenharmony_ci    return (UMessageFormat*)retVal;
2601cb0ef41Sopenharmony_ci}
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
2631cb0ef41Sopenharmony_ciumsg_close(UMessageFormat* format)
2641cb0ef41Sopenharmony_ci{
2651cb0ef41Sopenharmony_ci    //check arguments
2661cb0ef41Sopenharmony_ci    if(format==nullptr){
2671cb0ef41Sopenharmony_ci        return;
2681cb0ef41Sopenharmony_ci    }
2691cb0ef41Sopenharmony_ci    delete (MessageFormat*) format;
2701cb0ef41Sopenharmony_ci}
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ciU_CAPI UMessageFormat U_EXPORT2
2731cb0ef41Sopenharmony_ciumsg_clone(const UMessageFormat *fmt,
2741cb0ef41Sopenharmony_ci           UErrorCode *status)
2751cb0ef41Sopenharmony_ci{
2761cb0ef41Sopenharmony_ci    //check arguments
2771cb0ef41Sopenharmony_ci    if(status==nullptr || U_FAILURE(*status)){
2781cb0ef41Sopenharmony_ci        return nullptr;
2791cb0ef41Sopenharmony_ci    }
2801cb0ef41Sopenharmony_ci    if(fmt==nullptr){
2811cb0ef41Sopenharmony_ci        *status = U_ILLEGAL_ARGUMENT_ERROR;
2821cb0ef41Sopenharmony_ci        return nullptr;
2831cb0ef41Sopenharmony_ci    }
2841cb0ef41Sopenharmony_ci    UMessageFormat retVal = (UMessageFormat)((MessageFormat*)fmt)->clone();
2851cb0ef41Sopenharmony_ci    if(retVal == 0) {
2861cb0ef41Sopenharmony_ci        *status = U_MEMORY_ALLOCATION_ERROR;
2871cb0ef41Sopenharmony_ci        return 0;
2881cb0ef41Sopenharmony_ci    }
2891cb0ef41Sopenharmony_ci    return retVal;
2901cb0ef41Sopenharmony_ci}
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
2931cb0ef41Sopenharmony_ciumsg_setLocale(UMessageFormat *fmt, const char* locale)
2941cb0ef41Sopenharmony_ci{
2951cb0ef41Sopenharmony_ci    //check arguments
2961cb0ef41Sopenharmony_ci    if(fmt==nullptr){
2971cb0ef41Sopenharmony_ci        return;
2981cb0ef41Sopenharmony_ci    }
2991cb0ef41Sopenharmony_ci    ((MessageFormat*)fmt)->setLocale(Locale(locale));
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ciU_CAPI const char*  U_EXPORT2
3031cb0ef41Sopenharmony_ciumsg_getLocale(const UMessageFormat *fmt)
3041cb0ef41Sopenharmony_ci{
3051cb0ef41Sopenharmony_ci    //check arguments
3061cb0ef41Sopenharmony_ci    if(fmt==nullptr){
3071cb0ef41Sopenharmony_ci        return "";
3081cb0ef41Sopenharmony_ci    }
3091cb0ef41Sopenharmony_ci    return ((const MessageFormat*)fmt)->getLocale().getName();
3101cb0ef41Sopenharmony_ci}
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ciU_CAPI void  U_EXPORT2
3131cb0ef41Sopenharmony_ciumsg_applyPattern(UMessageFormat *fmt,
3141cb0ef41Sopenharmony_ci                           const char16_t* pattern,
3151cb0ef41Sopenharmony_ci                           int32_t patternLength,
3161cb0ef41Sopenharmony_ci                           UParseError* parseError,
3171cb0ef41Sopenharmony_ci                           UErrorCode* status)
3181cb0ef41Sopenharmony_ci{
3191cb0ef41Sopenharmony_ci    //check arguments
3201cb0ef41Sopenharmony_ci    UParseError tErr;
3211cb0ef41Sopenharmony_ci    if(status ==nullptr||U_FAILURE(*status)){
3221cb0ef41Sopenharmony_ci        return ;
3231cb0ef41Sopenharmony_ci    }
3241cb0ef41Sopenharmony_ci    if(fmt==nullptr || (pattern==nullptr && patternLength!=0) || patternLength<-1) {
3251cb0ef41Sopenharmony_ci        *status=U_ILLEGAL_ARGUMENT_ERROR;
3261cb0ef41Sopenharmony_ci        return ;
3271cb0ef41Sopenharmony_ci    }
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci    if(parseError==nullptr){
3301cb0ef41Sopenharmony_ci      parseError = &tErr;
3311cb0ef41Sopenharmony_ci    }
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci    // UnicodeString(pattern, -1) calls u_strlen().
3341cb0ef41Sopenharmony_ci    ((MessageFormat*)fmt)->applyPattern(UnicodeString(pattern,patternLength),*parseError,*status);
3351cb0ef41Sopenharmony_ci}
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ciU_CAPI int32_t  U_EXPORT2
3381cb0ef41Sopenharmony_ciumsg_toPattern(const UMessageFormat *fmt,
3391cb0ef41Sopenharmony_ci               char16_t* result,
3401cb0ef41Sopenharmony_ci               int32_t resultLength,
3411cb0ef41Sopenharmony_ci               UErrorCode* status)
3421cb0ef41Sopenharmony_ci{
3431cb0ef41Sopenharmony_ci    //check arguments
3441cb0ef41Sopenharmony_ci    if(status ==nullptr||U_FAILURE(*status)){
3451cb0ef41Sopenharmony_ci        return -1;
3461cb0ef41Sopenharmony_ci    }
3471cb0ef41Sopenharmony_ci    if(fmt==nullptr||resultLength<0 || (resultLength>0 && result==0)){
3481cb0ef41Sopenharmony_ci        *status=U_ILLEGAL_ARGUMENT_ERROR;
3491cb0ef41Sopenharmony_ci        return -1;
3501cb0ef41Sopenharmony_ci    }
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci    UnicodeString res;
3541cb0ef41Sopenharmony_ci    if(!(result==nullptr && resultLength==0)) {
3551cb0ef41Sopenharmony_ci        // nullptr destination for pure preflighting: empty dummy string
3561cb0ef41Sopenharmony_ci        // otherwise, alias the destination buffer
3571cb0ef41Sopenharmony_ci        res.setTo(result, 0, resultLength);
3581cb0ef41Sopenharmony_ci    }
3591cb0ef41Sopenharmony_ci    ((const MessageFormat*)fmt)->toPattern(res);
3601cb0ef41Sopenharmony_ci    return res.extract(result, resultLength, *status);
3611cb0ef41Sopenharmony_ci}
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ciU_CAPI int32_t
3641cb0ef41Sopenharmony_ciumsg_format(    const UMessageFormat *fmt,
3651cb0ef41Sopenharmony_ci                char16_t       *result,
3661cb0ef41Sopenharmony_ci                int32_t        resultLength,
3671cb0ef41Sopenharmony_ci                UErrorCode     *status,
3681cb0ef41Sopenharmony_ci                ...)
3691cb0ef41Sopenharmony_ci{
3701cb0ef41Sopenharmony_ci    va_list    ap;
3711cb0ef41Sopenharmony_ci    int32_t actLen;
3721cb0ef41Sopenharmony_ci    //argument checking deferred to last method call umsg_vformat which
3731cb0ef41Sopenharmony_ci    //saves time when arguments are valid and we don't care when arguments are not
3741cb0ef41Sopenharmony_ci    //since we return an error anyway
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci    // start vararg processing
3781cb0ef41Sopenharmony_ci    va_start(ap, status);
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci    actLen = umsg_vformat(fmt,result,resultLength,ap,status);
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci    // end vararg processing
3831cb0ef41Sopenharmony_ci    va_end(ap);
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci    return actLen;
3861cb0ef41Sopenharmony_ci}
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2
3891cb0ef41Sopenharmony_ciumsg_vformat(   const UMessageFormat *fmt,
3901cb0ef41Sopenharmony_ci                char16_t       *result,
3911cb0ef41Sopenharmony_ci                int32_t        resultLength,
3921cb0ef41Sopenharmony_ci                va_list        ap,
3931cb0ef41Sopenharmony_ci                UErrorCode     *status)
3941cb0ef41Sopenharmony_ci{
3951cb0ef41Sopenharmony_ci    //check arguments
3961cb0ef41Sopenharmony_ci    if(status==0 || U_FAILURE(*status))
3971cb0ef41Sopenharmony_ci    {
3981cb0ef41Sopenharmony_ci        return -1;
3991cb0ef41Sopenharmony_ci    }
4001cb0ef41Sopenharmony_ci    if(fmt==nullptr||resultLength<0 || (resultLength>0 && result==0)) {
4011cb0ef41Sopenharmony_ci        *status=U_ILLEGAL_ARGUMENT_ERROR;
4021cb0ef41Sopenharmony_ci        return -1;
4031cb0ef41Sopenharmony_ci    }
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci    int32_t count =0;
4061cb0ef41Sopenharmony_ci    const Formattable::Type* argTypes =
4071cb0ef41Sopenharmony_ci        MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, count);
4081cb0ef41Sopenharmony_ci    // Allocate at least one element.  Allocating an array of length
4091cb0ef41Sopenharmony_ci    // zero causes problems on some platforms (e.g. Win32).
4101cb0ef41Sopenharmony_ci    Formattable* args = new Formattable[count ? count : 1];
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci    // iterate through the vararg list, and get the arguments out
4131cb0ef41Sopenharmony_ci    for(int32_t i = 0; i < count; ++i) {
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci        char16_t *stringVal;
4161cb0ef41Sopenharmony_ci        double tDouble=0;
4171cb0ef41Sopenharmony_ci        int32_t tInt =0;
4181cb0ef41Sopenharmony_ci        int64_t tInt64 = 0;
4191cb0ef41Sopenharmony_ci        UDate tempDate = 0;
4201cb0ef41Sopenharmony_ci        switch(argTypes[i]) {
4211cb0ef41Sopenharmony_ci        case Formattable::kDate:
4221cb0ef41Sopenharmony_ci            tempDate = va_arg(ap, UDate);
4231cb0ef41Sopenharmony_ci            args[i].setDate(tempDate);
4241cb0ef41Sopenharmony_ci            break;
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci        case Formattable::kDouble:
4271cb0ef41Sopenharmony_ci            tDouble =va_arg(ap, double);
4281cb0ef41Sopenharmony_ci            args[i].setDouble(tDouble);
4291cb0ef41Sopenharmony_ci            break;
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci        case Formattable::kLong:
4321cb0ef41Sopenharmony_ci            tInt = va_arg(ap, int32_t);
4331cb0ef41Sopenharmony_ci            args[i].setLong(tInt);
4341cb0ef41Sopenharmony_ci            break;
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci        case Formattable::kInt64:
4371cb0ef41Sopenharmony_ci            tInt64 = va_arg(ap, int64_t);
4381cb0ef41Sopenharmony_ci            args[i].setInt64(tInt64);
4391cb0ef41Sopenharmony_ci            break;
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci        case Formattable::kString:
4421cb0ef41Sopenharmony_ci            // For some reason, a temporary is needed
4431cb0ef41Sopenharmony_ci            stringVal = va_arg(ap, char16_t*);
4441cb0ef41Sopenharmony_ci            if(stringVal){
4451cb0ef41Sopenharmony_ci                args[i].setString(UnicodeString(stringVal));
4461cb0ef41Sopenharmony_ci            }else{
4471cb0ef41Sopenharmony_ci                *status=U_ILLEGAL_ARGUMENT_ERROR;
4481cb0ef41Sopenharmony_ci            }
4491cb0ef41Sopenharmony_ci            break;
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci        case Formattable::kArray:
4521cb0ef41Sopenharmony_ci            // throw away this argument
4531cb0ef41Sopenharmony_ci            // this is highly platform-dependent, and probably won't work
4541cb0ef41Sopenharmony_ci            // so, if you try to skip arguments in the list (and not use them)
4551cb0ef41Sopenharmony_ci            // you'll probably crash
4561cb0ef41Sopenharmony_ci            va_arg(ap, int);
4571cb0ef41Sopenharmony_ci            break;
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci        case Formattable::kObject:
4601cb0ef41Sopenharmony_ci            // Unused argument number. Read and ignore a pointer argument.
4611cb0ef41Sopenharmony_ci            va_arg(ap, void*);
4621cb0ef41Sopenharmony_ci            break;
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci        default:
4651cb0ef41Sopenharmony_ci            // Unknown/unsupported argument type.
4661cb0ef41Sopenharmony_ci            UPRV_UNREACHABLE_EXIT;
4671cb0ef41Sopenharmony_ci        }
4681cb0ef41Sopenharmony_ci    }
4691cb0ef41Sopenharmony_ci    UnicodeString resultStr;
4701cb0ef41Sopenharmony_ci    FieldPosition fieldPosition(FieldPosition::DONT_CARE);
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci    /* format the message */
4731cb0ef41Sopenharmony_ci    ((const MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status);
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_ci    delete[] args;
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ci    if(U_FAILURE(*status)){
4781cb0ef41Sopenharmony_ci        return -1;
4791cb0ef41Sopenharmony_ci    }
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci    return resultStr.extract(result, resultLength, *status);
4821cb0ef41Sopenharmony_ci}
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ciU_CAPI void
4851cb0ef41Sopenharmony_ciumsg_parse( const UMessageFormat *fmt,
4861cb0ef41Sopenharmony_ci            const char16_t *source,
4871cb0ef41Sopenharmony_ci            int32_t        sourceLength,
4881cb0ef41Sopenharmony_ci            int32_t        *count,
4891cb0ef41Sopenharmony_ci            UErrorCode     *status,
4901cb0ef41Sopenharmony_ci            ...)
4911cb0ef41Sopenharmony_ci{
4921cb0ef41Sopenharmony_ci    va_list    ap;
4931cb0ef41Sopenharmony_ci    //argument checking deferred to last method call umsg_vparse which
4941cb0ef41Sopenharmony_ci    //saves time when arguments are valid and we don't care when arguments are not
4951cb0ef41Sopenharmony_ci    //since we return an error anyway
4961cb0ef41Sopenharmony_ci
4971cb0ef41Sopenharmony_ci    // start vararg processing
4981cb0ef41Sopenharmony_ci    va_start(ap, status);
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_ci    umsg_vparse(fmt,source,sourceLength,count,ap,status);
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci    // end vararg processing
5031cb0ef41Sopenharmony_ci    va_end(ap);
5041cb0ef41Sopenharmony_ci}
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
5071cb0ef41Sopenharmony_ciumsg_vparse(const UMessageFormat *fmt,
5081cb0ef41Sopenharmony_ci            const char16_t *source,
5091cb0ef41Sopenharmony_ci            int32_t        sourceLength,
5101cb0ef41Sopenharmony_ci            int32_t        *count,
5111cb0ef41Sopenharmony_ci            va_list        ap,
5121cb0ef41Sopenharmony_ci            UErrorCode     *status)
5131cb0ef41Sopenharmony_ci{
5141cb0ef41Sopenharmony_ci    //check arguments
5151cb0ef41Sopenharmony_ci    if(status==nullptr||U_FAILURE(*status))
5161cb0ef41Sopenharmony_ci    {
5171cb0ef41Sopenharmony_ci        return;
5181cb0ef41Sopenharmony_ci    }
5191cb0ef41Sopenharmony_ci    if(fmt==nullptr||source==nullptr || sourceLength<-1 || count==nullptr){
5201cb0ef41Sopenharmony_ci        *status=U_ILLEGAL_ARGUMENT_ERROR;
5211cb0ef41Sopenharmony_ci        return;
5221cb0ef41Sopenharmony_ci    }
5231cb0ef41Sopenharmony_ci    if(sourceLength==-1){
5241cb0ef41Sopenharmony_ci        sourceLength=u_strlen(source);
5251cb0ef41Sopenharmony_ci    }
5261cb0ef41Sopenharmony_ci
5271cb0ef41Sopenharmony_ci    UnicodeString srcString(source,sourceLength);
5281cb0ef41Sopenharmony_ci    Formattable *args = ((const MessageFormat*)fmt)->parse(srcString,*count,*status);
5291cb0ef41Sopenharmony_ci    UDate *aDate;
5301cb0ef41Sopenharmony_ci    double *aDouble;
5311cb0ef41Sopenharmony_ci    char16_t *aString;
5321cb0ef41Sopenharmony_ci    int32_t* aInt;
5331cb0ef41Sopenharmony_ci    int64_t* aInt64;
5341cb0ef41Sopenharmony_ci    UnicodeString temp;
5351cb0ef41Sopenharmony_ci    int len =0;
5361cb0ef41Sopenharmony_ci    // assign formattables to varargs
5371cb0ef41Sopenharmony_ci    for(int32_t i = 0; i < *count; i++) {
5381cb0ef41Sopenharmony_ci        switch(args[i].getType()) {
5391cb0ef41Sopenharmony_ci
5401cb0ef41Sopenharmony_ci        case Formattable::kDate:
5411cb0ef41Sopenharmony_ci            aDate = va_arg(ap, UDate*);
5421cb0ef41Sopenharmony_ci            if(aDate){
5431cb0ef41Sopenharmony_ci                *aDate = args[i].getDate();
5441cb0ef41Sopenharmony_ci            }else{
5451cb0ef41Sopenharmony_ci                *status=U_ILLEGAL_ARGUMENT_ERROR;
5461cb0ef41Sopenharmony_ci            }
5471cb0ef41Sopenharmony_ci            break;
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci        case Formattable::kDouble:
5501cb0ef41Sopenharmony_ci            aDouble = va_arg(ap, double*);
5511cb0ef41Sopenharmony_ci            if(aDouble){
5521cb0ef41Sopenharmony_ci                *aDouble = args[i].getDouble();
5531cb0ef41Sopenharmony_ci            }else{
5541cb0ef41Sopenharmony_ci                *status=U_ILLEGAL_ARGUMENT_ERROR;
5551cb0ef41Sopenharmony_ci            }
5561cb0ef41Sopenharmony_ci            break;
5571cb0ef41Sopenharmony_ci
5581cb0ef41Sopenharmony_ci        case Formattable::kLong:
5591cb0ef41Sopenharmony_ci            aInt = va_arg(ap, int32_t*);
5601cb0ef41Sopenharmony_ci            if(aInt){
5611cb0ef41Sopenharmony_ci                *aInt = (int32_t) args[i].getLong();
5621cb0ef41Sopenharmony_ci            }else{
5631cb0ef41Sopenharmony_ci                *status=U_ILLEGAL_ARGUMENT_ERROR;
5641cb0ef41Sopenharmony_ci            }
5651cb0ef41Sopenharmony_ci            break;
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ci        case Formattable::kInt64:
5681cb0ef41Sopenharmony_ci            aInt64 = va_arg(ap, int64_t*);
5691cb0ef41Sopenharmony_ci            if(aInt64){
5701cb0ef41Sopenharmony_ci                *aInt64 = args[i].getInt64();
5711cb0ef41Sopenharmony_ci            }else{
5721cb0ef41Sopenharmony_ci                *status=U_ILLEGAL_ARGUMENT_ERROR;
5731cb0ef41Sopenharmony_ci            }
5741cb0ef41Sopenharmony_ci            break;
5751cb0ef41Sopenharmony_ci
5761cb0ef41Sopenharmony_ci        case Formattable::kString:
5771cb0ef41Sopenharmony_ci            aString = va_arg(ap, char16_t*);
5781cb0ef41Sopenharmony_ci            if(aString){
5791cb0ef41Sopenharmony_ci                args[i].getString(temp);
5801cb0ef41Sopenharmony_ci                len = temp.length();
5811cb0ef41Sopenharmony_ci                temp.extract(0,len,aString);
5821cb0ef41Sopenharmony_ci                aString[len]=0;
5831cb0ef41Sopenharmony_ci            }else{
5841cb0ef41Sopenharmony_ci                *status= U_ILLEGAL_ARGUMENT_ERROR;
5851cb0ef41Sopenharmony_ci            }
5861cb0ef41Sopenharmony_ci            break;
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci        case Formattable::kObject:
5891cb0ef41Sopenharmony_ci            // This will never happen because MessageFormat doesn't
5901cb0ef41Sopenharmony_ci            // support kObject.  When MessageFormat is changed to
5911cb0ef41Sopenharmony_ci            // understand MeasureFormats, modify this code to do the
5921cb0ef41Sopenharmony_ci            // right thing. [alan]
5931cb0ef41Sopenharmony_ci            UPRV_UNREACHABLE_EXIT;
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_ci        // better not happen!
5961cb0ef41Sopenharmony_ci        case Formattable::kArray:
5971cb0ef41Sopenharmony_ci            UPRV_UNREACHABLE_EXIT;
5981cb0ef41Sopenharmony_ci        }
5991cb0ef41Sopenharmony_ci    }
6001cb0ef41Sopenharmony_ci
6011cb0ef41Sopenharmony_ci    // clean up
6021cb0ef41Sopenharmony_ci    delete [] args;
6031cb0ef41Sopenharmony_ci}
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci#define SINGLE_QUOTE      ((char16_t)0x0027)
6061cb0ef41Sopenharmony_ci#define CURLY_BRACE_LEFT  ((char16_t)0x007B)
6071cb0ef41Sopenharmony_ci#define CURLY_BRACE_RIGHT ((char16_t)0x007D)
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_ci#define STATE_INITIAL 0
6101cb0ef41Sopenharmony_ci#define STATE_SINGLE_QUOTE 1
6111cb0ef41Sopenharmony_ci#define STATE_IN_QUOTE 2
6121cb0ef41Sopenharmony_ci#define STATE_MSG_ELEMENT 3
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci#define MAppend(c) if (len < destCapacity) dest[len++] = c; else len++
6151cb0ef41Sopenharmony_ci
6161cb0ef41Sopenharmony_ciint32_t umsg_autoQuoteApostrophe(const char16_t* pattern,
6171cb0ef41Sopenharmony_ci                 int32_t patternLength,
6181cb0ef41Sopenharmony_ci                 char16_t* dest,
6191cb0ef41Sopenharmony_ci                 int32_t destCapacity,
6201cb0ef41Sopenharmony_ci                 UErrorCode* ec)
6211cb0ef41Sopenharmony_ci{
6221cb0ef41Sopenharmony_ci    int32_t state = STATE_INITIAL;
6231cb0ef41Sopenharmony_ci    int32_t braceCount = 0;
6241cb0ef41Sopenharmony_ci    int32_t len = 0;
6251cb0ef41Sopenharmony_ci
6261cb0ef41Sopenharmony_ci    if (ec == nullptr || U_FAILURE(*ec)) {
6271cb0ef41Sopenharmony_ci        return -1;
6281cb0ef41Sopenharmony_ci    }
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci    if (pattern == nullptr || patternLength < -1 || (dest == nullptr && destCapacity > 0)) {
6311cb0ef41Sopenharmony_ci        *ec = U_ILLEGAL_ARGUMENT_ERROR;
6321cb0ef41Sopenharmony_ci        return -1;
6331cb0ef41Sopenharmony_ci    }
6341cb0ef41Sopenharmony_ci    U_ASSERT(destCapacity >= 0);
6351cb0ef41Sopenharmony_ci
6361cb0ef41Sopenharmony_ci    if (patternLength == -1) {
6371cb0ef41Sopenharmony_ci        patternLength = u_strlen(pattern);
6381cb0ef41Sopenharmony_ci    }
6391cb0ef41Sopenharmony_ci
6401cb0ef41Sopenharmony_ci    for (int i = 0; i < patternLength; ++i) {
6411cb0ef41Sopenharmony_ci        char16_t c = pattern[i];
6421cb0ef41Sopenharmony_ci        switch (state) {
6431cb0ef41Sopenharmony_ci        case STATE_INITIAL:
6441cb0ef41Sopenharmony_ci            switch (c) {
6451cb0ef41Sopenharmony_ci            case SINGLE_QUOTE:
6461cb0ef41Sopenharmony_ci                state = STATE_SINGLE_QUOTE;
6471cb0ef41Sopenharmony_ci                break;
6481cb0ef41Sopenharmony_ci            case CURLY_BRACE_LEFT:
6491cb0ef41Sopenharmony_ci                state = STATE_MSG_ELEMENT;
6501cb0ef41Sopenharmony_ci                ++braceCount;
6511cb0ef41Sopenharmony_ci                break;
6521cb0ef41Sopenharmony_ci            }
6531cb0ef41Sopenharmony_ci            break;
6541cb0ef41Sopenharmony_ci
6551cb0ef41Sopenharmony_ci        case STATE_SINGLE_QUOTE:
6561cb0ef41Sopenharmony_ci            switch (c) {
6571cb0ef41Sopenharmony_ci            case SINGLE_QUOTE:
6581cb0ef41Sopenharmony_ci                state = STATE_INITIAL;
6591cb0ef41Sopenharmony_ci                break;
6601cb0ef41Sopenharmony_ci            case CURLY_BRACE_LEFT:
6611cb0ef41Sopenharmony_ci            case CURLY_BRACE_RIGHT:
6621cb0ef41Sopenharmony_ci                state = STATE_IN_QUOTE;
6631cb0ef41Sopenharmony_ci                break;
6641cb0ef41Sopenharmony_ci            default:
6651cb0ef41Sopenharmony_ci                MAppend(SINGLE_QUOTE);
6661cb0ef41Sopenharmony_ci                state = STATE_INITIAL;
6671cb0ef41Sopenharmony_ci                break;
6681cb0ef41Sopenharmony_ci            }
6691cb0ef41Sopenharmony_ci        break;
6701cb0ef41Sopenharmony_ci
6711cb0ef41Sopenharmony_ci        case STATE_IN_QUOTE:
6721cb0ef41Sopenharmony_ci            switch (c) {
6731cb0ef41Sopenharmony_ci            case SINGLE_QUOTE:
6741cb0ef41Sopenharmony_ci                state = STATE_INITIAL;
6751cb0ef41Sopenharmony_ci                break;
6761cb0ef41Sopenharmony_ci            }
6771cb0ef41Sopenharmony_ci            break;
6781cb0ef41Sopenharmony_ci
6791cb0ef41Sopenharmony_ci        case STATE_MSG_ELEMENT:
6801cb0ef41Sopenharmony_ci            switch (c) {
6811cb0ef41Sopenharmony_ci            case CURLY_BRACE_LEFT:
6821cb0ef41Sopenharmony_ci                ++braceCount;
6831cb0ef41Sopenharmony_ci                break;
6841cb0ef41Sopenharmony_ci            case CURLY_BRACE_RIGHT:
6851cb0ef41Sopenharmony_ci                if (--braceCount == 0) {
6861cb0ef41Sopenharmony_ci                    state = STATE_INITIAL;
6871cb0ef41Sopenharmony_ci                }
6881cb0ef41Sopenharmony_ci                break;
6891cb0ef41Sopenharmony_ci            }
6901cb0ef41Sopenharmony_ci            break;
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_ci        default: // Never happens.
6931cb0ef41Sopenharmony_ci            break;
6941cb0ef41Sopenharmony_ci        }
6951cb0ef41Sopenharmony_ci
6961cb0ef41Sopenharmony_ci        U_ASSERT(len >= 0);
6971cb0ef41Sopenharmony_ci        MAppend(c);
6981cb0ef41Sopenharmony_ci    }
6991cb0ef41Sopenharmony_ci
7001cb0ef41Sopenharmony_ci    // End of scan
7011cb0ef41Sopenharmony_ci    if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) {
7021cb0ef41Sopenharmony_ci        MAppend(SINGLE_QUOTE);
7031cb0ef41Sopenharmony_ci    }
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_ci    return u_terminateUChars(dest, destCapacity, len, ec);
7061cb0ef41Sopenharmony_ci}
7071cb0ef41Sopenharmony_ci
7081cb0ef41Sopenharmony_ci#endif /* #if !UCONFIG_NO_FORMATTING */
709