2 *******************************************************************************
4 * Copyright (C) 1999-2004, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
10 * tab size: 8 (not used)
13 * This is a C wrapper to MessageFormat C++ API.
17 * 08/5/2001 Ram Added C wrappers for C++ API. Changed implementation of old API's
18 * Removed pattern parser.
22 #include "unicode/utypes.h"
24 #if !UCONFIG_NO_FORMATTING
26 #include "unicode/umsg.h"
27 #include "unicode/ustring.h"
28 #include "unicode/fmtable.h"
29 #include "unicode/msgfmt.h"
30 #include "unicode/unistr.h"
37 u_formatMessage(const char *locale
,
39 int32_t patternLength
,
47 //argument checking defered to subsequent method calls
48 // start vararg processing
51 actLen
= u_vformatMessage(locale
,pattern
,patternLength
,result
,resultLength
,ap
,status
);
52 // end vararg processing
58 U_CAPI
int32_t U_EXPORT2
59 u_vformatMessage( const char *locale
,
61 int32_t patternLength
,
68 //argument checking defered to subsequent method calls
69 UMessageFormat
*fmt
= umsg_open(pattern
,patternLength
,locale
,NULL
,status
);
70 int32_t retVal
= umsg_vformat(fmt
,result
,resultLength
,ap
,status
);
76 u_formatMessageWithError(const char *locale
,
78 int32_t patternLength
,
81 UParseError
*parseError
,
87 //argument checking defered to subsequent method calls
88 // start vararg processing
91 actLen
= u_vformatMessageWithError(locale
,pattern
,patternLength
,result
,resultLength
,parseError
,ap
,status
);
93 // end vararg processing
98 U_CAPI
int32_t U_EXPORT2
99 u_vformatMessageWithError( const char *locale
,
100 const UChar
*pattern
,
101 int32_t patternLength
,
103 int32_t resultLength
,
104 UParseError
*parseError
,
109 //argument checking defered to subsequent method calls
110 UMessageFormat
*fmt
= umsg_open(pattern
,patternLength
,locale
,parseError
,status
);
111 int32_t retVal
= umsg_vformat(fmt
,result
,resultLength
,ap
,status
);
117 // For parse, do the reverse of format:
118 // 1. Call through to the C++ APIs
119 // 2. Just assume the user passed in enough arguments.
120 // 3. Iterate through each formattable returned, and assign to the arguments
122 u_parseMessage( const char *locale
,
123 const UChar
*pattern
,
124 int32_t patternLength
,
126 int32_t sourceLength
,
131 //argument checking defered to subsequent method calls
133 // start vararg processing
134 va_start(ap
, status
);
136 u_vparseMessage(locale
,pattern
,patternLength
,source
,sourceLength
,ap
,status
);
137 // end vararg processing
141 U_CAPI
void U_EXPORT2
142 u_vparseMessage(const char *locale
,
143 const UChar
*pattern
,
144 int32_t patternLength
,
146 int32_t sourceLength
,
150 //argument checking defered to subsequent method calls
151 UMessageFormat
*fmt
= umsg_open(pattern
,patternLength
,locale
,NULL
,status
);
153 umsg_vparse(fmt
,source
,sourceLength
,&count
,ap
,status
);
158 u_parseMessageWithError(const char *locale
,
159 const UChar
*pattern
,
160 int32_t patternLength
,
162 int32_t sourceLength
,
169 //argument checking defered to subsequent method calls
171 // start vararg processing
172 va_start(ap
, status
);
174 u_vparseMessageWithError(locale
,pattern
,patternLength
,source
,sourceLength
,ap
,error
,status
);
175 // end vararg processing
178 U_CAPI
void U_EXPORT2
179 u_vparseMessageWithError(const char *locale
,
180 const UChar
*pattern
,
181 int32_t patternLength
,
183 int32_t sourceLength
,
188 //argument checking defered to subsequent method calls
189 UMessageFormat
*fmt
= umsg_open(pattern
,patternLength
,locale
,error
,status
);
191 umsg_vparse(fmt
,source
,sourceLength
,&count
,ap
,status
);
194 //////////////////////////////////////////////////////////////////////////////////
196 // Message format C API
198 /////////////////////////////////////////////////////////////////////////////////
201 U_CAPI UMessageFormat
* U_EXPORT2
202 umsg_open( const UChar
*pattern
,
203 int32_t patternLength
,
205 UParseError
*parseError
,
209 if(status
==NULL
|| U_FAILURE(*status
))
213 if(pattern
==NULL
||patternLength
<-1){
214 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
225 UMessageFormat
* retVal
= 0;
227 int32_t len
= (patternLength
== -1 ? u_strlen(pattern
) : patternLength
);
229 UnicodeString
patString((patternLength
== -1 ? TRUE
:FALSE
), pattern
,len
);
231 retVal
= (UMessageFormat
*) new MessageFormat(patString
,Locale(locale
),*parseError
,*status
);
234 *status
= U_MEMORY_ALLOCATION_ERROR
;
240 U_CAPI
void U_EXPORT2
241 umsg_close(UMessageFormat
* format
)
247 delete (MessageFormat
*) format
;
250 U_CAPI UMessageFormat U_EXPORT2
251 umsg_clone(const UMessageFormat
*fmt
,
255 if(status
==NULL
|| U_FAILURE(*status
)){
259 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
262 UMessageFormat retVal
= (UMessageFormat
)((MessageFormat
*)fmt
)->clone();
264 *status
= U_MEMORY_ALLOCATION_ERROR
;
270 U_CAPI
void U_EXPORT2
271 umsg_setLocale(UMessageFormat
*fmt
, const char* locale
)
277 ((MessageFormat
*)fmt
)->setLocale(Locale(locale
));
280 U_CAPI
const char* U_EXPORT2
281 umsg_getLocale(const UMessageFormat
*fmt
)
287 return ((const MessageFormat
*)fmt
)->getLocale().getName();
290 U_CAPI
void U_EXPORT2
291 umsg_applyPattern(UMessageFormat
*fmt
,
292 const UChar
* pattern
,
293 int32_t patternLength
,
294 UParseError
* parseError
,
299 if(status
==NULL
||U_FAILURE(*status
)){
302 if(fmt
==NULL
||pattern
==NULL
||patternLength
<-1){
303 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
307 if(parseError
==NULL
){
310 if(patternLength
<-1){
311 patternLength
=u_strlen(pattern
);
314 ((MessageFormat
*)fmt
)->applyPattern(UnicodeString(pattern
,patternLength
),*parseError
,*status
);
317 U_CAPI
int32_t U_EXPORT2
318 umsg_toPattern(const UMessageFormat
*fmt
,
320 int32_t resultLength
,
324 if(status
==NULL
||U_FAILURE(*status
)){
327 if(fmt
==NULL
||resultLength
<0 || (resultLength
>0 && result
==0)){
328 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
334 if(!(result
==NULL
&& resultLength
==0)) {
335 // NULL destination for pure preflighting: empty dummy string
336 // otherwise, alias the destination buffer
337 res
.setTo(result
, 0, resultLength
);
339 ((const MessageFormat
*)fmt
)->toPattern(res
);
340 return res
.extract(result
, resultLength
, *status
);
344 umsg_format( const UMessageFormat
*fmt
,
346 int32_t resultLength
,
352 //argument checking defered to last method call umsg_vformat which
353 //saves time when arguments are valid and we dont care when arguments are not
354 //since we return an error anyway
357 // start vararg processing
358 va_start(ap
, status
);
360 actLen
= umsg_vformat(fmt
,result
,resultLength
,ap
,status
);
362 // end vararg processing
370 * This class isolates our access to private internal methods of
371 * MessageFormat. It is never instantiated; it exists only for C++
374 class MessageFormatAdapter
{
376 static const Formattable::Type
* getArgTypeList(const MessageFormat
& m
,
379 const Formattable::Type
*
380 MessageFormatAdapter::getArgTypeList(const MessageFormat
& m
,
382 return m
.getArgTypeList(count
);
386 U_CAPI
int32_t U_EXPORT2
387 umsg_vformat( const UMessageFormat
*fmt
,
389 int32_t resultLength
,
394 if(status
==0 || U_FAILURE(*status
))
398 if(fmt
==NULL
||resultLength
<0 || (resultLength
>0 && result
==0)) {
399 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
404 const Formattable::Type
* argTypes
=
405 MessageFormatAdapter::getArgTypeList(*(const MessageFormat
*)fmt
, count
);
406 // Allocate at least one element. Allocating an array of length
407 // zero causes problems on some platforms (e.g. Win32).
408 Formattable
* args
= new Formattable
[count
? count
: 1];
410 // iterate through the vararg list, and get the arguments out
411 for(int32_t i
= 0; i
< count
; ++i
) {
418 switch(argTypes
[i
]) {
419 case Formattable::kDate
:
420 tempDate
= va_arg(ap
, UDate
);
421 args
[i
].setDate(tempDate
);
424 case Formattable::kDouble
:
425 tDouble
=va_arg(ap
, double);
426 args
[i
].setDouble(tDouble
);
429 case Formattable::kLong
:
430 tInt
= va_arg(ap
, int32_t);
431 args
[i
].setLong(tInt
);
434 case Formattable::kInt64
:
435 tInt64
= va_arg(ap
, int64_t);
436 args
[i
].setInt64(tInt64
);
439 case Formattable::kString
:
440 // For some reason, a temporary is needed
441 stringVal
= va_arg(ap
, UChar
*);
443 args
[i
].setString(stringVal
);
445 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
449 case Formattable::kArray
:
450 // throw away this argument
451 // this is highly platform-dependent, and probably won't work
452 // so, if you try to skip arguments in the list (and not use them)
453 // you'll probably crash
457 case Formattable::kObject
:
458 // This will never happen because MessageFormat doesn't
459 // support kObject. When MessageFormat is changed to
460 // understand MeasureFormats, modify this code to do the
461 // right thing. [alan]
466 UnicodeString resultStr
;
467 FieldPosition
fieldPosition(0);
469 /* format the message */
470 ((const MessageFormat
*)fmt
)->format(args
,count
,resultStr
,fieldPosition
,*status
);
474 if(U_FAILURE(*status
)){
478 return resultStr
.extract(result
, resultLength
, *status
);
482 umsg_parse( const UMessageFormat
*fmt
,
484 int32_t sourceLength
,
490 //argument checking defered to last method call umsg_vparse which
491 //saves time when arguments are valid and we dont care when arguments are not
492 //since we return an error anyway
494 // start vararg processing
495 va_start(ap
, status
);
497 umsg_vparse(fmt
,source
,sourceLength
,count
,ap
,status
);
499 // end vararg processing
503 U_CAPI
void U_EXPORT2
504 umsg_vparse(const UMessageFormat
*fmt
,
506 int32_t sourceLength
,
512 if(status
==NULL
||U_FAILURE(*status
))
516 if(fmt
==NULL
||source
==NULL
|| sourceLength
<-1 || count
==NULL
){
517 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
520 if(sourceLength
==-1){
521 sourceLength
=u_strlen(source
);
524 UnicodeString
srcString(source
,sourceLength
);
525 Formattable
*args
= ((const MessageFormat
*)fmt
)->parse(source
,*count
,*status
);
533 // assign formattables to varargs
534 for(int32_t i
= 0; i
< *count
; i
++) {
535 switch(args
[i
].getType()) {
537 case Formattable::kDate
:
538 aDate
= va_arg(ap
, UDate
*);
540 *aDate
= args
[i
].getDate();
542 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
546 case Formattable::kDouble
:
547 aDouble
= va_arg(ap
, double*);
549 *aDouble
= args
[i
].getDouble();
551 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
555 case Formattable::kLong
:
556 aInt
= va_arg(ap
, int32_t*);
558 *aInt
= (int32_t) args
[i
].getLong();
560 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
564 case Formattable::kInt64
:
565 aInt64
= va_arg(ap
, int64_t*);
567 *aInt64
= args
[i
].getInt64();
569 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
573 case Formattable::kString
:
574 aString
= va_arg(ap
, UChar
*);
576 args
[i
].getString(temp
);
578 temp
.extract(0,len
,aString
);
581 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
585 case Formattable::kObject
:
586 // This will never happen because MessageFormat doesn't
587 // support kObject. When MessageFormat is changed to
588 // understand MeasureFormats, modify this code to do the
589 // right thing. [alan]
593 // better not happen!
594 case Formattable::kArray
:
604 U_CAPI
const char* U_EXPORT2
605 umsg_getLocaleByType(const UMessageFormat
*fmt
,
606 ULocDataLocaleType type
,
610 if (U_SUCCESS(*status
)) {
611 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
615 return ((Format
*)fmt
)->getLocaleID(type
, *status
);
618 #endif /* #if !UCONFIG_NO_FORMATTING */