~ubuntu-branches/ubuntu/quantal/icu/quantal

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Yves Arrouye
  • Date: 2002-03-03 15:31:13 UTC
  • Revision ID: package-import@ubuntu.com-20020303153113-3ssceqlq45xbmbnc
Tags: upstream-2.0-2.1pre20020303
ImportĀ upstreamĀ versionĀ 2.0-2.1pre20020303

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