~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/extra/ustdio/sprintf.c

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

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