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