1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 ******************************************************************************
6 * Copyright (C) 2001-2014, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 ******************************************************************************
13 * Modification History:
15 * Date Name Description
16 * 02/08/2001 george Creation. Copied from uprintf.c
17 * 03/27/2002 Mark Schneckloth Many fixes regarding alignment, null termination
18 * (mschneckloth@atomz.com) and other various problems.
19 * 08/07/2003 george Reunify printf implementations
20 *******************************************************************************
23 #include "unicode/utypes.h"
25 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_CONVERSION
27 #include "unicode/ustdio.h"
28 #include "unicode/ustring.h"
29 #include "unicode/putil.h"
37 /* u_minstrncpy copies the minimum number of code units of (count or output->available) */
39 u_sprintf_write(void *context
,
43 u_localized_print_string
*output
= (u_localized_print_string
*)context
;
44 int32_t size
= ufmt_min(count
, output
->available
);
46 u_strncpy(output
->str
+ (output
->len
- output
->available
), str
, size
);
47 output
->available
-= size
;
52 u_sprintf_pad_and_justify(void *context
,
53 const u_printf_spec_info
*info
,
57 u_localized_print_string
*output
= (u_localized_print_string
*)context
;
59 int32_t lengthOfResult
= resultLen
;
61 resultLen
= ufmt_min(resultLen
, output
->available
);
63 /* pad and justify, if needed */
64 if(info
->fWidth
!= -1 && resultLen
< info
->fWidth
) {
65 int32_t paddingLeft
= info
->fWidth
- resultLen
;
66 int32_t outputPos
= output
->len
- output
->available
;
68 if (paddingLeft
+ resultLen
> output
->available
) {
69 paddingLeft
= output
->available
- resultLen
;
70 if (paddingLeft
< 0) {
73 /* paddingLeft = output->available - resultLen;*/
75 written
+= paddingLeft
;
79 written
+= u_sprintf_write(output
, result
, resultLen
);
80 u_memset(&output
->str
[outputPos
+ resultLen
], info
->fPadChar
, paddingLeft
);
81 output
->available
-= paddingLeft
;
85 u_memset(&output
->str
[outputPos
], info
->fPadChar
, paddingLeft
);
86 output
->available
-= paddingLeft
;
87 written
+= u_sprintf_write(output
, result
, resultLen
);
90 /* just write the formatted output */
92 written
= u_sprintf_write(output
, result
, resultLen
);
95 if (written
>= 0 && lengthOfResult
> written
) {
96 return lengthOfResult
;
102 U_CAPI
int32_t U_EXPORT2
103 u_sprintf(UChar
*buffer
,
104 const char *patternSpecification
,
110 va_start(ap
, patternSpecification
);
111 written
= u_vsnprintf(buffer
, INT32_MAX
, patternSpecification
, ap
);
117 U_CAPI
int32_t U_EXPORT2
118 u_sprintf_u(UChar
*buffer
,
119 const UChar
*patternSpecification
,
125 va_start(ap
, patternSpecification
);
126 written
= u_vsnprintf_u(buffer
, INT32_MAX
, patternSpecification
, ap
);
132 U_CAPI
int32_t U_EXPORT2
/* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
133 u_vsprintf(UChar
*buffer
,
134 const char *patternSpecification
,
137 return u_vsnprintf(buffer
, INT32_MAX
, patternSpecification
, ap
);
140 U_CAPI
int32_t U_EXPORT2
141 u_snprintf(UChar
*buffer
,
143 const char *patternSpecification
,
149 va_start(ap
, patternSpecification
);
150 written
= u_vsnprintf(buffer
, count
, patternSpecification
, ap
);
156 U_CAPI
int32_t U_EXPORT2
157 u_snprintf_u(UChar
*buffer
,
159 const UChar
*patternSpecification
,
165 va_start(ap
, patternSpecification
);
166 written
= u_vsnprintf_u(buffer
, count
, patternSpecification
, ap
);
172 U_CAPI
int32_t U_EXPORT2
/* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
173 u_vsnprintf(UChar
*buffer
,
175 const char *patternSpecification
,
180 UChar patBuffer
[UFMT_DEFAULT_BUFFER_SIZE
];
181 int32_t size
= (int32_t)strlen(patternSpecification
) + 1;
183 /* convert from the default codepage to Unicode */
184 if (size
>= (int32_t)MAX_UCHAR_BUFFER_SIZE(patBuffer
)) {
185 pattern
= (UChar
*)uprv_malloc(size
* sizeof(UChar
));
193 u_charsToUChars(patternSpecification
, pattern
, size
);
196 written
= u_vsnprintf_u(buffer
, count
, pattern
, ap
);
199 if (pattern
!= patBuffer
) {
206 U_CAPI
int32_t U_EXPORT2
207 u_vsprintf_u(UChar
*buffer
,
208 const UChar
*patternSpecification
,
211 return u_vsnprintf_u(buffer
, INT32_MAX
, patternSpecification
, ap
);
214 static const u_printf_stream_handler g_sprintf_stream_handler
= {
216 u_sprintf_pad_and_justify
219 U_CAPI
int32_t U_EXPORT2
/* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
220 u_vsnprintf_u(UChar
*buffer
,
222 const UChar
*patternSpecification
,
225 int32_t written
= 0; /* haven't written anything yet */
226 int32_t result
= 0; /* test the return value of u_printf_parse */
228 u_localized_print_string outStr
;
236 outStr
.available
= count
;
238 if(u_locbund_init(&outStr
.fBundle
, "en_US_POSIX") == 0) {
242 /* parse and print the whole format string */
243 result
= u_printf_parse(&g_sprintf_stream_handler
, patternSpecification
, &outStr
, &outStr
, &outStr
.fBundle
, &written
, ap
);
245 /* Terminate the buffer, if there's room. */
246 if (outStr
.available
> 0) {
247 buffer
[outStr
.len
- outStr
.available
] = 0x0000;
250 /* Release the cloned bundle, if we cloned it. */
251 u_locbund_close(&outStr
.fBundle
);
257 /* return # of UChars written */
261 #endif /* #if !UCONFIG_NO_FORMATTING */