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