]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/umsg.cpp
ICU-6.2.15.tar.gz
[apple/icu.git] / icuSources / i18n / umsg.cpp
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
3*
374ca955 4* Copyright (C) 1999-2004, International Business Machines
b75a7d8f
A
5* Corporation and others. All Rights Reserved.
6*
7*******************************************************************************
8* file name: umsg.cpp
9* encoding: US-ASCII
10* tab size: 8 (not used)
11* indentation:4
12*
13* This is a C wrapper to MessageFormat C++ API.
14*
15* Change history:
16*
17* 08/5/2001 Ram Added C wrappers for C++ API. Changed implementation of old API's
18* Removed pattern parser.
19*
20*/
21
22#include "unicode/utypes.h"
23
24#if !UCONFIG_NO_FORMATTING
25
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"
31#include "cpputils.h"
374ca955 32#include "uassert.h"
b75a7d8f
A
33
34U_NAMESPACE_USE
35
36U_CAPI int32_t
37u_formatMessage(const char *locale,
38 const UChar *pattern,
39 int32_t patternLength,
40 UChar *result,
41 int32_t resultLength,
42 UErrorCode *status,
43 ...)
44{
45 va_list ap;
46 int32_t actLen;
47 //argument checking defered to subsequent method calls
48 // start vararg processing
49 va_start(ap, status);
50
51 actLen = u_vformatMessage(locale,pattern,patternLength,result,resultLength,ap,status);
52 // end vararg processing
53 va_end(ap);
54
55 return actLen;
56}
57
58U_CAPI int32_t U_EXPORT2
59u_vformatMessage( const char *locale,
60 const UChar *pattern,
61 int32_t patternLength,
62 UChar *result,
63 int32_t resultLength,
64 va_list ap,
65 UErrorCode *status)
66
67{
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);
71 umsg_close(fmt);
72 return retVal;
73}
74
75U_CAPI int32_t
76u_formatMessageWithError(const char *locale,
77 const UChar *pattern,
78 int32_t patternLength,
79 UChar *result,
80 int32_t resultLength,
81 UParseError *parseError,
82 UErrorCode *status,
83 ...)
84{
85 va_list ap;
86 int32_t actLen;
87 //argument checking defered to subsequent method calls
88 // start vararg processing
89 va_start(ap, status);
90
91 actLen = u_vformatMessageWithError(locale,pattern,patternLength,result,resultLength,parseError,ap,status);
92
93 // end vararg processing
94 va_end(ap);
95 return actLen;
96}
97
98U_CAPI int32_t U_EXPORT2
99u_vformatMessageWithError( const char *locale,
100 const UChar *pattern,
101 int32_t patternLength,
102 UChar *result,
103 int32_t resultLength,
104 UParseError *parseError,
105 va_list ap,
106 UErrorCode *status)
107
108{
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);
112 umsg_close(fmt);
113 return retVal;
114}
115
116
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
121U_CAPI void
122u_parseMessage( const char *locale,
123 const UChar *pattern,
124 int32_t patternLength,
125 const UChar *source,
126 int32_t sourceLength,
127 UErrorCode *status,
128 ...)
129{
130 va_list ap;
131 //argument checking defered to subsequent method calls
132
133 // start vararg processing
134 va_start(ap, status);
135
136 u_vparseMessage(locale,pattern,patternLength,source,sourceLength,ap,status);
137 // end vararg processing
138 va_end(ap);
139}
140
141U_CAPI void U_EXPORT2
142u_vparseMessage(const char *locale,
143 const UChar *pattern,
144 int32_t patternLength,
145 const UChar *source,
146 int32_t sourceLength,
147 va_list ap,
148 UErrorCode *status)
149{
150 //argument checking defered to subsequent method calls
151 UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,NULL,status);
152 int32_t count = 0;
153 umsg_vparse(fmt,source,sourceLength,&count,ap,status);
154 umsg_close(fmt);
155}
156
157U_CAPI void
158u_parseMessageWithError(const char *locale,
159 const UChar *pattern,
160 int32_t patternLength,
161 const UChar *source,
162 int32_t sourceLength,
163 UParseError *error,
164 UErrorCode *status,
165 ...)
166{
167 va_list ap;
168
169 //argument checking defered to subsequent method calls
170
171 // start vararg processing
172 va_start(ap, status);
173
174 u_vparseMessageWithError(locale,pattern,patternLength,source,sourceLength,ap,error,status);
175 // end vararg processing
176 va_end(ap);
177}
178U_CAPI void U_EXPORT2
179u_vparseMessageWithError(const char *locale,
180 const UChar *pattern,
181 int32_t patternLength,
182 const UChar *source,
183 int32_t sourceLength,
184 va_list ap,
185 UParseError *error,
186 UErrorCode* status)
187{
188 //argument checking defered to subsequent method calls
189 UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,error,status);
190 int32_t count = 0;
191 umsg_vparse(fmt,source,sourceLength,&count,ap,status);
192 umsg_close(fmt);
193}
194//////////////////////////////////////////////////////////////////////////////////
195//
196// Message format C API
197//
198/////////////////////////////////////////////////////////////////////////////////
199
200
201U_CAPI UMessageFormat* U_EXPORT2
202umsg_open( const UChar *pattern,
203 int32_t patternLength,
204 const char *locale,
205 UParseError *parseError,
206 UErrorCode *status)
207{
208 //check arguments
209 if(status==NULL || U_FAILURE(*status))
210 {
211 return 0;
212 }
213 if(pattern==NULL||patternLength<-1){
214 *status=U_ILLEGAL_ARGUMENT_ERROR;
215 return 0;
216 }
217
218 UParseError tErr;
219
220 if(parseError==NULL)
221 {
222 parseError = &tErr;
223 }
224
225 UMessageFormat* retVal = 0;
226
227 int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
228
229 UnicodeString patString((patternLength == -1 ? TRUE:FALSE), pattern,len);
230
374ca955 231 retVal = (UMessageFormat*) new MessageFormat(patString,Locale(locale),*parseError,*status);
b75a7d8f
A
232
233 if(retVal == 0) {
234 *status = U_MEMORY_ALLOCATION_ERROR;
235 return 0;
236 }
237 return retVal;
238}
239
240U_CAPI void U_EXPORT2
241umsg_close(UMessageFormat* format)
242{
243 //check arguments
244 if(format==NULL){
245 return;
246 }
247 delete (MessageFormat*) format;
248}
249
250U_CAPI UMessageFormat U_EXPORT2
251umsg_clone(const UMessageFormat *fmt,
252 UErrorCode *status)
253{
254 //check arguments
255 if(status==NULL || U_FAILURE(*status)){
256 return NULL;
257 }
258 if(fmt==NULL){
259 *status = U_ILLEGAL_ARGUMENT_ERROR;
260 return NULL;
261 }
262 UMessageFormat retVal = (UMessageFormat)((MessageFormat*)fmt)->clone();
263 if(retVal == 0) {
264 *status = U_MEMORY_ALLOCATION_ERROR;
265 return 0;
266 }
267 return retVal;
268}
269
270U_CAPI void U_EXPORT2
271umsg_setLocale(UMessageFormat *fmt, const char* locale)
272{
273 //check arguments
274 if(fmt==NULL){
275 return;
276 }
277 ((MessageFormat*)fmt)->setLocale(Locale(locale));
278}
279
280U_CAPI const char* U_EXPORT2
374ca955 281umsg_getLocale(const UMessageFormat *fmt)
b75a7d8f
A
282{
283 //check arguments
284 if(fmt==NULL){
285 return "";
286 }
374ca955 287 return ((const MessageFormat*)fmt)->getLocale().getName();
b75a7d8f
A
288}
289
290U_CAPI void U_EXPORT2
291umsg_applyPattern(UMessageFormat *fmt,
292 const UChar* pattern,
293 int32_t patternLength,
294 UParseError* parseError,
295 UErrorCode* status)
296{
297 //check arguments
298 UParseError tErr;
299 if(status ==NULL||U_FAILURE(*status)){
300 return ;
301 }
302 if(fmt==NULL||pattern==NULL||patternLength<-1){
303 *status=U_ILLEGAL_ARGUMENT_ERROR;
304 return ;
305 }
306
307 if(parseError==NULL){
308 parseError = &tErr;
309 }
310 if(patternLength<-1){
311 patternLength=u_strlen(pattern);
312 }
313
314 ((MessageFormat*)fmt)->applyPattern(UnicodeString(pattern,patternLength),*parseError,*status);
315}
316
317U_CAPI int32_t U_EXPORT2
374ca955 318umsg_toPattern(const UMessageFormat *fmt,
b75a7d8f
A
319 UChar* result,
320 int32_t resultLength,
321 UErrorCode* status)
322{
323 //check arguments
324 if(status ==NULL||U_FAILURE(*status)){
325 return -1;
326 }
327 if(fmt==NULL||resultLength<0 || (resultLength>0 && result==0)){
328 *status=U_ILLEGAL_ARGUMENT_ERROR;
329 return -1;
330 }
331
332
333 UnicodeString res;
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);
338 }
374ca955 339 ((const MessageFormat*)fmt)->toPattern(res);
b75a7d8f
A
340 return res.extract(result, resultLength, *status);
341}
342
343U_CAPI int32_t
374ca955 344umsg_format( const UMessageFormat *fmt,
b75a7d8f
A
345 UChar *result,
346 int32_t resultLength,
347 UErrorCode *status,
348 ...)
349{
350 va_list ap;
351 int32_t actLen;
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
355
356
357 // start vararg processing
358 va_start(ap, status);
359
360 actLen = umsg_vformat(fmt,result,resultLength,ap,status);
361
362 // end vararg processing
363 va_end(ap);
364
365 return actLen;
366}
367
368U_NAMESPACE_BEGIN
369/**
370 * This class isolates our access to private internal methods of
371 * MessageFormat. It is never instantiated; it exists only for C++
372 * access management.
373 */
374class MessageFormatAdapter {
375public:
376 static const Formattable::Type* getArgTypeList(const MessageFormat& m,
377 int32_t& count);
378};
379const Formattable::Type*
380MessageFormatAdapter::getArgTypeList(const MessageFormat& m,
381 int32_t& count) {
382 return m.getArgTypeList(count);
383}
384U_NAMESPACE_END
385
386U_CAPI int32_t U_EXPORT2
374ca955 387umsg_vformat( const UMessageFormat *fmt,
b75a7d8f
A
388 UChar *result,
389 int32_t resultLength,
390 va_list ap,
391 UErrorCode *status)
392{
393 //check arguments
394 if(status==0 || U_FAILURE(*status))
395 {
396 return -1;
397 }
398 if(fmt==NULL||resultLength<0 || (resultLength>0 && result==0)) {
399 *status=U_ILLEGAL_ARGUMENT_ERROR;
400 return -1;
401 }
402
403 int32_t count =0;
404 const Formattable::Type* argTypes =
374ca955 405 MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, count);
b75a7d8f
A
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];
409
410 // iterate through the vararg list, and get the arguments out
411 for(int32_t i = 0; i < count; ++i) {
412
413 UChar *stringVal;
414 double tDouble=0;
415 int32_t tInt =0;
374ca955 416 int64_t tInt64 = 0;
b75a7d8f
A
417 UDate tempDate = 0;
418 switch(argTypes[i]) {
419 case Formattable::kDate:
420 tempDate = va_arg(ap, UDate);
421 args[i].setDate(tempDate);
422 break;
423
424 case Formattable::kDouble:
425 tDouble =va_arg(ap, double);
426 args[i].setDouble(tDouble);
427 break;
428
429 case Formattable::kLong:
430 tInt = va_arg(ap, int32_t);
431 args[i].setLong(tInt);
432 break;
374ca955
A
433
434 case Formattable::kInt64:
435 tInt64 = va_arg(ap, int64_t);
436 args[i].setInt64(tInt64);
437 break;
b75a7d8f
A
438
439 case Formattable::kString:
440 // For some reason, a temporary is needed
441 stringVal = va_arg(ap, UChar*);
442 if(stringVal){
443 args[i].setString(stringVal);
444 }else{
445 *status=U_ILLEGAL_ARGUMENT_ERROR;
446 }
447 break;
448
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
454 va_arg(ap, int);
455 break;
456
374ca955
A
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]
462 U_ASSERT(FALSE);
463 break;
b75a7d8f
A
464 }
465 }
466 UnicodeString resultStr;
467 FieldPosition fieldPosition(0);
468
469 /* format the message */
374ca955 470 ((const MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status);
b75a7d8f
A
471
472 delete[] args;
473
474 if(U_FAILURE(*status)){
475 return -1;
476 }
477
478 return resultStr.extract(result, resultLength, *status);
479}
480
481U_CAPI void
374ca955 482umsg_parse( const UMessageFormat *fmt,
b75a7d8f
A
483 const UChar *source,
484 int32_t sourceLength,
485 int32_t *count,
486 UErrorCode *status,
487 ...)
488{
489 va_list ap;
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
493
494 // start vararg processing
495 va_start(ap, status);
496
497 umsg_vparse(fmt,source,sourceLength,count,ap,status);
498
499 // end vararg processing
500 va_end(ap);
501}
502
503U_CAPI void U_EXPORT2
374ca955 504umsg_vparse(const UMessageFormat *fmt,
b75a7d8f
A
505 const UChar *source,
506 int32_t sourceLength,
507 int32_t *count,
508 va_list ap,
509 UErrorCode *status)
510{
511 //check arguments
512 if(status==NULL||U_FAILURE(*status))
513 {
514 return;
515 }
516 if(fmt==NULL||source==NULL || sourceLength<-1 || count==NULL){
517 *status=U_ILLEGAL_ARGUMENT_ERROR;
518 return;
519 }
520 if(sourceLength==-1){
521 sourceLength=u_strlen(source);
522 }
523
524 UnicodeString srcString(source,sourceLength);
374ca955 525 Formattable *args = ((const MessageFormat*)fmt)->parse(source,*count,*status);
b75a7d8f
A
526 UDate *aDate;
527 double *aDouble;
528 UChar *aString;
529 int32_t* aInt;
374ca955 530 int64_t* aInt64;
b75a7d8f
A
531 UnicodeString temp;
532 int len =0;
533 // assign formattables to varargs
534 for(int32_t i = 0; i < *count; i++) {
535 switch(args[i].getType()) {
536
537 case Formattable::kDate:
538 aDate = va_arg(ap, UDate*);
539 if(aDate){
540 *aDate = args[i].getDate();
541 }else{
542 *status=U_ILLEGAL_ARGUMENT_ERROR;
543 }
544 break;
545
546 case Formattable::kDouble:
547 aDouble = va_arg(ap, double*);
548 if(aDouble){
549 *aDouble = args[i].getDouble();
550 }else{
551 *status=U_ILLEGAL_ARGUMENT_ERROR;
552 }
553 break;
554
555 case Formattable::kLong:
b75a7d8f
A
556 aInt = va_arg(ap, int32_t*);
557 if(aInt){
558 *aInt = (int32_t) args[i].getLong();
559 }else{
560 *status=U_ILLEGAL_ARGUMENT_ERROR;
561 }
562 break;
563
374ca955
A
564 case Formattable::kInt64:
565 aInt64 = va_arg(ap, int64_t*);
566 if(aInt64){
567 *aInt64 = args[i].getInt64();
568 }else{
569 *status=U_ILLEGAL_ARGUMENT_ERROR;
570 }
571 break;
572
b75a7d8f
A
573 case Formattable::kString:
574 aString = va_arg(ap, UChar*);
575 if(aString){
576 args[i].getString(temp);
577 len = temp.length();
578 temp.extract(0,len,aString);
579 aString[len]=0;
580 }else{
581 *status= U_ILLEGAL_ARGUMENT_ERROR;
582 }
583 break;
584
374ca955
A
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]
590 U_ASSERT(FALSE);
591 break;
592
b75a7d8f
A
593 // better not happen!
594 case Formattable::kArray:
374ca955 595 U_ASSERT(FALSE);
b75a7d8f
A
596 break;
597 }
598 }
599
600 // clean up
601 delete [] args;
602}
603
374ca955
A
604U_CAPI const char* U_EXPORT2
605umsg_getLocaleByType(const UMessageFormat *fmt,
606 ULocDataLocaleType type,
607 UErrorCode* status)
608{
609 if (fmt == NULL) {
610 if (U_SUCCESS(*status)) {
611 *status = U_ILLEGAL_ARGUMENT_ERROR;
612 }
613 return NULL;
614 }
615 return ((Format*)fmt)->getLocaleID(type, *status);
616}
617
b75a7d8f 618#endif /* #if !UCONFIG_NO_FORMATTING */