]> git.saurik.com Git - apple/icu.git/blame - icuSources/extra/ustdio/sprintf.c
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / extra / ustdio / sprintf.c
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
3*
4* Copyright (C) 1998-2003, International Business Machines
5* Corporation and others. All Rights Reserved.
6*
7*******************************************************************************
8*
9* File sprintf.c
10*
11* Modification History:
12*
13* Date Name Description
14* 02/08/2000 george Creation. Copied from uprintf.c
15* 03/27/2002 Mark Schneckloth Many fixes regarding alignment, null termination
16* (mschneckloth@atomz.com) and other various problems.
17*******************************************************************************
18*/
19
20#include "unicode/utypes.h"
21
22#if !UCONFIG_NO_FORMATTING
23
24#include "sprintf.h"
25#include "sprntf_p.h"
26#include "unicode/ustdio.h"
27#include "unicode/ustring.h"
28#include "locbund.h"
29#include "loccache.h"
30#include "unicode/unum.h"
31#include "unicode/udat.h"
32#include "unicode/uloc.h"
33
34#include "cmemory.h"
35#include <ctype.h>
36
37
38/* --- Prototypes ---------------------------- */
39
40int32_t
41u_sprintf_simple_percent_handler(u_localized_string *output,
42 const u_sprintf_spec_info *info,
43 const ufmt_args *args);
44
45int32_t
46u_sprintf_string_handler(u_localized_string *output,
47 const u_sprintf_spec_info *info,
48 const ufmt_args *args);
49
50int32_t
51u_sprintf_date_handler(u_localized_string *output,
52 const u_sprintf_spec_info *info,
53 const ufmt_args *args);
54
55int32_t
56u_sprintf_scientific_handler(u_localized_string *output,
57 const u_sprintf_spec_info *info,
58 const ufmt_args *args);
59
60int32_t
61u_sprintf_scidbl_handler(u_localized_string *output,
62 const u_sprintf_spec_info *info,
63 const ufmt_args *args);
64
65int32_t
66u_sprintf_uchar_handler(u_localized_string *output,
67 const u_sprintf_spec_info *info,
68 const ufmt_args *args);
69
70int32_t
71u_sprintf_currency_handler(u_localized_string *output,
72 const u_sprintf_spec_info *info,
73 const ufmt_args *args);
74
75int32_t
76u_sprintf_ustring_handler(u_localized_string *output,
77 const u_sprintf_spec_info *info,
78 const ufmt_args *args);
79
80int32_t
81u_sprintf_percent_handler(u_localized_string *output,
82 const u_sprintf_spec_info *info,
83 const ufmt_args *args);
84
85int32_t
86u_sprintf_time_handler(u_localized_string *output,
87 const u_sprintf_spec_info *info,
88 const ufmt_args *args);
89
90int32_t
91u_sprintf_spellout_handler(u_localized_string *output,
92 const u_sprintf_spec_info *info,
93 const ufmt_args *args);
94
95int32_t
96u_sprintf_hex_handler(u_localized_string *output,
97 const u_sprintf_spec_info *info,
98 const ufmt_args *args);
99
100int32_t
101u_sprintf_char_handler(u_localized_string *output,
102 const u_sprintf_spec_info *info,
103 const ufmt_args *args);
104
105int32_t
106u_sprintf_integer_handler(u_localized_string *output,
107 const u_sprintf_spec_info *info,
108 const ufmt_args *args);
109
110int32_t
111u_sprintf_uinteger_handler(u_localized_string *output,
112 const u_sprintf_spec_info *info,
113 const ufmt_args *args);
114
115int32_t
116u_sprintf_double_handler(u_localized_string *output,
117 const u_sprintf_spec_info *info,
118 const ufmt_args *args);
119
120int32_t
121u_sprintf_count_handler(u_localized_string *output,
122 const u_sprintf_spec_info *info,
123 const ufmt_args *args);
124
125int32_t
126u_sprintf_octal_handler(u_localized_string *output,
127 const u_sprintf_spec_info *info,
128 const ufmt_args *args);
129
130int32_t
131u_sprintf_pointer_handler(u_localized_string *output,
132 const u_sprintf_spec_info *info,
133 const ufmt_args *args);
134
135/* ANSI style formatting */
136/* Use US-ASCII characters only for formatting */
137
138/* % */
139#define UFMT_SIMPLE_PERCENT {ufmt_simple_percent, u_sprintf_simple_percent_handler}
140/* s */
141#define UFMT_STRING {ufmt_string, u_sprintf_string_handler}
142/* c */
143#define UFMT_CHAR {ufmt_char, u_sprintf_char_handler}
144/* d, i */
145#define UFMT_INT {ufmt_int, u_sprintf_integer_handler}
146/* u */
147#define UFMT_UINT {ufmt_int, u_sprintf_uinteger_handler}
148/* o */
149#define UFMT_OCTAL {ufmt_int, u_sprintf_octal_handler}
150/* x, X */
151#define UFMT_HEX {ufmt_int, u_sprintf_hex_handler}
152/* f */
153#define UFMT_DOUBLE {ufmt_double, u_sprintf_double_handler}
154/* e, E */
155#define UFMT_SCIENTIFIC {ufmt_double, u_sprintf_scientific_handler}
156/* g, G */
157#define UFMT_SCIDBL {ufmt_double, u_sprintf_scidbl_handler}
158/* n */
159#define UFMT_COUNT {ufmt_count, u_sprintf_count_handler}
160
161/* non-ANSI extensions */
162/* Use US-ASCII characters only for formatting */
163
164/* p */
165#define UFMT_POINTER {ufmt_pointer, u_sprintf_pointer_handler}
166/* D */
167#define UFMT_DATE {ufmt_date, u_sprintf_date_handler}
168/* T */
169#define UFMT_TIME {ufmt_date, u_sprintf_time_handler}
170/* V */
171#define UFMT_SPELLOUT {ufmt_double, u_sprintf_spellout_handler}
172/* P */
173#define UFMT_PERCENT {ufmt_double, u_sprintf_percent_handler}
174/* M */
175#define UFMT_CURRENCY {ufmt_double, u_sprintf_currency_handler}
176/* K */
177#define UFMT_UCHAR {ufmt_uchar, u_sprintf_uchar_handler}
178/* U */
179#define UFMT_USTRING {ufmt_ustring, u_sprintf_ustring_handler}
180
181
182#define UFMT_EMPTY {ufmt_empty, NULL}
183
184struct u_sprintf_info {
185 enum ufmt_type_info info;
186 u_sprintf_handler handler;
187};
188typedef struct u_sprintf_info u_sprintf_info;
189
190/* Use US-ASCII characters only for formatting. Most codepages have
191characters 20-7F from Unicode. Using any other codepage specific
192characters will make it very difficult to format the string on
193non-Unicode machines */
194static const u_sprintf_info g_u_sprintf_infos[108] = {
195 /* 0x20 */
196 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
197 UFMT_EMPTY, UFMT_SIMPLE_PERCENT,UFMT_EMPTY, UFMT_EMPTY,
198 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
199 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
200
201 /* 0x30 */
202 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
203 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
204 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
205 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
206
207 /* 0x40 */
208 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
209 UFMT_DATE, UFMT_SCIENTIFIC, UFMT_EMPTY, UFMT_SCIDBL,
210 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_UCHAR,
211 UFMT_EMPTY, UFMT_CURRENCY, UFMT_EMPTY, UFMT_EMPTY,
212
213 /* 0x50 */
214 UFMT_PERCENT, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
215 UFMT_TIME, UFMT_USTRING, UFMT_SPELLOUT, UFMT_EMPTY,
216 UFMT_HEX, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
217 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
218
219 /* 0x60 */
220 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_CHAR,
221 UFMT_INT, UFMT_SCIENTIFIC, UFMT_DOUBLE, UFMT_SCIDBL,
222 UFMT_EMPTY, UFMT_INT, UFMT_EMPTY, UFMT_EMPTY,
223 UFMT_EMPTY, UFMT_EMPTY, UFMT_COUNT, UFMT_OCTAL,
224
225 /* 0x70 */
226 UFMT_POINTER, UFMT_EMPTY, UFMT_EMPTY, UFMT_STRING,
227 UFMT_EMPTY, UFMT_UINT, UFMT_EMPTY, UFMT_EMPTY,
228 UFMT_HEX, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
229 UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY, UFMT_EMPTY,
230};
231
232#define USPRINTF_NUM_FMT_HANDLERS sizeof(g_u_sprintf_infos)
233
234/* We do not use handlers for 0-0x1f */
235#define USPRINTF_BASE_FMT_HANDLERS 0x20
236
237/* buffer size for formatting */
238#define USPRINTF_BUFFER_SIZE 1024
239#define USPRINTF_SYMBOL_BUFFER_SIZE 8
240
241static const UChar gNullStr[] = {0x28, 0x6E, 0x75, 0x6C, 0x6C, 0x29, 0}; /* "(null)" */
242static const UChar gSpaceStr[] = {0x20, 0}; /* " " */
243
244U_CAPI int32_t U_EXPORT2
245u_sprintf(UChar *buffer,
246 const char *locale,
247 const char *patternSpecification,
248 ... )
249{
250 va_list ap;
251 int32_t written;
252
253 va_start(ap, patternSpecification);
254 written = u_vsnprintf(buffer, INT32_MAX, locale, patternSpecification, ap);
255 va_end(ap);
256
257 return written;
258}
259
260U_CAPI int32_t U_EXPORT2
261u_sprintf_u(UChar *buffer,
262 const char *locale,
263 const UChar *patternSpecification,
264 ... )
265{
266 va_list ap;
267 int32_t written;
268
269 va_start(ap, patternSpecification);
270 written = u_vsnprintf_u(buffer, INT32_MAX, locale, patternSpecification, ap);
271 va_end(ap);
272
273 return written;
274}
275
276U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
277u_vsprintf(UChar *buffer,
278 const char *locale,
279 const char *patternSpecification,
280 va_list ap)
281{
282 return u_vsnprintf(buffer, INT32_MAX, locale, patternSpecification, ap);
283}
284
285U_CAPI int32_t U_EXPORT2
286u_snprintf(UChar *buffer,
287 int32_t count,
288 const char *locale,
289 const char *patternSpecification,
290 ... )
291{
292 va_list ap;
293 int32_t written;
294
295 va_start(ap, patternSpecification);
296 written = u_vsnprintf(buffer, count, locale, patternSpecification, ap);
297 va_end(ap);
298
299 return written;
300}
301
302U_CAPI int32_t U_EXPORT2
303u_snprintf_u(UChar *buffer,
304 int32_t count,
305 const char *locale,
306 const UChar *patternSpecification,
307 ... )
308{
309 va_list ap;
310 int32_t written;
311
312 va_start(ap, patternSpecification);
313 written = u_vsnprintf_u(buffer, count, locale, patternSpecification, ap);
314 va_end(ap);
315
316 return written;
317}
318
319U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
320u_vsnprintf(UChar *buffer,
321 int32_t count,
322 const char *locale,
323 const char *patternSpecification,
324 va_list ap)
325{
326 int32_t written;
327 UChar *pattern;
328 UChar patBuffer[UFMT_DEFAULT_BUFFER_SIZE];
329 int32_t size = (int32_t)strlen(patternSpecification) + 1;
330
331 /* convert from the default codepage to Unicode */
332 if (size >= MAX_UCHAR_BUFFER_SIZE(patBuffer)) {
333 pattern = (UChar *)uprv_malloc(size * sizeof(UChar));
334 if(pattern == 0) {
335 return 0;
336 }
337 }
338 else {
339 pattern = patBuffer;
340 }
341 ufmt_defaultCPToUnicode(patternSpecification, size, pattern, size);
342
343 /* do the work */
344 written = u_vsnprintf_u(buffer, count, locale, pattern, ap);
345
346 /* clean up */
347 if (pattern != patBuffer) {
348 uprv_free(pattern);
349 }
350
351 return written;
352}
353
354U_CAPI int32_t U_EXPORT2
355u_vsprintf_u(UChar *buffer,
356 const char *locale,
357 const UChar *patternSpecification,
358 va_list ap)
359{
360 return u_vsnprintf_u(buffer, INT32_MAX, locale, patternSpecification, ap);
361}
362
363
364static UChar *
365u_strset(UChar *str, int32_t count, UChar c) {
366 int32_t idx;
367 for(idx = 0; idx < count; ++idx) {
368 str[idx] = c;
369 }
370 return str;
371}
372
373/* copies the minimum number of code units of (count or output->available) */
374static int32_t
375u_minstrncpy(u_localized_string *output, const UChar *str, int32_t count) {
376 int32_t size = ufmt_min(count, output->available);
377
378 u_strncpy(output->str + (output->len - output->available), str, size);
379 output->available -= size;
380 return size;
381}
382
383static int32_t
384u_sprintf_pad_and_justify(u_localized_string *output,
385 const u_sprintf_spec_info *info,
386 const UChar *result,
387 int32_t resultLen)
388{
389 int32_t written = 0;
390
391 resultLen = ufmt_min(resultLen, output->available);
392
393 /* pad and justify, if needed */
394 if(info->fWidth != -1 && resultLen < info->fWidth) {
395 int32_t paddingLeft = info->fWidth - resultLen;
396 int32_t outputPos = output->len - output->available;
397
398 if (paddingLeft + resultLen > output->available) {
399 paddingLeft = output->available - resultLen;
400 if (paddingLeft < 0) {
401 paddingLeft = 0;
402 }
403 /* paddingLeft = output->available - resultLen;*/
404 }
405 written += paddingLeft;
406
407 /* left justify */
408 if(info->fLeft) {
409 written += u_minstrncpy(output, result, resultLen);
410 u_strset(&output->str[outputPos + resultLen], paddingLeft, info->fPadChar);
411 output->available -= paddingLeft;
412 }
413 /* right justify */
414 else {
415 u_strset(&output->str[outputPos], paddingLeft, info->fPadChar);
416 output->available -= paddingLeft;
417 written += u_minstrncpy(output, result, resultLen);
418 }
419 }
420 /* just write the formatted output */
421 else {
422 written = u_minstrncpy(output, result, resultLen);
423 }
424
425 return written;
426}
427
428/* Sets the sign of a format based on u_sprintf_spec_info */
429/* TODO: Is setting the prefix symbol to a positive sign a good idea in all locales? */
430static void
431u_sprintf_set_sign(UNumberFormat *format,
432 const u_sprintf_spec_info *info,
433 UErrorCode *status)
434{
435 if(info->fShowSign) {
436 if (info->fSpace) {
437 /* Setting UNUM_PLUS_SIGN_SYMBOL affects the exponent too. */
438 /* unum_setSymbol(format, UNUM_PLUS_SIGN_SYMBOL, gSpaceStr, 1, &status); */
439 unum_setTextAttribute(format, UNUM_POSITIVE_PREFIX, gSpaceStr, 1, status);
440 }
441 else {
442 UChar plusSymbol[USPRINTF_SYMBOL_BUFFER_SIZE];
443 int32_t symbolLen;
444
445 symbolLen = unum_getSymbol(format,
446 UNUM_PLUS_SIGN_SYMBOL,
447 plusSymbol,
448 sizeof(plusSymbol)/sizeof(*plusSymbol),
449 status);
450 unum_setTextAttribute(format,
451 UNUM_POSITIVE_PREFIX,
452 plusSymbol,
453 symbolLen,
454 status);
455 }
456 }
457}
458
459/* handle a '%' */
460
461int32_t
462u_sprintf_simple_percent_handler(u_localized_string *output,
463 const u_sprintf_spec_info *info,
464 const ufmt_args *args)
465{
466 /* put a single '%' on the stream */
467 if (output->available >= 1) {
468 output->str[output->len - output->available--] = 0x0025;
469 /* we wrote one character */
470 return 1;
471 }
472 return 0;
473}
474
475/* handle 's' */
476
477int32_t
478u_sprintf_string_handler(u_localized_string *output,
479 const u_sprintf_spec_info *info,
480 const ufmt_args *args)
481{
482 UChar *s;
483 UChar buffer[UFMT_DEFAULT_BUFFER_SIZE];
484 int32_t len, written;
485 int32_t argSize;
486 const char *arg = (const char*)(args[0].ptrValue);
487
488 /* convert from the default codepage to Unicode */
489 if (arg) {
490 argSize = (int32_t)strlen(arg) + 1;
491 if (argSize >= MAX_UCHAR_BUFFER_SIZE(buffer)) {
492 s = ufmt_defaultCPToUnicode(arg, argSize,
493 (UChar *)uprv_malloc(MAX_UCHAR_BUFFER_NEEDED(argSize)),
494 MAX_UCHAR_BUFFER_NEEDED(argSize));
495 if(s == NULL) {
496 return 0;
497 }
498 }
499 else {
500 s = ufmt_defaultCPToUnicode(arg, argSize, buffer,
501 sizeof(buffer)/sizeof(UChar));
502 }
503 }
504 else {
505 s = (UChar *)gNullStr;
506 }
507 len = u_strlen(s);
508
509 /* width = minimum # of characters to write */
510 /* precision = maximum # of characters to write */
511
512 /* precision takes precedence over width */
513 /* determine if the string should be truncated */
514 if(info->fPrecision != -1 && len > info->fPrecision) {
515 written = u_minstrncpy(output, s, info->fPrecision);
516 }
517 /* determine if the string should be padded */
518 else {
519 written = u_sprintf_pad_and_justify(output, info, s, len);
520 }
521
522 /* clean up */
523 if (gNullStr != s && buffer != s) {
524 uprv_free(s);
525 }
526
527 return written;
528}
529
530/* HSYS */
531int32_t
532u_sprintf_integer_handler(u_localized_string *output,
533 const u_sprintf_spec_info *info,
534 const ufmt_args *args)
535{
536 long num = (long) (args[0].intValue);
537 UNumberFormat *format;
538 UChar result [USPRINTF_BUFFER_SIZE];
539 int32_t minDigits = -1;
540 UErrorCode status = U_ZERO_ERROR;
541
542
543 /* mask off any necessary bits */
544 if(info->fIsShort)
545 num &= UINT16_MAX;
546 else if(! info->fIsLong || ! info->fIsLongLong)
547 num &= UINT32_MAX;
548
549 /* get the formatter */
550 format = u_locbund_getNumberFormat(output->fBundle);
551
552 /* handle error */
553 if(format == 0)
554 return 0;
555
556 /* set the appropriate flags on the formatter */
557
558 /* set the minimum integer digits */
559 if(info->fPrecision != -1) {
560 /* clone the stream's bundle if it isn't owned */
561 if(! output->fOwnBundle) {
562 output->fBundle = u_locbund_clone(output->fBundle);
563 output->fOwnBundle = TRUE;
564 format = u_locbund_getNumberFormat(output->fBundle);
565 }
566
567 /* set the minimum # of digits */
568 minDigits = unum_getAttribute(format, UNUM_MIN_INTEGER_DIGITS);
569 unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, info->fPrecision);
570 }
571
572 /* set whether to show the sign */
573 if(info->fShowSign) {
574 /* clone the stream's bundle if it isn't owned */
575 if(! output->fOwnBundle) {
576 output->fBundle = u_locbund_clone(output->fBundle);
577 output->fOwnBundle = TRUE;
578 format = u_locbund_getNumberFormat(output->fBundle);
579 }
580
581 u_sprintf_set_sign(format, info, &status);
582 }
583
584 /* format the number */
585 unum_format(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status);
586
587 /* restore the number format */
588 if(minDigits != -1) {
589 unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, minDigits);
590 }
591
592 return u_sprintf_pad_and_justify(output, info, result, u_strlen(result));
593}
594
595int32_t
596u_sprintf_hex_handler(u_localized_string *output,
597 const u_sprintf_spec_info *info,
598 const ufmt_args *args)
599{
600 long num = (long) (args[0].intValue);
601 UChar result [USPRINTF_BUFFER_SIZE];
602 int32_t len = USPRINTF_BUFFER_SIZE;
603
604
605 /* mask off any necessary bits */
606 if(info->fIsShort)
607 num &= UINT16_MAX;
608 else if(! info->fIsLong || ! info->fIsLongLong)
609 num &= UINT32_MAX;
610
611 /* format the number, preserving the minimum # of digits */
612 ufmt_ltou(result, &len, num, 16,
613 (UBool)(info->fSpec == 0x0078),
614 (info->fPrecision == -1 && info->fZero) ? info->fWidth : info->fPrecision);
615
616 /* convert to alt form, if desired */
617 if(num != 0 && info->fAlt && len < USPRINTF_BUFFER_SIZE - 2) {
618 /* shift the formatted string right by 2 chars */
619 memmove(result + 2, result, len * sizeof(UChar));
620 result[0] = 0x0030;
621 result[1] = info->fSpec;
622 len += 2;
623 }
624
625 return u_sprintf_pad_and_justify(output, info, result, len);
626}
627
628int32_t
629u_sprintf_octal_handler(u_localized_string *output,
630 const u_sprintf_spec_info *info,
631 const ufmt_args *args)
632{
633 long num = (long) (args[0].intValue);
634 UChar result [USPRINTF_BUFFER_SIZE];
635 int32_t len = USPRINTF_BUFFER_SIZE;
636
637
638 /* mask off any necessary bits */
639 if(info->fIsShort)
640 num &= UINT16_MAX;
641 else if(! info->fIsLong || ! info->fIsLongLong)
642 num &= UINT32_MAX;
643
644 /* format the number, preserving the minimum # of digits */
645 ufmt_ltou(result, &len, num, 8,
646 FALSE, /* doesn't matter for octal */
647 info->fPrecision == -1 && info->fZero ? info->fWidth : info->fPrecision);
648
649 /* convert to alt form, if desired */
650 if(info->fAlt && result[0] != 0x0030 && len < USPRINTF_BUFFER_SIZE - 1) {
651 /* shift the formatted string right by 1 char */
652 memmove(result + 1, result, len * sizeof(UChar));
653 result[0] = 0x0030;
654 len += 1;
655 }
656
657 return u_sprintf_pad_and_justify(output, info, result, len);
658}
659
660
661int32_t
662u_sprintf_uinteger_handler(u_localized_string *output,
663 const u_sprintf_spec_info *info,
664 const ufmt_args *args)
665{
666 u_sprintf_spec_info uint_info;
667 ufmt_args uint_args;
668
669 memcpy(&uint_info, info, sizeof(u_sprintf_spec_info));
670 memcpy(&uint_args, args, sizeof(ufmt_args));
671
672 uint_info.fPrecision = 0;
673 uint_info.fAlt = FALSE;
674
675 /* Get around int32_t limitations */
676 uint_args.doubleValue = ((double) ((uint32_t) (uint_args.intValue)));
677
678 return u_sprintf_double_handler(output, &uint_info, &uint_args);
679}
680
681int32_t
682u_sprintf_double_handler(u_localized_string *output,
683 const u_sprintf_spec_info *info,
684 const ufmt_args *args)
685{
686 double num = (double) (args[0].doubleValue);
687 UNumberFormat *format;
688 UChar result [USPRINTF_BUFFER_SIZE];
689 int32_t minDecimalDigits;
690 int32_t maxDecimalDigits;
691 UErrorCode status = U_ZERO_ERROR;
692
693 /* mask off any necessary bits */
694 /* if(! info->fIsLongDouble)
695 num &= DBL_MAX;*/
696
697 /* get the formatter */
698 format = u_locbund_getNumberFormat(output->fBundle);
699
700 /* handle error */
701 if(format == 0)
702 return 0;
703
704 /* set the appropriate flags on the formatter */
705
706 /* clone the stream's bundle if it isn't owned */
707 if(! output->fOwnBundle) {
708 output->fBundle = u_locbund_clone(output->fBundle);
709 output->fOwnBundle = TRUE;
710 format = u_locbund_getNumberFormat(output->fBundle);
711 }
712
713 /* set the number of decimal digits */
714
715 /* save the formatter's state */
716 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
717 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
718
719 if(info->fPrecision != -1) {
720 /* set the # of decimal digits */
721 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
722 }
723 else if(info->fPrecision == 0 && ! info->fAlt) {
724 /* no decimal point in this case */
725 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
726 }
727 else if(info->fAlt) {
728 /* '#' means always show decimal point */
729 /* copy of printf behavior on Solaris - '#' shows 6 digits */
730 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
731 }
732 else {
733 /* # of decimal digits is 6 if precision not specified regardless of locale */
734 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
735 }
736
737 /* set whether to show the sign */
738 u_sprintf_set_sign(format, info, &status);
739
740 /* format the number */
741 unum_formatDouble(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status);
742
743 /* restore the number format */
744 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
745 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
746
747 return u_sprintf_pad_and_justify(output, info, result, u_strlen(result));
748}
749
750
751int32_t
752u_sprintf_char_handler(u_localized_string *output,
753 const u_sprintf_spec_info *info,
754 const ufmt_args *args)
755{
756 UChar s[UTF_MAX_CHAR_LENGTH+1];
757 int32_t len, written;
758 unsigned char arg = (unsigned char)(args[0].intValue);
759
760 /* convert from default codepage to Unicode */
761 ufmt_defaultCPToUnicode((const char *)&arg, 2, s, sizeof(s)/sizeof(UChar));
762
763 /* Remember that this may be a surrogate pair */
764 len = u_strlen(s);
765
766 /* width = minimum # of characters to write */
767 /* precision = maximum # of characters to write */
768
769 /* precision takes precedence over width */
770 /* determine if the string should be truncated */
771 if(info->fPrecision != -1 && len > info->fPrecision) {
772 written = u_minstrncpy(output, s, info->fPrecision);
773 }
774 else {
775 /* determine if the string should be padded */
776 written = u_sprintf_pad_and_justify(output, info, s, len);
777 }
778
779 return written;
780}
781
782
783int32_t
784u_sprintf_pointer_handler(u_localized_string *output,
785 const u_sprintf_spec_info *info,
786 const ufmt_args *args)
787{
788 long num = (long) (args[0].intValue);
789 UChar result [USPRINTF_BUFFER_SIZE];
790 int32_t len = USPRINTF_BUFFER_SIZE;
791
792
793 /* format the pointer in hex */
794 ufmt_ltou(result, &len, num, 16, TRUE, info->fPrecision);
795
796 return u_sprintf_pad_and_justify(output, info, result, len);
797}
798
799int32_t
800u_sprintf_scientific_handler(u_localized_string *output,
801 const u_sprintf_spec_info *info,
802 const ufmt_args *args)
803{
804 double num = (double) (args[0].doubleValue);
805 UNumberFormat *format;
806 UChar result [USPRINTF_BUFFER_SIZE];
807 int32_t minDecimalDigits;
808 int32_t maxDecimalDigits;
809 UErrorCode status = U_ZERO_ERROR;
810 UChar srcExpBuf[USPRINTF_SYMBOL_BUFFER_SIZE];
811 int32_t srcLen, expLen;
812 UChar expBuf[USPRINTF_SYMBOL_BUFFER_SIZE];
813
814
815 /* mask off any necessary bits */
816 /* if(! info->fIsLongDouble)
817 num &= DBL_MAX;*/
818
819 /* get the formatter */
820 format = u_locbund_getScientificFormat(output->fBundle);
821
822 /* handle error */
823 if(format == 0)
824 return 0;
825
826 /* set the appropriate flags on the formatter */
827
828 /* clone the stream's bundle if it isn't owned */
829 if(! output->fOwnBundle) {
830 output->fBundle = u_locbund_clone(output->fBundle);
831 output->fOwnBundle = TRUE;
832 format = u_locbund_getScientificFormat(output->fBundle);
833 }
834
835 srcLen = unum_getSymbol(format,
836 UNUM_EXPONENTIAL_SYMBOL,
837 srcExpBuf,
838 sizeof(srcExpBuf),
839 &status);
840
841 /* Upper/lower case the e */
842 if (info->fSpec == (UChar)0x65 /* e */) {
843 expLen = u_strToLower(expBuf, (int32_t)sizeof(expBuf),
844 srcExpBuf, srcLen,
845 output->fBundle->fLocale,
846 &status);
847 }
848 else {
849 expLen = u_strToUpper(expBuf, (int32_t)sizeof(expBuf),
850 srcExpBuf, srcLen,
851 output->fBundle->fLocale,
852 &status);
853 }
854
855 unum_setSymbol(format,
856 UNUM_EXPONENTIAL_SYMBOL,
857 expBuf,
858 expLen,
859 &status);
860
861 /* set the number of decimal digits */
862
863 /* save the formatter's state */
864 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
865 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
866
867 if(info->fPrecision != -1) {
868 /* set the # of decimal digits */
869 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
870 }
871 else if(info->fPrecision == 0 && ! info->fAlt) {
872 /* no decimal point in this case */
873 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
874 }
875 else if(info->fAlt) {
876 /* '#' means always show decimal point */
877 /* copy of printf behavior on Solaris - '#' shows 6 digits */
878 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
879 }
880 else {
881 /* # of decimal digits is 6 if precision not specified */
882 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
883 }
884
885 /* set whether to show the sign */
886 u_sprintf_set_sign(format, info, &status);
887
888 /* format the number */
889 unum_formatDouble(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status);
890
891 /* restore the number format */
892 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
893 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
894
895 /* Since we clone the fBundle and we're only using the scientific
896 format, we don't need to save the old exponent value. */
897 /*unum_setSymbol(format,
898 UNUM_EXPONENTIAL_SYMBOL,
899 srcExpBuf,
900 srcLen,
901 &status);*/
902
903 return u_sprintf_pad_and_justify(output, info, result, u_strlen(result));
904}
905
906int32_t
907u_sprintf_date_handler(u_localized_string *output,
908 const u_sprintf_spec_info *info,
909 const ufmt_args *args)
910{
911 UDate num = (UDate) (args[0].dateValue);
912 UDateFormat *format;
913 UChar result [USPRINTF_BUFFER_SIZE];
914 UErrorCode status = U_ZERO_ERROR;
915
916
917 /* get the formatter */
918 format = u_locbund_getDateFormat(output->fBundle);
919
920 /* handle error */
921 if(format == 0)
922 return 0;
923
924 /* format the date */
925 udat_format(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status);
926
927 return u_sprintf_pad_and_justify(output, info, result, u_strlen(result));
928}
929
930int32_t
931u_sprintf_time_handler(u_localized_string *output,
932 const u_sprintf_spec_info *info,
933 const ufmt_args *args)
934{
935 UDate num = (UDate) (args[0].dateValue);
936 UDateFormat *format;
937 UChar result [USPRINTF_BUFFER_SIZE];
938 UErrorCode status = U_ZERO_ERROR;
939
940
941 /* get the formatter */
942 format = u_locbund_getTimeFormat(output->fBundle);
943
944 /* handle error */
945 if(format == 0)
946 return 0;
947
948 /* format the time */
949 udat_format(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status);
950
951 return u_sprintf_pad_and_justify(output, info, result, u_strlen(result));
952}
953
954
955int32_t
956u_sprintf_percent_handler(u_localized_string *output,
957 const u_sprintf_spec_info *info,
958 const ufmt_args *args)
959{
960 double num = (double) (args[0].doubleValue);
961 UNumberFormat *format;
962 UChar result [USPRINTF_BUFFER_SIZE];
963 int32_t minDecimalDigits;
964 int32_t maxDecimalDigits;
965 UErrorCode status = U_ZERO_ERROR;
966
967
968 /* mask off any necessary bits */
969 /* if(! info->fIsLongDouble)
970 num &= DBL_MAX;*/
971
972 /* get the formatter */
973 format = u_locbund_getPercentFormat(output->fBundle);
974
975 /* handle error */
976 if(format == 0)
977 return 0;
978
979 /* set the appropriate flags on the formatter */
980
981 /* clone the stream's bundle if it isn't owned */
982 if(! output->fOwnBundle) {
983 output->fBundle = u_locbund_clone(output->fBundle);
984 output->fOwnBundle = TRUE;
985 format = u_locbund_getPercentFormat(output->fBundle);
986 }
987
988 /* set the number of decimal digits */
989
990 /* save the formatter's state */
991 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
992 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
993
994 if(info->fPrecision != -1) {
995 /* set the # of decimal digits */
996 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
997 }
998 else if(info->fPrecision == 0 && ! info->fAlt) {
999 /* no decimal point in this case */
1000 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
1001 }
1002 else if(info->fAlt) {
1003 /* '#' means always show decimal point */
1004 /* copy of printf behavior on Solaris - '#' shows 6 digits */
1005 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
1006 }
1007 else {
1008 /* # of decimal digits is 6 if precision not specified */
1009 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
1010 }
1011
1012 /* set whether to show the sign */
1013 u_sprintf_set_sign(format, info, &status);
1014
1015 /* format the number */
1016 unum_formatDouble(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status);
1017
1018 /* restore the number format */
1019 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
1020 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
1021
1022 return u_sprintf_pad_and_justify(output, info, result, u_strlen(result));
1023}
1024
1025
1026int32_t
1027u_sprintf_currency_handler(u_localized_string *output,
1028 const u_sprintf_spec_info *info,
1029 const ufmt_args *args)
1030{
1031 double num = (double) (args[0].doubleValue);
1032 UNumberFormat *format;
1033 UChar result [USPRINTF_BUFFER_SIZE];
1034 int32_t minDecimalDigits;
1035 int32_t maxDecimalDigits;
1036 UErrorCode status = U_ZERO_ERROR;
1037
1038
1039 /* mask off any necessary bits */
1040 /* if(! info->fIsLongDouble)
1041 num &= DBL_MAX;*/
1042
1043 /* get the formatter */
1044 format = u_locbund_getCurrencyFormat(output->fBundle);
1045
1046 /* handle error */
1047 if(format == 0)
1048 return 0;
1049
1050 /* set the appropriate flags on the formatter */
1051
1052 /* clone the stream's bundle if it isn't owned */
1053 if(! output->fOwnBundle) {
1054 output->fBundle = u_locbund_clone(output->fBundle);
1055 output->fOwnBundle = TRUE;
1056 format = u_locbund_getCurrencyFormat(output->fBundle);
1057 }
1058
1059 /* set the number of decimal digits */
1060
1061 /* save the formatter's state */
1062 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
1063 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
1064
1065 if(info->fPrecision != -1) {
1066 /* set the # of decimal digits */
1067 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
1068 }
1069 else if(info->fPrecision == 0 && ! info->fAlt) {
1070 /* no decimal point in this case */
1071 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
1072 }
1073 else if(info->fAlt) {
1074 /* '#' means always show decimal point */
1075 /* copy of printf behavior on Solaris - '#' shows 6 digits */
1076 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 2);
1077 }
1078 else {
1079 /* # of decimal digits is 2 if precision not specified, 2 is typical */
1080 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 2);
1081 }
1082
1083 /* set whether to show the sign */
1084 u_sprintf_set_sign(format, info, &status);
1085
1086 /* format the number */
1087 unum_formatDouble(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status);
1088
1089 /* restore the number format */
1090 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
1091 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
1092
1093 return u_sprintf_pad_and_justify(output, info, result, u_strlen(result));
1094}
1095
1096int32_t
1097u_sprintf_ustring_handler(u_localized_string *output,
1098 const u_sprintf_spec_info *info,
1099 const ufmt_args *args)
1100{
1101 int32_t len, written;
1102 const UChar *arg = (const UChar*)(args[0].ptrValue);
1103
1104 /* allocate enough space for the buffer */
1105 if (!arg) {
1106 arg = gNullStr;
1107 }
1108 len = u_strlen(arg);
1109
1110 /* width = minimum # of characters to write */
1111 /* precision = maximum # of characters to write */
1112
1113 /* precision takes precedence over width */
1114 /* determine if the string should be truncated */
1115 if(info->fPrecision != -1 && len > info->fPrecision) {
1116 written = u_minstrncpy(output, arg, info->fPrecision);
1117 }
1118 else {
1119 /* determine if the string should be padded */
1120 written = u_sprintf_pad_and_justify(output, info, arg, len);
1121 }
1122
1123 return written;
1124}
1125
1126
1127
1128int32_t
1129u_sprintf_uchar_handler(u_localized_string *output,
1130 const u_sprintf_spec_info *info,
1131 const ufmt_args *args)
1132{
1133 int32_t written = 0;
1134 UChar arg = (UChar)(args[0].intValue);
1135
1136
1137 /* width = minimum # of characters to write */
1138 /* precision = maximum # of characters to write */
1139
1140 /* precision takes precedence over width */
1141 /* determine if the char should be printed */
1142 if(info->fPrecision != -1 && info->fPrecision < 1) {
1143 /* write nothing */
1144 written = 0;
1145 }
1146 else {
1147 /* determine if the string should be padded */
1148 written = u_sprintf_pad_and_justify(output, info, &arg, 1);
1149 }
1150
1151 return written;
1152}
1153
1154int32_t
1155u_sprintf_scidbl_handler(u_localized_string *output,
1156 const u_sprintf_spec_info *info,
1157 const ufmt_args *args)
1158{
1159 u_sprintf_spec_info scidbl_info;
1160 double num = args[0].doubleValue;
1161
1162 memcpy(&scidbl_info, info, sizeof(u_sprintf_spec_info));
1163
1164 /* determine whether to use 'd', 'e' or 'f' notation */
1165 if (scidbl_info.fPrecision == -1 && num == uprv_trunc(num))
1166 {
1167 /* use 'f' notation */
1168 scidbl_info.fSpec = 0x0066;
1169 scidbl_info.fPrecision = 0;
1170 /* call the double handler */
1171 return u_sprintf_double_handler(output, &scidbl_info, args);
1172 }
1173 else if(num < 0.0001 || (scidbl_info.fPrecision < 1 && 1000000.0 <= num)
1174 || (scidbl_info.fPrecision != -1 && num > uprv_pow10(scidbl_info.fPrecision)))
1175 {
1176 /* use 'e' or 'E' notation */
1177 scidbl_info.fSpec = scidbl_info.fSpec - 2;
1178 /* call the scientific handler */
1179 return u_sprintf_scientific_handler(output, &scidbl_info, args);
1180 }
1181 else {
1182 /* use 'f' notation */
1183 scidbl_info.fSpec = 0x0066;
1184 /* call the double handler */
1185 return u_sprintf_double_handler(output, &scidbl_info, args);
1186 }
1187}
1188
1189
1190int32_t
1191u_sprintf_count_handler(u_localized_string *output,
1192 const u_sprintf_spec_info *info,
1193 const ufmt_args *args)
1194{
1195 int *count = (int*)(args[0].ptrValue);
1196
1197 /* in the special case of count, the u_printf_spec_info's width */
1198 /* will contain the # of chars written thus far */
1199 *count = info->fWidth;
1200
1201 return 0;
1202}
1203
1204
1205int32_t
1206u_sprintf_spellout_handler(u_localized_string *output,
1207 const u_sprintf_spec_info *info,
1208 const ufmt_args *args)
1209{
1210 double num = (double) (args[0].doubleValue);
1211 UNumberFormat *format;
1212 UChar result [USPRINTF_BUFFER_SIZE];
1213 int32_t minDecimalDigits;
1214 int32_t maxDecimalDigits;
1215 UErrorCode status = U_ZERO_ERROR;
1216
1217
1218 /* mask off any necessary bits */
1219 /* if(! info->fIsLongDouble)
1220 num &= DBL_MAX;*/
1221
1222 /* get the formatter */
1223 format = u_locbund_getSpelloutFormat(output->fBundle);
1224
1225 /* handle error */
1226 if(format == 0)
1227 return 0;
1228
1229 /* set the appropriate flags on the formatter */
1230
1231 /* clone the stream's bundle if it isn't owned */
1232 if(! output->fOwnBundle) {
1233 output->fBundle = u_locbund_clone(output->fBundle);
1234 output->fOwnBundle = TRUE;
1235 format = u_locbund_getSpelloutFormat(output->fBundle);
1236 }
1237
1238 /* set the number of decimal digits */
1239
1240 /* save the formatter's state */
1241 minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
1242 maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
1243
1244 if(info->fPrecision != -1) {
1245 /* set the # of decimal digits */
1246 unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
1247 }
1248 else if(info->fPrecision == 0 && ! info->fAlt) {
1249 /* no decimal point in this case */
1250 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
1251 }
1252 else if(info->fAlt) {
1253 /* '#' means always show decimal point */
1254 /* copy of printf behavior on Solaris - '#' shows 6 digits */
1255 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
1256 }
1257 else {
1258 /* # of decimal digits is 6 if precision not specified */
1259 unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
1260 }
1261
1262 /* set whether to show the sign */
1263 u_sprintf_set_sign(format, info, &status);
1264
1265 /* format the number */
1266 unum_formatDouble(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status);
1267
1268 /* restore the number format */
1269 unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
1270 unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
1271
1272 return u_sprintf_pad_and_justify(output, info, result, u_strlen(result));
1273}
1274
1275#define UP_PERCENT 0x0025
1276
1277U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
1278u_vsnprintf_u(UChar *buffer,
1279 int32_t count,
1280 const char *locale,
1281 const UChar *patternSpecification,
1282 va_list ap)
1283{
1284 const UChar *alias = patternSpecification;
1285 const UChar *lastAlias;
1286 int32_t patCount;
1287 int32_t written = 0;
1288 uint16_t handlerNum;
1289
1290 ufmt_args args;
1291 u_localized_string outStr;
1292 u_sprintf_spec spec;
1293 ufmt_type_info info;
1294 u_sprintf_handler handler;
1295
1296 if (count < 0) {
1297 count = INT32_MAX;
1298 }
1299
1300 outStr.str = buffer;
1301 outStr.len = count;
1302 outStr.available = count;
1303
1304 /* if locale is 0, use the default */
1305 if(locale == 0) {
1306 locale = uloc_getDefault();
1307 }
1308 outStr.fBundle = u_loccache_get(locale);
1309
1310 if(outStr.fBundle == 0) {
1311 return 0;
1312 }
1313 outStr.fOwnBundle = FALSE;
1314
1315 /* iterate through the pattern */
1316 while(outStr.available > 0) {
1317
1318 /* find the next '%' */
1319 lastAlias = alias;
1320 while(*alias != UP_PERCENT && *alias != 0x0000) {
1321 alias++;
1322 }
1323
1324 /* write any characters before the '%' */
1325 if(alias > lastAlias) {
1326 written += u_minstrncpy(&outStr, lastAlias, (int32_t)(alias - lastAlias));
1327 }
1328
1329 /* break if at end of string */
1330 if(*alias == 0x0000) {
1331 break;
1332 }
1333
1334 /* parse the specifier */
1335 patCount = u_sprintf_parse_spec(alias, &spec);
1336
1337 /* fill in the precision and width, if specified out of line */
1338
1339 /* width specified out of line */
1340 if(spec.fInfo.fWidth == -2) {
1341 if(spec.fWidthPos == -1) {
1342 /* read the width from the argument list */
1343 spec.fInfo.fWidth = va_arg(ap, int);
1344 }
1345 else {
1346 /* handle positional parameter */
1347 }
1348
1349 /* if it's negative, take the absolute value and set left alignment */
1350 if(spec.fInfo.fWidth < 0) {
1351 spec.fInfo.fWidth *= -1;
1352 spec.fInfo.fLeft = TRUE;
1353 }
1354 }
1355
1356 /* precision specified out of line */
1357 if(spec.fInfo.fPrecision == -2) {
1358 if(spec.fPrecisionPos == -1) {
1359 /* read the precision from the argument list */
1360 spec.fInfo.fPrecision = va_arg(ap, int);
1361 }
1362 else {
1363 /* handle positional parameter */
1364 }
1365
1366 /* if it's negative, set it to zero */
1367 if(spec.fInfo.fPrecision < 0)
1368 spec.fInfo.fPrecision = 0;
1369 }
1370
1371 handlerNum = (uint16_t)(spec.fInfo.fSpec - USPRINTF_BASE_FMT_HANDLERS);
1372 if (handlerNum < USPRINTF_NUM_FMT_HANDLERS) {
1373 /* query the info function for argument information */
1374 info = g_u_sprintf_infos[ handlerNum ].info;
1375 if(info > ufmt_simple_percent) {
1376 switch(info) {
1377 case ufmt_count:
1378 /* set the spec's width to the # of chars written */
1379 spec.fInfo.fWidth = written;
1380 case ufmt_char:
1381 case ufmt_uchar:
1382 case ufmt_int:
1383 args.intValue = va_arg(ap, int);
1384 break;
1385 case ufmt_wchar:
1386 args.wcharValue = va_arg(ap, wchar_t);
1387 break;
1388 case ufmt_string:
1389 args.ptrValue = va_arg(ap, char*);
1390 break;
1391 case ufmt_wstring:
1392 args.ptrValue = va_arg(ap, wchar_t*);
1393 break;
1394 case ufmt_ustring:
1395 args.ptrValue = va_arg(ap, UChar*);
1396 break;
1397 case ufmt_pointer:
1398 args.ptrValue = va_arg(ap, void*);
1399 break;
1400 case ufmt_float:
1401 args.floatValue = (float) va_arg(ap, double);
1402 break;
1403 case ufmt_double:
1404 args.doubleValue = va_arg(ap, double);
1405 break;
1406 case ufmt_date:
1407 args.dateValue = va_arg(ap, UDate);
1408 break;
1409 default:
1410 break; /* Should never get here */
1411 }
1412 }
1413
1414 /* call the handler function */
1415 handler = g_u_sprintf_infos[ handlerNum ].handler;
1416 if(handler != 0) {
1417 written += (*handler)(&outStr, &spec.fInfo, &args);
1418 }
1419 else {
1420 /* just echo unknown tags */
1421 written += u_minstrncpy(&outStr, lastAlias, (int32_t)(alias - lastAlias));
1422 }
1423 }
1424 else {
1425 /* just echo unknown tags */
1426 written += u_minstrncpy(&outStr, lastAlias, (int32_t)(alias - lastAlias));
1427 }
1428
1429 /* update the pointer in pattern and continue */
1430 alias += patCount;
1431 }
1432
1433 /* Terminate the buffer, if there's room. */
1434 if (outStr.available > 0) {
1435 buffer[outStr.len - outStr.available] = 0x0000;
1436 }
1437
1438 /* Release the cloned bundle, if we cloned it. */
1439 if(outStr.fOwnBundle) {
1440 u_locbund_delete(outStr.fBundle);
1441 outStr.fBundle = NULL;
1442 outStr.fOwnBundle = FALSE;
1443 }
1444
1445 /* return # of UChars written */
1446 return written;
1447}
1448
1449#endif /* #if !UCONFIG_NO_FORMATTING */