1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius*   Copyright (C) 1998-2011, International Business Machines
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* File uprntf_p.c
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Modification History:
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Date        Name        Description
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   11/23/98    stephen     Creation.
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   03/12/99    stephen     Modified for new C API.
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   08/07/2003  george      Reunify printf implementations
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
2583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#include "unicode/utf16.h"
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uprintf.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ufmt_cmn.h"
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "putilimp.h"
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* ANSI style formatting */
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Use US-ASCII characters only for formatting */
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* % */
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_SIMPLE_PERCENT {ufmt_simple_percent, u_printf_simple_percent_handler}
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* s */
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_STRING         {ufmt_string, u_printf_string_handler}
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* c */
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_CHAR           {ufmt_char, u_printf_char_handler}
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* d, i */
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_INT            {ufmt_int, u_printf_integer_handler}
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* u */
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_UINT           {ufmt_int, u_printf_uinteger_handler}
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* o */
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_OCTAL          {ufmt_int, u_printf_octal_handler}
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* x, X */
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_HEX            {ufmt_int, u_printf_hex_handler}
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* f */
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_DOUBLE         {ufmt_double, u_printf_double_handler}
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* e, E */
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_SCIENTIFIC     {ufmt_double, u_printf_scientific_handler}
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* g, G */
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_SCIDBL         {ufmt_double, u_printf_scidbl_handler}
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* n */
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_COUNT          {ufmt_count, u_printf_count_handler}
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* non-ANSI extensions */
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Use US-ASCII characters only for formatting */
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* p */
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_POINTER        {ufmt_pointer, u_printf_pointer_handler}
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* V */
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_SPELLOUT       {ufmt_double, u_printf_spellout_handler}
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* P */
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_PERCENT        {ufmt_double, u_printf_percent_handler}
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* C  K is old format */
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_UCHAR          {ufmt_uchar, u_printf_uchar_handler}
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* S  U is old format */
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_USTRING        {ufmt_ustring, u_printf_ustring_handler}
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UFMT_EMPTY {ufmt_empty, NULL}
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * A u_printf handler function.
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * A u_printf handler is responsible for handling a single u_printf
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * format specification, for example 'd' or 's'.
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param stream The UFILE to which to write output.
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param info A pointer to a <TT>u_printf_spec_info</TT> struct containing
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * information on the format specification.
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param args A pointer to the argument data
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The number of Unicode characters written to <TT>stream</TT>.
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef int32_t U_EXPORT2
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_handler(const u_printf_stream_handler  *handler,
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 void                           *context,
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 ULocaleBundle                  *formatBundle,
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 const u_printf_spec_info       *info,
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 const ufmt_args                *args);
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef struct u_printf_info {
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ufmt_type_info info;
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_printf_handler *handler;
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} u_printf_info;
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Struct encapsulating a single uprintf format specification.
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef struct u_printf_spec {
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  u_printf_spec_info    fInfo;        /* Information on this spec */
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  int32_t        fWidthPos;     /* Position of width in arg list */
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  int32_t        fPrecisionPos;    /* Position of precision in arg list */
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  int32_t        fArgPos;    /* Position of data in arg list */
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} u_printf_spec;
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UPRINTF_NUM_FMT_HANDLERS 108
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* We do not use handlers for 0-0x1f */
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UPRINTF_BASE_FMT_HANDLERS 0x20
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* buffer size for formatting */
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UPRINTF_BUFFER_SIZE 1024
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UPRINTF_SYMBOL_BUFFER_SIZE 8
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gNullStr[] = {0x28, 0x6E, 0x75, 0x6C, 0x6C, 0x29, 0}; /* "(null)" */
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gSpaceStr[] = {0x20, 0}; /* " " */
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Sets the sign of a format based on u_printf_spec_info */
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* TODO: Is setting the prefix symbol to a positive sign a good idea in all locales? */
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_set_sign(UNumberFormat        *format,
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   const u_printf_spec_info     *info,
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   UChar *prefixBuffer,
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   int32_t *prefixBufLen,
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   UErrorCode *status)
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fShowSign) {
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *prefixBufLen = unum_getTextAttribute(format,
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                              UNUM_POSITIVE_PREFIX,
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                              prefixBuffer,
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                              *prefixBufLen,
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                              status);
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (info->fSpace) {
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Setting UNUM_PLUS_SIGN_SYMBOL affects the exponent too. */
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* unum_setSymbol(format, UNUM_PLUS_SIGN_SYMBOL, gSpaceStr, 1, &status); */
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            unum_setTextAttribute(format, UNUM_POSITIVE_PREFIX, gSpaceStr, 1, status);
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UChar plusSymbol[UPRINTF_SYMBOL_BUFFER_SIZE];
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t symbolLen;
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            symbolLen = unum_getSymbol(format,
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UNUM_PLUS_SIGN_SYMBOL,
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                plusSymbol,
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                sizeof(plusSymbol)/sizeof(*plusSymbol),
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status);
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            unum_setTextAttribute(format,
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UNUM_POSITIVE_PREFIX,
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                plusSymbol,
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                symbolLen,
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status);
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *prefixBufLen = 0;
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_reset_sign(UNumberFormat        *format,
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   const u_printf_spec_info     *info,
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   UChar *prefixBuffer,
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   int32_t *prefixBufLen,
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   UErrorCode *status)
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fShowSign) {
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setTextAttribute(format,
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UNUM_POSITIVE_PREFIX,
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              prefixBuffer,
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              *prefixBufLen,
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              status);
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* handle a '%' */
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_simple_percent_handler(const u_printf_stream_handler  *handler,
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                void                           *context,
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                ULocaleBundle                  *formatBundle,
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                const u_printf_spec_info       *info,
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                const ufmt_args                *args)
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    static const UChar PERCENT[] = { UP_PERCENT };
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* put a single '%' onto the output */
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->write(context, PERCENT, 1);
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* handle 's' */
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_string_handler(const u_printf_stream_handler  *handler,
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        void                           *context,
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ULocaleBundle                  *formatBundle,
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        const u_printf_spec_info       *info,
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        const ufmt_args                *args)
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *s;
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar buffer[UFMT_DEFAULT_BUFFER_SIZE];
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len, written;
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t argSize;
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *arg = (const char*)(args[0].ptrValue);
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* convert from the default codepage to Unicode */
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (arg) {
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        argSize = (int32_t)strlen(arg) + 1;
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (argSize >= MAX_UCHAR_BUFFER_SIZE(buffer)) {
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            s = ufmt_defaultCPToUnicode(arg, argSize,
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    (UChar *)uprv_malloc(MAX_UCHAR_BUFFER_NEEDED(argSize)),
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    MAX_UCHAR_BUFFER_NEEDED(argSize));
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(s == NULL) {
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return 0;
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            s = ufmt_defaultCPToUnicode(arg, argSize, buffer,
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    sizeof(buffer)/sizeof(UChar));
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s = (UChar *)gNullStr;
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    len = u_strlen(s);
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* width = minimum # of characters to write */
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* precision = maximum # of characters to write */
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fPrecision != -1 && info->fPrecision < len) {
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        len = info->fPrecision;
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    written = handler->pad_and_justify(context, info, s, len);
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* clean up */
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (gNullStr != s && buffer != s) {
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(s);
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return written;
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_char_handler(const u_printf_stream_handler  *handler,
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      void                           *context,
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      ULocaleBundle                  *formatBundle,
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      const u_printf_spec_info       *info,
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      const ufmt_args                *args)
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
24983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius    UChar s[U16_MAX_LENGTH+1];
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len = 1, written;
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unsigned char arg = (unsigned char)(args[0].int64Value);
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* convert from default codepage to Unicode */
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ufmt_defaultCPToUnicode((const char *)&arg, 2, s, sizeof(s)/sizeof(UChar));
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Remember that this may be an MBCS character */
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (arg != 0) {
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        len = u_strlen(s);
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* width = minimum # of characters to write */
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* precision = maximum # of characters to write */
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* precision is ignored when handling a char */
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    written = handler->pad_and_justify(context, info, s, len);
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return written;
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_double_handler(const u_printf_stream_handler  *handler,
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        void                           *context,
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ULocaleBundle                  *formatBundle,
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        const u_printf_spec_info       *info,
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        const ufmt_args                *args)
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double        num         = (double) (args[0].doubleValue);
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UNumberFormat  *format;
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar          result[UPRINTF_BUFFER_SIZE];
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar          prefixBuffer[UPRINTF_BUFFER_SIZE];
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t        prefixBufferLen = sizeof(prefixBuffer);
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t        minDecimalDigits;
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t        maxDecimalDigits;
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t        resultLen;
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode     status        = U_ZERO_ERROR;
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    prefixBuffer[0] = 0;
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* mask off any necessary bits */
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*  if(! info->fIsLongDouble)
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    num &= DBL_MAX;*/
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the formatter */
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    format = u_locbund_getNumberFormat(formatBundle, UNUM_DECIMAL);
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* handle error */
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(format == 0)
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* save the formatter's state */
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set the appropriate flags and number of decimal digits on the formatter */
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fPrecision != -1) {
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* set the # of decimal digits */
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if(info->fAlt) {
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* '#' means always show decimal point */
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* copy of printf behavior on Solaris - '#' shows 6 digits */
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* # of decimal digits is 6 if precision not specified regardless of locale */
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set whether to show the sign */
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fShowSign) {
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* format the number */
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultLen = 0;
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* restore the number format */
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* TODO: Is this needed? */
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fShowSign) {
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Reset back to original value regardless of what the error was */
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode localStatus = U_ZERO_ERROR;
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->pad_and_justify(context, info, result, resultLen);
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* HSYS */
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_integer_handler(const u_printf_stream_handler  *handler,
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         void                           *context,
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         ULocaleBundle                  *formatBundle,
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const u_printf_spec_info       *info,
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const ufmt_args                *args)
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int64_t         num        = args[0].int64Value;
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UNumberFormat   *format;
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           result[UPRINTF_BUFFER_SIZE];
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           prefixBuffer[UPRINTF_BUFFER_SIZE];
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         prefixBufferLen = sizeof(prefixBuffer);
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         minDigits     = -1;
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         resultLen;
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode      status        = U_ZERO_ERROR;
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    prefixBuffer[0] = 0;
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* mask off any necessary bits */
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fIsShort)
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        num = (int16_t)num;
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (!info->fIsLongLong)
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        num = (int32_t)num;
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the formatter */
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    format = u_locbund_getNumberFormat(formatBundle, UNUM_DECIMAL);
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* handle error */
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(format == 0)
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set the appropriate flags on the formatter */
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set the minimum integer digits */
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fPrecision != -1) {
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* set the minimum # of digits */
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        minDigits = unum_getAttribute(format, UNUM_MIN_INTEGER_DIGITS);
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, info->fPrecision);
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set whether to show the sign */
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fShowSign) {
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* format the number */
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultLen = unum_formatInt64(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultLen = 0;
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* restore the number format */
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (minDigits != -1) {
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, minDigits);
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fShowSign) {
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Reset back to original value regardless of what the error was */
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode localStatus = U_ZERO_ERROR;
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->pad_and_justify(context, info, result, resultLen);
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_hex_handler(const u_printf_stream_handler  *handler,
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     void                           *context,
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     ULocaleBundle                  *formatBundle,
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     const u_printf_spec_info       *info,
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     const ufmt_args                *args)
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int64_t         num        = args[0].int64Value;
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           result[UPRINTF_BUFFER_SIZE];
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         len        = UPRINTF_BUFFER_SIZE;
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* mask off any necessary bits */
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fIsShort)
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        num &= UINT16_MAX;
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (!info->fIsLongLong)
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        num &= UINT32_MAX;
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* format the number, preserving the minimum # of digits */
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ufmt_64tou(result, &len, num, 16,
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (UBool)(info->fSpec == 0x0078),
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (info->fPrecision == -1 && info->fZero) ? info->fWidth : info->fPrecision);
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* convert to alt form, if desired */
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(num != 0 && info->fAlt && len < UPRINTF_BUFFER_SIZE - 2) {
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* shift the formatted string right by 2 chars */
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        memmove(result + 2, result, len * sizeof(UChar));
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result[0] = 0x0030;
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result[1] = info->fSpec;
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        len += 2;
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->pad_and_justify(context, info, result, len);
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_octal_handler(const u_printf_stream_handler  *handler,
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       void                           *context,
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       ULocaleBundle                  *formatBundle,
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       const u_printf_spec_info       *info,
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       const ufmt_args                *args)
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int64_t         num        = args[0].int64Value;
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           result[UPRINTF_BUFFER_SIZE];
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         len        = UPRINTF_BUFFER_SIZE;
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* mask off any necessary bits */
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fIsShort)
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        num &= UINT16_MAX;
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (!info->fIsLongLong)
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        num &= UINT32_MAX;
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* format the number, preserving the minimum # of digits */
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ufmt_64tou(result, &len, num, 8,
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        FALSE, /* doesn't matter for octal */
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        info->fPrecision == -1 && info->fZero ? info->fWidth : info->fPrecision);
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* convert to alt form, if desired */
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fAlt && result[0] != 0x0030 && len < UPRINTF_BUFFER_SIZE - 1) {
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* shift the formatted string right by 1 char */
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        memmove(result + 1, result, len * sizeof(UChar));
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result[0] = 0x0030;
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        len += 1;
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->pad_and_justify(context, info, result, len);
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_uinteger_handler(const u_printf_stream_handler *handler,
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          void                          *context,
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          ULocaleBundle                 *formatBundle,
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          const u_printf_spec_info      *info,
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          const ufmt_args               *args)
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int64_t         num        = args[0].int64Value;
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UNumberFormat   *format;
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           result[UPRINTF_BUFFER_SIZE];
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         minDigits     = -1;
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         resultLen;
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode      status        = U_ZERO_ERROR;
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* TODO: Fix this once uint64_t can be formatted. */
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fIsShort)
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        num &= UINT16_MAX;
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if (!info->fIsLongLong)
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        num &= UINT32_MAX;
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the formatter */
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    format = u_locbund_getNumberFormat(formatBundle, UNUM_DECIMAL);
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* handle error */
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(format == 0)
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set the appropriate flags on the formatter */
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set the minimum integer digits */
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fPrecision != -1) {
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* set the minimum # of digits */
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        minDigits = unum_getAttribute(format, UNUM_MIN_INTEGER_DIGITS);
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, info->fPrecision);
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* To mirror other stdio implementations, we ignore the sign argument */
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* format the number */
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultLen = unum_formatInt64(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultLen = 0;
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* restore the number format */
527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (minDigits != -1) {
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, minDigits);
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->pad_and_justify(context, info, result, resultLen);
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_pointer_handler(const u_printf_stream_handler  *handler,
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         void                           *context,
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         ULocaleBundle                  *formatBundle,
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const u_printf_spec_info       *info,
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const ufmt_args                *args)
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           result[UPRINTF_BUFFER_SIZE];
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         len  = UPRINTF_BUFFER_SIZE;
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* format the pointer in hex */
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ufmt_ptou(result, &len, args[0].ptrValue, TRUE/*, info->fPrecision*/);
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->pad_and_justify(context, info, result, len);
548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_scientific_handler(const u_printf_stream_handler  *handler,
552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            void                           *context,
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            ULocaleBundle                  *formatBundle,
554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            const u_printf_spec_info       *info,
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            const ufmt_args                *args)
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double          num         = (double) (args[0].doubleValue);
558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UNumberFormat   *format;
559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           result[UPRINTF_BUFFER_SIZE];
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           prefixBuffer[UPRINTF_BUFFER_SIZE];
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         prefixBufferLen = sizeof(prefixBuffer);
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         minDecimalDigits;
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         maxDecimalDigits;
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode      status        = U_ZERO_ERROR;
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar srcExpBuf[UPRINTF_SYMBOL_BUFFER_SIZE];
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t srcLen, expLen;
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t resultLen;
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar expBuf[UPRINTF_SYMBOL_BUFFER_SIZE];
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    prefixBuffer[0] = 0;
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* mask off any necessary bits */
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*  if(! info->fIsLongDouble)
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    num &= DBL_MAX;*/
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the formatter */
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    format = u_locbund_getNumberFormat(formatBundle, UNUM_SCIENTIFIC);
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* handle error */
580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(format == 0)
581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set the appropriate flags on the formatter */
584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    srcLen = unum_getSymbol(format,
586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UNUM_EXPONENTIAL_SYMBOL,
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srcExpBuf,
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sizeof(srcExpBuf),
589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        &status);
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Upper/lower case the e */
592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fSpec == (UChar)0x65 /* e */) {
593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        expLen = u_strToLower(expBuf, (int32_t)sizeof(expBuf),
594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            srcExpBuf, srcLen,
595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            formatBundle->fLocale,
596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &status);
597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        expLen = u_strToUpper(expBuf, (int32_t)sizeof(expBuf),
600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            srcExpBuf, srcLen,
601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            formatBundle->fLocale,
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &status);
603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unum_setSymbol(format,
606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UNUM_EXPONENTIAL_SYMBOL,
607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        expBuf,
608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        expLen,
609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        &status);
610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* save the formatter's state */
612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set the appropriate flags and number of decimal digits on the formatter */
616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fPrecision != -1) {
617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* set the # of decimal digits */
618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (info->fOrigSpec == (UChar)0x65 /* e */ || info->fOrigSpec == (UChar)0x45 /* E */) {
619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, 1);
623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, info->fPrecision);
624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if(info->fAlt) {
627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* '#' means always show decimal point */
628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* copy of printf behavior on Solaris - '#' shows 6 digits */
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* # of decimal digits is 6 if precision not specified */
633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set whether to show the sign */
637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fShowSign) {
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* format the number */
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultLen = 0;
646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* restore the number format */
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* TODO: Is this needed? */
650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Since we're the only one using the scientific
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru       format, we don't need to save the old exponent value. */
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*unum_setSymbol(format,
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UNUM_EXPONENTIAL_SYMBOL,
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srcExpBuf,
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        srcLen,
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        &status);*/
660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fShowSign) {
662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Reset back to original value regardless of what the error was */
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode localStatus = U_ZERO_ERROR;
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->pad_and_justify(context, info, result, resultLen);
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_percent_handler(const u_printf_stream_handler  *handler,
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         void                           *context,
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         ULocaleBundle                  *formatBundle,
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const u_printf_spec_info       *info,
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const ufmt_args                *args)
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double          num         = (double) (args[0].doubleValue);
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UNumberFormat   *format;
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           result[UPRINTF_BUFFER_SIZE];
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           prefixBuffer[UPRINTF_BUFFER_SIZE];
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         prefixBufferLen = sizeof(prefixBuffer);
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         minDecimalDigits;
683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         maxDecimalDigits;
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         resultLen;
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode      status        = U_ZERO_ERROR;
686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    prefixBuffer[0] = 0;
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* mask off any necessary bits */
690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*  if(! info->fIsLongDouble)
691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    num &= DBL_MAX;*/
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the formatter */
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    format = u_locbund_getNumberFormat(formatBundle, UNUM_PERCENT);
695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* handle error */
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(format == 0)
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* save the formatter's state */
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set the appropriate flags and number of decimal digits on the formatter */
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fPrecision != -1) {
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* set the # of decimal digits */
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if(info->fAlt) {
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* '#' means always show decimal point */
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* copy of printf behavior on Solaris - '#' shows 6 digits */
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* # of decimal digits is 6 if precision not specified */
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set whether to show the sign */
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fShowSign) {
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* format the number */
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultLen = 0;
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* restore the number format */
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* TODO: Is this needed? */
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fShowSign) {
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Reset back to original value regardless of what the error was */
738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode localStatus = U_ZERO_ERROR;
739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->pad_and_justify(context, info, result, resultLen);
743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_ustring_handler(const u_printf_stream_handler  *handler,
747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         void                           *context,
748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         ULocaleBundle                  *formatBundle,
749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const u_printf_spec_info       *info,
750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const ufmt_args                *args)
751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len, written;
753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *arg = (const UChar*)(args[0].ptrValue);
754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* allocate enough space for the buffer */
756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (arg == NULL) {
757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        arg = gNullStr;
758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    len = u_strlen(arg);
760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* width = minimum # of characters to write */
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* precision = maximum # of characters to write */
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fPrecision != -1 && info->fPrecision < len) {
764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        len = info->fPrecision;
765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* determine if the string should be padded */
768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    written = handler->pad_and_justify(context, info, arg, len);
769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return written;
771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_uchar_handler(const u_printf_stream_handler  *handler,
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       void                           *context,
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       ULocaleBundle                  *formatBundle,
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       const u_printf_spec_info       *info,
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       const ufmt_args                *args)
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t written = 0;
781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar arg = (UChar)(args[0].int64Value);
782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* width = minimum # of characters to write */
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* precision = maximum # of characters to write */
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* precision is ignored when handling a uchar */
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* determine if the string should be padded */
788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    written = handler->pad_and_justify(context, info, &arg, 1);
789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return written;
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_scidbl_handler(const u_printf_stream_handler  *handler,
795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        void                           *context,
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ULocaleBundle                  *formatBundle,
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        const u_printf_spec_info       *info,
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        const ufmt_args                *args)
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_printf_spec_info scidbl_info;
801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double      num = args[0].doubleValue;
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t     retVal;
80385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UNumberFormat *format;
80485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t maxSigDecimalDigits, significantDigits;
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    memcpy(&scidbl_info, info, sizeof(u_printf_spec_info));
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* determine whether to use 'd', 'e' or 'f' notation */
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (scidbl_info.fPrecision == -1 && num == uprv_trunc(num))
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* use 'f' notation */
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        scidbl_info.fSpec = 0x0066;
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        scidbl_info.fPrecision = 0;
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* call the double handler */
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        retVal = u_printf_double_handler(handler, context, formatBundle, &scidbl_info, args);
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if(num < 0.0001 || (scidbl_info.fPrecision < 1 && 1000000.0 <= num)
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        || (scidbl_info.fPrecision != -1 && num > uprv_pow10(scidbl_info.fPrecision)))
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* use 'e' or 'E' notation */
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        scidbl_info.fSpec = scidbl_info.fSpec - 2;
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (scidbl_info.fPrecision == -1) {
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            scidbl_info.fPrecision = 5;
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* call the scientific handler */
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        retVal = u_printf_scientific_handler(handler, context, formatBundle, &scidbl_info, args);
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
82985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        format = u_locbund_getNumberFormat(formatBundle, UNUM_DECIMAL);
83085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* Check for null pointer */
83185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (format == NULL) {
83285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return 0;
83385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
83485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        maxSigDecimalDigits = unum_getAttribute(format, UNUM_MAX_SIGNIFICANT_DIGITS);
83585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        significantDigits = scidbl_info.fPrecision;
836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* use 'f' notation */
838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        scidbl_info.fSpec = 0x0066;
839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (significantDigits == -1) {
840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            significantDigits = 6;
841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_SIGNIFICANT_DIGITS_USED, TRUE);
843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_MAX_SIGNIFICANT_DIGITS, significantDigits);
844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* call the double handler */
845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        retVal = u_printf_double_handler(handler, context, formatBundle, &scidbl_info, args);
846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_MAX_SIGNIFICANT_DIGITS, maxSigDecimalDigits);
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_SIGNIFICANT_DIGITS_USED, FALSE);
848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return retVal;
850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_count_handler(const u_printf_stream_handler  *handler,
854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       void                           *context,
855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       ULocaleBundle                  *formatBundle,
856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       const u_printf_spec_info       *info,
857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       const ufmt_args                *args)
858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t *count = (int32_t*)(args[0].ptrValue);
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* in the special case of count, the u_printf_spec_info's width */
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* will contain the # of chars written thus far */
863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *count = info->fWidth;
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_spellout_handler(const u_printf_stream_handler *handler,
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          void                          *context,
871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          ULocaleBundle                 *formatBundle,
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          const u_printf_spec_info      *info,
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          const ufmt_args               *args)
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double          num         = (double) (args[0].doubleValue);
876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UNumberFormat   *format;
877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           result[UPRINTF_BUFFER_SIZE];
878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar           prefixBuffer[UPRINTF_BUFFER_SIZE];
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         prefixBufferLen = sizeof(prefixBuffer);
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         minDecimalDigits;
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         maxDecimalDigits;
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t         resultLen;
883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode      status        = U_ZERO_ERROR;
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    prefixBuffer[0] = 0;
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* mask off any necessary bits */
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*  if(! info->fIsLongDouble)
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    num &= DBL_MAX;*/
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the formatter */
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    format = u_locbund_getNumberFormat(formatBundle, UNUM_SPELLOUT);
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* handle error */
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(format == 0)
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* save the formatter's state */
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set the appropriate flags and number of decimal digits on the formatter */
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(info->fPrecision != -1) {
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* set the # of decimal digits */
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else if(info->fAlt) {
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* '#' means always show decimal point */
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* copy of printf behavior on Solaris - '#' shows 6 digits */
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* # of decimal digits is 6 if precision not specified */
914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* set whether to show the sign */
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fShowSign) {
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* format the number */
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultLen = 0;
927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* restore the number format */
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* TODO: Is this needed? */
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info->fShowSign) {
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Reset back to original value regardless of what the error was */
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode localStatus = U_ZERO_ERROR;
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handler->pad_and_justify(context, info, result, resultLen);
941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Use US-ASCII characters only for formatting. Most codepages have
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru characters 20-7F from Unicode. Using any other codepage specific
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru characters will make it very difficult to format the string on
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru non-Unicode machines */
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const u_printf_info g_u_printf_infos[UPRINTF_NUM_FMT_HANDLERS] = {
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 0x20 */
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_SIMPLE_PERCENT,UFMT_EMPTY,         UFMT_EMPTY,
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 0x30 */
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 0x40 */
961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_UCHAR,
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_SCIENTIFIC,    UFMT_EMPTY,         UFMT_SCIDBL,
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef U_USE_OBSOLETE_IO_FORMATTING
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_UCHAR/*deprecated*/,
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 0x50 */
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_PERCENT,       UFMT_EMPTY,         UFMT_EMPTY,         UFMT_USTRING,
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef U_USE_OBSOLETE_IO_FORMATTING
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_USTRING/*deprecated*/,UFMT_SPELLOUT,      UFMT_EMPTY,
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_SPELLOUT,      UFMT_EMPTY,
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_HEX,           UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 0x60 */
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_CHAR,
982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_INT,           UFMT_SCIENTIFIC,    UFMT_DOUBLE,        UFMT_SCIDBL,
983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_INT,           UFMT_EMPTY,         UFMT_EMPTY,
984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_COUNT,         UFMT_OCTAL,
985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 0x70 */
987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_POINTER,       UFMT_EMPTY,         UFMT_EMPTY,         UFMT_STRING,
988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_UINT,          UFMT_EMPTY,         UFMT_EMPTY,
989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_HEX,           UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* flag characters for uprintf */
994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define FLAG_MINUS 0x002D
995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define FLAG_PLUS 0x002B
996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define FLAG_SPACE 0x0020
997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define FLAG_POUND 0x0023
998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define FLAG_ZERO  0x0030
999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define FLAG_PAREN 0x0028
1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ISFLAG(s)    (s) == FLAG_MINUS || \
1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == FLAG_PLUS || \
1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == FLAG_SPACE || \
1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == FLAG_POUND || \
1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == FLAG_ZERO || \
1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == FLAG_PAREN
1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* special characters for uprintf */
1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SPEC_ASTERISK 0x002A
1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SPEC_DOLLARSIGN 0x0024
1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SPEC_PERIOD 0x002E
1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SPEC_PERCENT 0x0025
1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* unicode digits */
1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_ZERO 0x0030
1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_ONE 0x0031
1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_TWO 0x0032
1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_THREE 0x0033
1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_FOUR 0x0034
1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_FIVE 0x0035
1021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_SIX 0x0036
1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_SEVEN 0x0037
1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_EIGHT 0x0038
1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DIGIT_NINE 0x0039
1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ISDIGIT(s)    (s) == DIGIT_ZERO || \
1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == DIGIT_ONE || \
1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == DIGIT_TWO || \
1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == DIGIT_THREE || \
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == DIGIT_FOUR || \
1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == DIGIT_FIVE || \
1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == DIGIT_SIX || \
1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == DIGIT_SEVEN || \
1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == DIGIT_EIGHT || \
1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == DIGIT_NINE
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* u_printf modifiers */
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MOD_H 0x0068
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MOD_LOWERL 0x006C
1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MOD_L 0x004C
1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ISMOD(s)    (s) == MOD_H || \
1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == MOD_LOWERL || \
1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (s) == MOD_L
104585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* Returns an array of the parsed argument type given in the format string. */
104685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic ufmt_args* parseArguments(const UChar *alias, va_list ap, UErrorCode *status) {
104785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    ufmt_args *arglist = NULL;
104885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    ufmt_type_info *typelist = NULL;
104985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UBool *islonglong = NULL;
105085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t size = 0;
105185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t pos = 0;
105285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UChar type;
105385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uint16_t handlerNum;
105485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const UChar *aliasStart = alias;
105585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
105685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* get maximum number of arguments */
105785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for(;;) {
105885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* find % */
105985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while(*alias != UP_PERCENT && *alias != 0x0000) {
106085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            alias++;
106185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
106285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
106385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(*alias == 0x0000) {
106485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
106585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
106685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
106785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        alias++;
106885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
106985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* handle the pos number */
107085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(ISDIGIT(*alias)) {
107185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
107285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* handle positional parameters */
107385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if(ISDIGIT(*alias)) {
107485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pos = (int) (*alias++ - DIGIT_ZERO);
107585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
107685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                while(ISDIGIT(*alias)) {
107785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    pos *= 10;
107885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    pos += (int) (*alias++ - DIGIT_ZERO);
107985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
108085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
108185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
108285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* if there is no '$', don't read anything */
108385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if(*alias != SPEC_DOLLARSIGN) {
108485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return NULL;
108585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
108685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
108785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return NULL;
108885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
108985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
109085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (pos > size) {
109185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            size = pos;
109285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
109385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
109485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
109585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* create the parsed argument list */
109685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    typelist = (ufmt_type_info*)uprv_malloc(sizeof(ufmt_type_info) * size);
109785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    islonglong = (UBool*)uprv_malloc(sizeof(UBool) * size);
109885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    arglist = (ufmt_args*)uprv_malloc(sizeof(ufmt_args) * size);
109985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
110085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* If malloc failed, return NULL */
110185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (!typelist || !islonglong || !arglist) {
110285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (typelist) {
110385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            uprv_free(typelist);
110485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
110585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
110685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (islonglong) {
110785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            uprv_free(islonglong);
110885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
110985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
111085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (arglist) {
111185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            uprv_free(arglist);
111285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
111385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
111485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        *status = U_MEMORY_ALLOCATION_ERROR;
111585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return NULL;
111685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
111785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
111885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* reset alias back to the beginning */
111985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    alias = aliasStart;
112085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
112185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for(;;) {
112285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* find % */
112385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while(*alias != UP_PERCENT && *alias != 0x0000) {
112485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            alias++;
112585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
112685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
112785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(*alias == 0x0000) {
112885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
112985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
113085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
113185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        alias++;
113285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
113385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* handle positional parameters */
113485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(ISDIGIT(*alias)) {
113585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            pos = (int) (*alias++ - DIGIT_ZERO);
113685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
113785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            while(ISDIGIT(*alias)) {
113885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pos *= 10;
113985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pos += (int) (*alias++ - DIGIT_ZERO);
114085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
114185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
114285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* offset position by 1 */
114385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pos--;
114485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
114585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* skip over everything except for the type */
114685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while (ISMOD(*alias) || ISFLAG(*alias) || ISDIGIT(*alias) ||
114785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            *alias == SPEC_ASTERISK || *alias == SPEC_PERIOD || *alias == SPEC_DOLLARSIGN) {
114885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                islonglong[pos] = FALSE;
114985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (ISMOD(*alias)) {
115085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    alias++;
115185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    if (*alias == MOD_LOWERL) {
115285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        islonglong[pos] = TRUE;
115385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
115485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
115585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                alias++;
115685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
115785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        type = *alias;
115885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
115985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* store the argument type in the correct position of the parsed argument list */
116085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        handlerNum = (uint16_t)(type - UPRINTF_BASE_FMT_HANDLERS);
116185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (handlerNum < UPRINTF_NUM_FMT_HANDLERS) {
116285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            typelist[pos] = g_u_printf_infos[ handlerNum ].info;
116385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
116485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            typelist[pos] = ufmt_empty;
116585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
116685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
116785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
116885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* store argument in arglist */
116985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (pos = 0; pos < size; pos++) {
117085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        switch (typelist[pos]) {
117185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        case ufmt_string:
117285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        case ufmt_ustring:
117385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        case ufmt_pointer:
117485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            arglist[pos].ptrValue = va_arg(ap, void*);
117585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
117685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        case ufmt_char:
117785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        case ufmt_uchar:
117885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        case ufmt_int:
117985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (islonglong[pos]) {
118085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                arglist[pos].int64Value = va_arg(ap, int64_t);
118185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
118285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            else {
118385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                arglist[pos].int64Value = va_arg(ap, int32_t);
118485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
118585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
118685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        case ufmt_float:
118785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            arglist[pos].floatValue = (float) va_arg(ap, double);
118885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
118985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        case ufmt_double:
119085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            arglist[pos].doubleValue = va_arg(ap, double);
119185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
119285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        default:
119385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* else args is ignored */
119485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            arglist[pos].ptrValue = NULL;
119585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            break;
119685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
119785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
119885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
119985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uprv_free(typelist);
120085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uprv_free(islonglong);
120185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
120285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return arglist;
120385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
1204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* We parse the argument list in Unicode */
1206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC int32_t
1207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruu_printf_parse(const u_printf_stream_handler *streamHandler,
1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               const UChar     *fmt,
1209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               void            *context,
1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               u_localized_print_string *locStringContext,
1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               ULocaleBundle   *formatBundle,
1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               int32_t         *written,
1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru               va_list         ap)
1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint16_t         handlerNum;
1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ufmt_args        args;
1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ufmt_type_info   argType;
1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_printf_handler *handler;
1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_printf_spec    spec;
1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_printf_spec_info *info = &(spec.fInfo);
1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *alias = fmt;
1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *backup;
1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *lastAlias;
122585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const UChar *orgAlias = fmt;
122685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* parsed argument list */
122785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    ufmt_args *arglist = NULL; /* initialized it to avoid compiler warnings */
122885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UErrorCode status = U_ZERO_ERROR;
122985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (!locStringContext || locStringContext->available >= 0) {
123085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* get the parsed list of argument types */
123185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        arglist = parseArguments(orgAlias, ap, &status);
123285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
123385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* Return error if parsing failed. */
123485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
123585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return -1;
123685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
123785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
123885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* iterate through the pattern */
124085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while(!locStringContext || locStringContext->available >= 0) {
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* find the next '%' */
1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lastAlias = alias;
1244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while(*alias != UP_PERCENT && *alias != 0x0000) {
1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            alias++;
1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* write any characters before the '%' */
1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(alias > lastAlias) {
1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *written += (streamHandler->write)(context, lastAlias, (int32_t)(alias - lastAlias));
1251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* break if at end of string */
1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(*alias == 0x0000) {
1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* initialize spec to default values */
1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        spec.fWidthPos     = -1;
1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        spec.fPrecisionPos = -1;
1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        spec.fArgPos       = -1;
1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memset(info, 0, sizeof(*info));
1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        info->fPrecision    = -1;
1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        info->fWidth        = -1;
1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        info->fPadChar      = 0x0020;
1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* skip over the initial '%' */
1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        alias++;
1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Check for positional argument */
1272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(ISDIGIT(*alias)) {
1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Save the current position */
1275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            backup = alias;
1276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* handle positional parameters */
1278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(ISDIGIT(*alias)) {
1279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                spec.fArgPos = (int) (*alias++ - DIGIT_ZERO);
1280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                while(ISDIGIT(*alias)) {
1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    spec.fArgPos *= 10;
1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    spec.fArgPos += (int) (*alias++ - DIGIT_ZERO);
1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* if there is no '$', don't read anything */
1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(*alias != SPEC_DOLLARSIGN) {
1289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                spec.fArgPos = -1;
1290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                alias = backup;
1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* munge the '$' */
1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else
1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                alias++;
1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Get any format flags */
1298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while(ISFLAG(*alias)) {
1299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            switch(*alias++) {
1300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* left justify */
1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case FLAG_MINUS:
1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fLeft = TRUE;
1304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* always show sign */
1307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case FLAG_PLUS:
1308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fShowSign = TRUE;
1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* use space if no sign present */
1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case FLAG_SPACE:
1313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fShowSign = TRUE;
1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fSpace = TRUE;
1315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* use alternate form */
1318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case FLAG_POUND:
1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fAlt = TRUE;
1320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* pad with leading zeroes */
1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case FLAG_ZERO:
1324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fZero = TRUE;
1325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fPadChar = 0x0030;
1326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* pad character specified */
1329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case FLAG_PAREN:
1330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* TODO test that all four are numbers */
1332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* first four characters are hex values for pad char */
1333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fPadChar = (UChar)ufmt_digitvalue(*alias++);
1334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*alias++));
1335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*alias++));
1336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*alias++));
1337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* final character is ignored */
1339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                alias++;
1340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Get the width */
1346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* width is specified out of line */
1348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(*alias == SPEC_ASTERISK) {
1349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            info->fWidth = -2;
1351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Skip the '*' */
1353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            alias++;
1354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Save the current position */
1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            backup = alias;
1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* handle positional parameters */
1359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(ISDIGIT(*alias)) {
1360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                spec.fWidthPos = (int) (*alias++ - DIGIT_ZERO);
1361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                while(ISDIGIT(*alias)) {
1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    spec.fWidthPos *= 10;
1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    spec.fWidthPos += (int) (*alias++ - DIGIT_ZERO);
1365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* if there is no '$', don't read anything */
1369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(*alias != SPEC_DOLLARSIGN) {
1370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                spec.fWidthPos = -1;
1371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                alias = backup;
1372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* munge the '$' */
1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else
1375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                alias++;
1376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* read the width, if present */
1378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if(ISDIGIT(*alias)){
1379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            info->fWidth = (int) (*alias++ - DIGIT_ZERO);
1380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while(ISDIGIT(*alias)) {
1382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fWidth *= 10;
1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fWidth += (int) (*alias++ - DIGIT_ZERO);
1384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Get the precision */
1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(*alias == SPEC_PERIOD) {
1390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* eat up the '.' */
1392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            alias++;
1393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* precision is specified out of line */
1395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(*alias == SPEC_ASTERISK) {
1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fPrecision = -2;
1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* Skip the '*' */
1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                alias++;
1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* save the current position */
1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                backup = alias;
1404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* handle positional parameters */
1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(ISDIGIT(*alias)) {
1407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    spec.fPrecisionPos = (int) (*alias++ - DIGIT_ZERO);
1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    while(ISDIGIT(*alias)) {
1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        spec.fPrecisionPos *= 10;
1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        spec.fPrecisionPos += (int) (*alias++ - DIGIT_ZERO);
1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* if there is no '$', don't read anything */
1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(*alias != SPEC_DOLLARSIGN) {
1416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        spec.fPrecisionPos = -1;
1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        alias = backup;
1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    else {
1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        /* munge the '$' */
1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        alias++;
1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* read the precision */
1426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else if(ISDIGIT(*alias)){
1427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fPrecision = (int) (*alias++ - DIGIT_ZERO);
1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                while(ISDIGIT(*alias)) {
1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    info->fPrecision *= 10;
1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    info->fPrecision += (int) (*alias++ - DIGIT_ZERO);
1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Get any modifiers */
1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(ISMOD(*alias)) {
1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            switch(*alias++) {
1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* short */
1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case MOD_H:
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fIsShort = TRUE;
1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* long or long long */
1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case MOD_LOWERL:
1447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(*alias == MOD_LOWERL) {
1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    info->fIsLongLong = TRUE;
1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* skip over the next 'l' */
1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    alias++;
1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                else
1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    info->fIsLong = TRUE;
1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* long double */
1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            case MOD_L:
1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fIsLongDouble = TRUE;
1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* finally, get the specifier letter */
1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        info->fSpec = *alias++;
1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        info->fOrigSpec = info->fSpec;
1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* fill in the precision and width, if specified out of line */
1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* width specified out of line */
1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(spec.fInfo.fWidth == -2) {
1471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(spec.fWidthPos == -1) {
1472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* read the width from the argument list */
1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fWidth = va_arg(ap, int32_t);
1474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* else handle positional parameter */
1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* if it's negative, take the absolute value and set left alignment */
1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(info->fWidth < 0) {
1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fWidth *= -1; /* Make positive */
1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fLeft = TRUE;
1481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* precision specified out of line */
1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(info->fPrecision == -2) {
1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(spec.fPrecisionPos == -1) {
1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* read the precision from the argument list */
1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fPrecision = va_arg(ap, int32_t);
1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* else handle positional parameter */
1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* if it's negative, set it to zero */
1493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(info->fPrecision < 0)
1494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                info->fPrecision = 0;
1495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        handlerNum = (uint16_t)(info->fSpec - UPRINTF_BASE_FMT_HANDLERS);
1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (handlerNum < UPRINTF_NUM_FMT_HANDLERS) {
1499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* query the info function for argument information */
1500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            argType = g_u_printf_infos[ handlerNum ].info;
150185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
150285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* goto the correct argument on arg_list if position is specified */
150385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (spec.fArgPos > 0) {
150485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                /* offset position by 1 */
150585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                spec.fArgPos--;
150685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                switch(argType) {
150785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_count:
150885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    /* set the spec's width to the # of chars written */
150985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    info->fWidth = *written;
151085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    /* fall through to set the pointer */
151185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_string:
151285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_ustring:
151385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_pointer:
151485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    args.ptrValue = arglist[spec.fArgPos].ptrValue;
151585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
151685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_char:
151785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_uchar:
151885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_int:
151985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    args.int64Value = arglist[spec.fArgPos].int64Value;
152085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
152185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_float:
152285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    args.floatValue = arglist[spec.fArgPos].floatValue;
152385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
152485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_double:
152585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    args.doubleValue = arglist[spec.fArgPos].doubleValue;
152685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
152785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                default:
152885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    /* else args is ignored */
152985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    args.ptrValue = NULL;
153085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
153285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else { /* no positional argument specified */
153385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                switch(argType) {
153485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_count:
153585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    /* set the spec's width to the # of chars written */
153685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    info->fWidth = *written;
153785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    /* fall through to set the pointer */
153885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_string:
153985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_ustring:
154085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_pointer:
154185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    args.ptrValue = va_arg(ap, void*);
154285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
154385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_char:
154485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_uchar:
154585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_int:
154685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    if (info->fIsLongLong) {
154785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        args.int64Value = va_arg(ap, int64_t);
154885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
154985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    else {
155085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        args.int64Value = va_arg(ap, int32_t);
155185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
155285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
155385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_float:
155485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    args.floatValue = (float) va_arg(ap, double);
155585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
155685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                case ufmt_double:
155785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    args.doubleValue = va_arg(ap, double);
155885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
155985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                default:
156085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    /* else args is ignored */
156185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    args.ptrValue = NULL;
156285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
1563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* call the handler function */
1567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            handler = g_u_printf_infos[ handlerNum ].handler;
1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(handler != 0) {
1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *written += (*handler)(streamHandler, context, formatBundle, info, &args);
1570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            else {
1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* just echo unknown tags */
1573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *written += (streamHandler->write)(context, fmt, (int32_t)(alias - lastAlias));
1574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* just echo unknown tags */
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *written += (streamHandler->write)(context, fmt, (int32_t)(alias - lastAlias));
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
158185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* delete parsed argument list */
158285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (arglist != NULL) {
158385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_free(arglist);
158485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* return # of characters in this format that have been parsed. */
1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (int32_t)(alias - fmt);
1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
1590