• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ******************************************************************************
5 *
6 *   Copyright (C) 2001-2014, International Business Machines
7 *   Corporation and others.  All Rights Reserved.
8 *
9 ******************************************************************************
10 *
11 * File sprintf.c
12 *
13 * Modification History:
14 *
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 *******************************************************************************
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/putil.h"
30 
31 #include "uprintf.h"
32 #include "locbund.h"
33 
34 #include "cmemory.h"
35 #include <ctype.h>
36 
37 /* u_minstrncpy copies the minimum number of code units of (count or output->available) */
38 static int32_t
u_sprintf_write(void * context,const UChar * str,int32_t count)39 u_sprintf_write(void        *context,
40                 const UChar *str,
41                 int32_t     count)
42 {
43     u_localized_print_string *output = (u_localized_print_string *)context;
44 
45     /* just calculating buffer size */
46     if (output->str == 0) {
47         return count;
48     }
49 
50     int32_t size = ufmt_min(count, output->available);
51 
52     u_strncpy(output->str + (output->len - output->available), str, size);
53     output->available -= size;
54     return size;
55 }
56 
57 static int32_t
u_sprintf_pad_and_justify(void * context,const u_printf_spec_info * info,const UChar * result,int32_t resultLen)58 u_sprintf_pad_and_justify(void                        *context,
59                           const u_printf_spec_info    *info,
60                           const UChar                 *result,
61                           int32_t                     resultLen)
62 {
63     u_localized_print_string *output = (u_localized_print_string *)context;
64     int32_t written = 0;
65     int32_t lengthOfResult = resultLen;
66 
67     /* just calculating buffer size */
68     if (output->str == 0 &&
69         info->fWidth != -1 && resultLen < info->fWidth) {
70         return info->fWidth;
71     }
72 
73     resultLen = ufmt_min(resultLen, output->available);
74 
75     /* pad and justify, if needed */
76     if(info->fWidth != -1 && resultLen < info->fWidth) {
77         int32_t paddingLeft = info->fWidth - resultLen;
78         int32_t outputPos = output->len - output->available;
79 
80         if (paddingLeft + resultLen > output->available) {
81             paddingLeft = output->available - resultLen;
82             if (paddingLeft < 0) {
83                 paddingLeft = 0;
84             }
85             /* paddingLeft = output->available - resultLen;*/
86         }
87         written += paddingLeft;
88 
89         /* left justify */
90         if(info->fLeft) {
91             written += u_sprintf_write(output, result, resultLen);
92             u_memset(&output->str[outputPos + resultLen], info->fPadChar, paddingLeft);
93             output->available -= paddingLeft;
94         }
95         /* right justify */
96         else {
97             u_memset(&output->str[outputPos], info->fPadChar, paddingLeft);
98             output->available -= paddingLeft;
99             written += u_sprintf_write(output, result, resultLen);
100         }
101     }
102     /* just write the formatted output */
103     else {
104         written = u_sprintf_write(output, result, resultLen);
105     }
106 
107     if (written >= 0 && lengthOfResult > written) {
108     	return lengthOfResult;
109     }
110 
111     return written;
112 }
113 
114 U_CAPI int32_t U_EXPORT2
u_sprintf(UChar * buffer,const char * patternSpecification,...)115 u_sprintf(UChar       *buffer,
116           const char    *patternSpecification,
117           ... )
118 {
119     va_list ap;
120     int32_t written;
121 
122     va_start(ap, patternSpecification);
123     written = u_vsnprintf(buffer, INT32_MAX, patternSpecification, ap);
124     va_end(ap);
125 
126     return written;
127 }
128 
129 U_CAPI int32_t U_EXPORT2
u_sprintf_u(UChar * buffer,const UChar * patternSpecification,...)130 u_sprintf_u(UChar     *buffer,
131             const UChar    *patternSpecification,
132             ... )
133 {
134     va_list ap;
135     int32_t written;
136 
137     va_start(ap, patternSpecification);
138     written = u_vsnprintf_u(buffer, INT32_MAX, patternSpecification, ap);
139     va_end(ap);
140 
141     return written;
142 }
143 
144 U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
u_vsprintf(UChar * buffer,const char * patternSpecification,va_list ap)145 u_vsprintf(UChar       *buffer,
146            const char     *patternSpecification,
147            va_list         ap)
148 {
149     return u_vsnprintf(buffer, INT32_MAX, patternSpecification, ap);
150 }
151 
152 U_CAPI int32_t U_EXPORT2
u_snprintf(UChar * buffer,int32_t count,const char * patternSpecification,...)153 u_snprintf(UChar       *buffer,
154            int32_t         count,
155            const char    *patternSpecification,
156            ... )
157 {
158     va_list ap;
159     int32_t written;
160 
161     va_start(ap, patternSpecification);
162     written = u_vsnprintf(buffer, count, patternSpecification, ap);
163     va_end(ap);
164 
165     return written;
166 }
167 
168 U_CAPI int32_t U_EXPORT2
u_snprintf_u(UChar * buffer,int32_t count,const UChar * patternSpecification,...)169 u_snprintf_u(UChar     *buffer,
170              int32_t        count,
171              const UChar    *patternSpecification,
172              ... )
173 {
174     va_list ap;
175     int32_t written;
176 
177     va_start(ap, patternSpecification);
178     written = u_vsnprintf_u(buffer, count, patternSpecification, ap);
179     va_end(ap);
180 
181     return written;
182 }
183 
184 U_CAPI int32_t  U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
u_vsnprintf(UChar * buffer,int32_t count,const char * patternSpecification,va_list ap)185 u_vsnprintf(UChar       *buffer,
186             int32_t         count,
187             const char     *patternSpecification,
188             va_list         ap)
189 {
190     int32_t written;
191     UChar *pattern;
192     UChar patBuffer[UFMT_DEFAULT_BUFFER_SIZE];
193     int32_t size = (int32_t)strlen(patternSpecification) + 1;
194 
195     /* convert from the default codepage to Unicode */
196     if (size >= (int32_t)MAX_UCHAR_BUFFER_SIZE(patBuffer)) {
197         pattern = (UChar *)uprv_malloc(size * sizeof(UChar));
198         if(pattern == 0) {
199             return 0;
200         }
201     }
202     else {
203         pattern = patBuffer;
204     }
205     u_charsToUChars(patternSpecification, pattern, size);
206 
207     /* do the work */
208     written = u_vsnprintf_u(buffer, count, pattern, ap);
209 
210     /* clean up */
211     if (pattern != patBuffer) {
212         uprv_free(pattern);
213     }
214 
215     return written;
216 }
217 
218 U_CAPI int32_t U_EXPORT2
u_vsprintf_u(UChar * buffer,const UChar * patternSpecification,va_list ap)219 u_vsprintf_u(UChar       *buffer,
220              const UChar *patternSpecification,
221              va_list     ap)
222 {
223     return u_vsnprintf_u(buffer, INT32_MAX, patternSpecification, ap);
224 }
225 
226 static const u_printf_stream_handler g_sprintf_stream_handler = {
227     u_sprintf_write,
228     u_sprintf_pad_and_justify
229 };
230 
231 U_CAPI int32_t  U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
u_vsnprintf_u(UChar * buffer,int32_t count,const UChar * patternSpecification,va_list ap)232 u_vsnprintf_u(UChar    *buffer,
233               int32_t        count,
234               const UChar    *patternSpecification,
235               va_list        ap)
236 {
237     int32_t          written = 0;   /* haven't written anything yet */
238     int32_t			 result = 0; /* test the return value of u_printf_parse */
239 
240     u_localized_print_string outStr;
241 
242     if (count < 0) {
243         count = INT32_MAX;
244     }
245 
246     outStr.str = buffer;
247     outStr.len = count;
248     outStr.available = count;
249 
250     if(u_locbund_init(&outStr.fBundle, "en_US_POSIX") == 0) {
251         return 0;
252     }
253 
254     /* parse and print the whole format string */
255     result = u_printf_parse(&g_sprintf_stream_handler, patternSpecification, &outStr, &outStr, &outStr.fBundle, &written, ap);
256 
257     /* Terminate the buffer, if there's room. */
258     if (outStr.available > 0) {
259         buffer[outStr.len - outStr.available] = 0x0000;
260     }
261 
262     /* Release the cloned bundle, if we cloned it. */
263     u_locbund_close(&outStr.fBundle);
264 
265     /* parsing error */
266     if (result < 0) {
267     	return result;
268     }
269     /* return # of UChars written */
270     return written;
271 }
272 
273 #endif /* #if !UCONFIG_NO_FORMATTING */
274 
275