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