1f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius/*
2f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius******************************************************************************
3f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*
4f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*   Copyright (C) 1998-2014, International Business Machines
5f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*   Corporation and others.  All Rights Reserved.
6f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*
7f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius******************************************************************************
8f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*
9f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius* File uprintf.cpp
10f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*
11f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius* Modification History:
12f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*
13f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*   Date        Name        Description
14f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*   11/19/98    stephen     Creation.
15f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*   03/12/99    stephen     Modified for new C API.
16f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*                           Added conversion from default codepage.
17f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*   08/07/2003  george      Reunify printf implementations
18f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius******************************************************************************
19f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius*/
20f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
21f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "unicode/utypes.h"
22f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
23f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_CONVERSION
24f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
25f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "unicode/ustdio.h"
26f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "unicode/ustring.h"
27f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "unicode/unum.h"
28f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "unicode/udat.h"
29f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "unicode/putil.h"
30f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
31f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "cmemory.h"
32f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "locbund.h"
33f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "mutex.h"
34f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "uassert.h"
35f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "uprintf.h"
36f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "ufile.h"
37f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "ucln_io.h"
38f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
39f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_NAMESPACE_USE
40f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
41f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic UFILE *gStdOut = NULL;
42f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic UInitOnce gStdOutInitOnce = U_INITONCE_INITIALIZER;
43f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
44f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic UBool U_CALLCONV uprintf_cleanup(void)
45f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
46f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (gStdOut != NULL) {
47f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        u_fclose(gStdOut);
48f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        gStdOut = NULL;
49f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
50f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gStdOutInitOnce.reset();
51f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TRUE;
52f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
53f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
54f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic void U_CALLCONV u_stdout_init() {
55f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    U_ASSERT(gStdOut ==  NULL);
56f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gStdOut = u_finit(stdout, NULL, NULL);
57f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ucln_io_registerCleanup(UCLN_IO_PRINTF, &uprintf_cleanup);
58f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
59f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
60f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI UFILE * U_EXPORT2
61f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_get_stdout()
62f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
63f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_initOnce(gStdOutInitOnce, &u_stdout_init);
64f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return gStdOut;
65f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
66f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
67f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic int32_t U_EXPORT2
68f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_printf_write(void          *context,
69f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius               const UChar   *str,
70f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius               int32_t       count)
71f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
72f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return u_file_write(str, count, (UFILE *)context);
73f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
74f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
75f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic int32_t
76f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_printf_pad_and_justify(void                        *context,
77f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                         const u_printf_spec_info    *info,
78f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                         const UChar                 *result,
79f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                         int32_t                     resultLen)
80f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
81f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UFILE   *output = (UFILE *)context;
82f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t written, i;
83f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
84f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    /* pad and justify, if needed */
85f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if(info->fWidth != -1 && resultLen < info->fWidth) {
86f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        /* left justify */
87f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if(info->fLeft) {
88f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            written = u_file_write(result, resultLen, output);
89f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            for(i = 0; i < info->fWidth - resultLen; ++i) {
90f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                written += u_file_write(&info->fPadChar, 1, output);
91f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
92f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
93f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        /* right justify */
94f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        else {
95f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            written = 0;
96f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            for(i = 0; i < info->fWidth - resultLen; ++i) {
97f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                written += u_file_write(&info->fPadChar, 1, output);
98f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
99f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            written += u_file_write(result, resultLen, output);
100f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
101f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
102f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    /* just write the formatted output */
103f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    else {
104f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        written = u_file_write(result, resultLen, output);
105f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
106f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
107f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return written;
108f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
109f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
110f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI int32_t U_EXPORT2
111f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_fprintf(    UFILE        *f,
112f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius          const char    *patternSpecification,
113f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius          ... )
114f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
115f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_list ap;
116f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t count;
117f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
118f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_start(ap, patternSpecification);
119f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    count = u_vfprintf(f, patternSpecification, ap);
120f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_end(ap);
121f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
122f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return count;
123f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
124f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
125f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI int32_t U_EXPORT2
126f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_printf(const char *patternSpecification,
127f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius         ...)
128f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
129f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_list ap;
130f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t count;
131f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_start(ap, patternSpecification);
132f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    count = u_vfprintf(u_get_stdout(), patternSpecification, ap);
133f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_end(ap);
134f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return count;
135f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
136f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
137f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI int32_t U_EXPORT2
138f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_fprintf_u(    UFILE        *f,
139f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            const UChar    *patternSpecification,
140f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            ... )
141f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
142f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_list ap;
143f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t count;
144f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
145f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_start(ap, patternSpecification);
146f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    count = u_vfprintf_u(f, patternSpecification, ap);
147f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_end(ap);
148f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
149f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return count;
150f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
151f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
152f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI int32_t U_EXPORT2
153f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_printf_u(const UChar *patternSpecification,
154f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius           ...)
155f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
156f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_list ap;
157f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t count;
158f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_start(ap, patternSpecification);
159f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    count = u_vfprintf_u(u_get_stdout(), patternSpecification, ap);
160f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    va_end(ap);
161f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return count;
162f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
163f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
164f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI int32_t  U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
165f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_vfprintf(    UFILE        *f,
166f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius           const char    *patternSpecification,
167f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius           va_list        ap)
168f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
169f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t count;
170f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UChar *pattern;
171f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UChar buffer[UFMT_DEFAULT_BUFFER_SIZE];
172f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    size_t size = strlen(patternSpecification) + 1;
173f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
174f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    /* convert from the default codepage to Unicode */
175f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (size >= MAX_UCHAR_BUFFER_SIZE(buffer)) {
176f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        pattern = (UChar *)uprv_malloc(size * sizeof(UChar));
177f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if(pattern == 0) {
178f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            return 0;
179f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
180f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
181f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    else {
182f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        pattern = buffer;
183f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
184f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    u_charsToUChars(patternSpecification, pattern, size);
185f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
186f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    /* do the work */
187f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    count = u_vfprintf_u(f, pattern, ap);
188f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
189f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    /* clean up */
190f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (pattern != buffer) {
191f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        uprv_free(pattern);
192f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
193f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
194f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return count;
195f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
196f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
197f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic const u_printf_stream_handler g_stream_handler = {
198f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    u_printf_write,
199f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    u_printf_pad_and_justify
200f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius};
201f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
202f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI int32_t  U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
203f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusu_vfprintf_u(    UFILE        *f,
204f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius             const UChar    *patternSpecification,
205f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius             va_list        ap)
206f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
207f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t          written = 0;   /* haven't written anything yet */
208f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
209f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    /* parse and print the whole format string */
210f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    u_printf_parse(&g_stream_handler, patternSpecification, f, NULL, &f->str.fBundle, &written, ap);
211f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
212f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    /* return # of UChars written */
213f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return written;
214f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
215f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
216f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#endif /* #if !UCONFIG_NO_FORMATTING */
217f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
218