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