tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sprintf.cpp (7706B)


      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
     39 u_sprintf_write(void        *context,
     40                const char16_t *str,
     41                int32_t     count)
     42 {
     43    u_localized_print_string* output = static_cast<u_localized_print_string*>(context);
     44 
     45    /* just calculating buffer size */
     46    if (output->str == nullptr) {
     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
     58 u_sprintf_pad_and_justify(void                        *context,
     59                          const u_printf_spec_info    *info,
     60                          const char16_t              *result,
     61                          int32_t                     resultLen)
     62 {
     63    u_localized_print_string* output = static_cast<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 == nullptr &&
     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
    115 u_sprintf(char16_t    *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
    130 u_sprintf_u(char16_t  *buffer,
    131            const char16_t *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 */
    145 u_vsprintf(char16_t    *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
    153 u_snprintf(char16_t    *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
    169 u_snprintf_u(char16_t  *buffer,
    170             int32_t        count,
    171             const char16_t *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 */
    185 u_vsnprintf(char16_t    *buffer,
    186            int32_t         count,
    187            const char     *patternSpecification,
    188            va_list         ap)
    189 {
    190    int32_t written;
    191    char16_t *pattern;
    192    char16_t 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 >= MAX_UCHAR_BUFFER_SIZE(patBuffer)) {
    197        pattern = (char16_t *)uprv_malloc(size * sizeof(char16_t));
    198        if (pattern == nullptr) {
    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 
    219 u_vsprintf_u(char16_t    *buffer,
    220             const char16_t *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 */
    232 u_vsnprintf_u(char16_t *buffer,
    233              int32_t        count,
    234              const char16_t *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") == nullptr) {
    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 */