Home | History | Annotate | Download | only in io
      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 (at) 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
     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     int32_t size = ufmt_min(count, output->available);
     45 
     46     u_strncpy(output->str + (output->len - output->available), str, size);
     47     output->available -= size;
     48     return size;
     49 }
     50 
     51 static int32_t
     52 u_sprintf_pad_and_justify(void                        *context,
     53                           const u_printf_spec_info    *info,
     54                           const UChar                 *result,
     55                           int32_t                     resultLen)
     56 {
     57     u_localized_print_string *output = (u_localized_print_string *)context;
     58     int32_t written = 0;
     59     int32_t lengthOfResult = resultLen;
     60 
     61     resultLen = ufmt_min(resultLen, output->available);
     62 
     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;
     67 
     68         if (paddingLeft + resultLen > output->available) {
     69             paddingLeft = output->available - resultLen;
     70             if (paddingLeft < 0) {
     71                 paddingLeft = 0;
     72             }
     73             /* paddingLeft = output->available - resultLen;*/
     74         }
     75         written += paddingLeft;
     76 
     77         /* left justify */
     78         if(info->fLeft) {
     79             written += u_sprintf_write(output, result, resultLen);
     80             u_memset(&output->str[outputPos + resultLen], info->fPadChar, paddingLeft);
     81             output->available -= paddingLeft;
     82         }
     83         /* right justify */
     84         else {
     85             u_memset(&output->str[outputPos], info->fPadChar, paddingLeft);
     86             output->available -= paddingLeft;
     87             written += u_sprintf_write(output, result, resultLen);
     88         }
     89     }
     90     /* just write the formatted output */
     91     else {
     92         written = u_sprintf_write(output, result, resultLen);
     93     }
     94 
     95     if (written >= 0 && lengthOfResult > written) {
     96     	return lengthOfResult;
     97     }
     98 
     99     return written;
    100 }
    101 
    102 U_CAPI int32_t U_EXPORT2
    103 u_sprintf(UChar       *buffer,
    104           const char    *patternSpecification,
    105           ... )
    106 {
    107     va_list ap;
    108     int32_t written;
    109 
    110     va_start(ap, patternSpecification);
    111     written = u_vsnprintf(buffer, INT32_MAX, patternSpecification, ap);
    112     va_end(ap);
    113 
    114     return written;
    115 }
    116 
    117 U_CAPI int32_t U_EXPORT2
    118 u_sprintf_u(UChar     *buffer,
    119             const UChar    *patternSpecification,
    120             ... )
    121 {
    122     va_list ap;
    123     int32_t written;
    124 
    125     va_start(ap, patternSpecification);
    126     written = u_vsnprintf_u(buffer, INT32_MAX, patternSpecification, ap);
    127     va_end(ap);
    128 
    129     return written;
    130 }
    131 
    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,
    135            va_list         ap)
    136 {
    137     return u_vsnprintf(buffer, INT32_MAX, patternSpecification, ap);
    138 }
    139 
    140 U_CAPI int32_t U_EXPORT2
    141 u_snprintf(UChar       *buffer,
    142            int32_t         count,
    143            const char    *patternSpecification,
    144            ... )
    145 {
    146     va_list ap;
    147     int32_t written;
    148 
    149     va_start(ap, patternSpecification);
    150     written = u_vsnprintf(buffer, count, patternSpecification, ap);
    151     va_end(ap);
    152 
    153     return written;
    154 }
    155 
    156 U_CAPI int32_t U_EXPORT2
    157 u_snprintf_u(UChar     *buffer,
    158              int32_t        count,
    159              const UChar    *patternSpecification,
    160              ... )
    161 {
    162     va_list ap;
    163     int32_t written;
    164 
    165     va_start(ap, patternSpecification);
    166     written = u_vsnprintf_u(buffer, count, patternSpecification, ap);
    167     va_end(ap);
    168 
    169     return written;
    170 }
    171 
    172 U_CAPI int32_t  U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
    173 u_vsnprintf(UChar       *buffer,
    174             int32_t         count,
    175             const char     *patternSpecification,
    176             va_list         ap)
    177 {
    178     int32_t written;
    179     UChar *pattern;
    180     UChar patBuffer[UFMT_DEFAULT_BUFFER_SIZE];
    181     int32_t size = (int32_t)strlen(patternSpecification) + 1;
    182 
    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));
    186         if(pattern == 0) {
    187             return 0;
    188         }
    189     }
    190     else {
    191         pattern = patBuffer;
    192     }
    193     u_charsToUChars(patternSpecification, pattern, size);
    194 
    195     /* do the work */
    196     written = u_vsnprintf_u(buffer, count, pattern, ap);
    197 
    198     /* clean up */
    199     if (pattern != patBuffer) {
    200         uprv_free(pattern);
    201     }
    202 
    203     return written;
    204 }
    205 
    206 U_CAPI int32_t U_EXPORT2
    207 u_vsprintf_u(UChar       *buffer,
    208              const UChar *patternSpecification,
    209              va_list     ap)
    210 {
    211     return u_vsnprintf_u(buffer, INT32_MAX, patternSpecification, ap);
    212 }
    213 
    214 static const u_printf_stream_handler g_sprintf_stream_handler = {
    215     u_sprintf_write,
    216     u_sprintf_pad_and_justify
    217 };
    218 
    219 U_CAPI int32_t  U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
    220 u_vsnprintf_u(UChar    *buffer,
    221               int32_t        count,
    222               const UChar    *patternSpecification,
    223               va_list        ap)
    224 {
    225     int32_t          written = 0;   /* haven't written anything yet */
    226     int32_t			 result = 0; /* test the return value of u_printf_parse */
    227 
    228     u_localized_print_string outStr;
    229 
    230     if (count < 0) {
    231         count = INT32_MAX;
    232     }
    233 
    234     outStr.str = buffer;
    235     outStr.len = count;
    236     outStr.available = count;
    237 
    238     if(u_locbund_init(&outStr.fBundle, "en_US_POSIX") == 0) {
    239         return 0;
    240     }
    241 
    242     /* parse and print the whole format string */
    243     result = u_printf_parse(&g_sprintf_stream_handler, patternSpecification, &outStr, &outStr, &outStr.fBundle, &written, ap);
    244 
    245     /* Terminate the buffer, if there's room. */
    246     if (outStr.available > 0) {
    247         buffer[outStr.len - outStr.available] = 0x0000;
    248     }
    249 
    250     /* Release the cloned bundle, if we cloned it. */
    251     u_locbund_close(&outStr.fBundle);
    252 
    253     /* parsing error */
    254     if (result < 0) {
    255     	return result;
    256     }
    257     /* return # of UChars written */
    258     return written;
    259 }
    260 
    261 #endif /* #if !UCONFIG_NO_FORMATTING */
    262 
    263