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