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