tor-browser

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

uwmsg.c (6512B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 **********************************************************************
      5 * Copyright (C) 1998-2016, International Business Machines Corporation
      6 * and others.  All Rights Reserved.
      7 **********************************************************************
      8 *
      9 * File uwmsg.c
     10 *
     11 * Modification History:
     12 *
     13 *   Date        Name        Description
     14 *   06/14/99    stephen     Creation.
     15 *******************************************************************************
     16 */
     17 
     18 #include "unicode/ucnv.h"
     19 #include "unicode/ustring.h"
     20 #include "unicode/umsg.h"
     21 #include "unicode/uwmsg.h"
     22 #include "unicode/ures.h"
     23 #include "unicode/putil.h"
     24 #include "cmemory.h"
     25 #include "cstring.h"
     26 
     27 #include <stdbool.h>
     28 #include <stdlib.h>
     29 #include <stdarg.h>
     30 #include <stdio.h>
     31 #include <string.h>
     32 
     33 #define BUF_SIZE 128
     34 
     35 /* Print a ustring to the specified FILE* in the default codepage */
     36 static void
     37 uprint(const UChar *s,
     38       int32_t sourceLen,
     39       FILE *f,
     40       UErrorCode *status)
     41 {
     42    /* converter */
     43    UConverter *converter;
     44    char buf [BUF_SIZE];
     45    const UChar *mySource;
     46    const UChar *mySourceEnd;
     47    char *myTarget;
     48    int32_t arraySize;
     49    UErrorCode bufferStatus;
     50 
     51    if(s == 0) return;
     52 
     53    /* set up the conversion parameters */
     54    mySource     = s;
     55    mySourceEnd  = mySource + sourceLen;
     56    myTarget     = buf;
     57    arraySize    = BUF_SIZE;
     58    bufferStatus = U_ZERO_ERROR;
     59 
     60    /* open a default converter */
     61    converter = ucnv_open(0, status);
     62 
     63    /* if we failed, clean up and exit */
     64    if(U_FAILURE(*status)) goto finish;
     65 
     66    /* perform the conversion */
     67    do {
     68        /* reset the error code */
     69        bufferStatus = U_ZERO_ERROR;
     70 
     71        /* perform the conversion */
     72        ucnv_fromUnicode(converter, &myTarget,  myTarget + arraySize,
     73            &mySource, mySourceEnd, NULL,
     74            true, &bufferStatus);
     75 
     76        /* Write the converted data to the FILE* */
     77        fwrite(buf, sizeof(char), myTarget - buf, f);
     78 
     79        /* update the conversion parameters*/
     80        myTarget     = buf;
     81        arraySize    = BUF_SIZE;
     82    }
     83    while(bufferStatus == U_BUFFER_OVERFLOW_ERROR);
     84    if (U_FAILURE(bufferStatus)) {
     85        *status = bufferStatus;
     86    }
     87 
     88 finish:
     89 
     90    /* close the converter */
     91    ucnv_close(converter);
     92 }
     93 
     94 static UResourceBundle *gBundle = NULL;
     95 
     96 U_STRING_DECL(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38);
     97 
     98 U_CFUNC UResourceBundle *u_wmsg_setPath(const char *path, UErrorCode *err)
     99 {
    100  if(U_FAILURE(*err))
    101  {
    102    return 0;
    103  }
    104 
    105  if(gBundle != NULL)
    106  {
    107    *err = U_ILLEGAL_ARGUMENT_ERROR;
    108    return 0;
    109  }
    110  else
    111  {
    112    UResourceBundle *b = NULL;
    113    b = ures_open(path, NULL, err);
    114    if(U_FAILURE(*err))
    115    {
    116         return 0;
    117    }
    118 
    119    gBundle = b;
    120 
    121    U_STRING_INIT(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38);
    122  }
    123  
    124  return gBundle;
    125 }
    126 
    127 /* Format a message and print it's output to fp */
    128 U_CFUNC int u_wmsg(FILE *fp, const char *tag, ... )
    129 {
    130    const UChar *msg;
    131    int32_t      msgLen;
    132    UErrorCode  err = U_ZERO_ERROR;
    133 #if !UCONFIG_NO_FORMATTING
    134    va_list ap;
    135 #endif
    136    UChar   result[4096];
    137    int32_t resultLength = UPRV_LENGTHOF(result);
    138 
    139    if(gBundle == NULL)
    140    {
    141 #if 0
    142        fprintf(stderr, "u_wmsg: No path set!!\n"); /* FIXME: codepage?? */
    143 #endif
    144        return -1;
    145    }
    146 
    147    msg = ures_getStringByKey(gBundle, tag, &msgLen, &err);
    148 
    149    if(U_FAILURE(err))
    150    {
    151        return -1;
    152    }
    153 
    154 #if UCONFIG_NO_FORMATTING
    155    resultLength = UPRV_LENGTHOF(gNoFormatting);
    156    if((msgLen + resultLength) <= UPRV_LENGTHOF(result)) {
    157        memcpy(result, msg, msgLen * U_SIZEOF_UCHAR);
    158        memcpy(result + msgLen, gNoFormatting, resultLength);
    159        resultLength += msgLen;
    160        uprint(result, resultLength, fp, &err);
    161    } else {
    162        uprint(msg,msgLen, fp, &err);
    163    }
    164 #else
    165    (void)gNoFormatting;  // suppress -Wunused-variable
    166    va_start(ap, tag);
    167 
    168    resultLength = u_vformatMessage(uloc_getDefault(), msg, msgLen, result, resultLength, ap, &err);
    169 
    170    va_end(ap);
    171 
    172    if(U_FAILURE(err))
    173    {
    174 #if 0
    175        fprintf(stderr, "u_wmsg: failed to format %s:%s, err %s\n",
    176            uloc_getDefault(),
    177            tag,
    178            u_errorName(err));
    179 #endif
    180        err = U_ZERO_ERROR;
    181        uprint(msg,msgLen, fp, &err);
    182        return -1;
    183    }
    184 
    185    uprint(result, resultLength, fp, &err);
    186 #endif
    187 
    188    if(U_FAILURE(err))
    189    {
    190 #if 0
    191        fprintf(stderr, "u_wmsg: failed to print %s: %s, err %s\n",
    192            uloc_getDefault(),
    193            tag,
    194            u_errorName(err));
    195 #endif
    196        return -1;
    197    }
    198 
    199    return 0;
    200 }
    201 
    202 /* these will break if the # of messages change. simply add or remove 0's .. */
    203 UChar **gInfoMessages = NULL;
    204 
    205 UChar **gErrMessages = NULL;
    206 
    207 static const UChar *fetchErrorName(UErrorCode err)
    208 {
    209    if (!gInfoMessages) {
    210        gInfoMessages = (UChar **)malloc((U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
    211        memset(gInfoMessages, 0, (U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
    212    }
    213    if (!gErrMessages) {
    214        gErrMessages = (UChar **)malloc(U_ERROR_LIMIT*sizeof(UChar*));
    215        memset(gErrMessages, 0, U_ERROR_LIMIT*sizeof(UChar*));
    216    }
    217    if(err>=0)
    218        return gErrMessages[err];
    219    else
    220        return gInfoMessages[err-U_ERROR_WARNING_START];
    221 }
    222 
    223 U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err)
    224 {
    225    UChar *msg;
    226    int32_t msgLen;
    227    UErrorCode subErr = U_ZERO_ERROR;
    228    const char *textMsg = NULL;
    229 
    230    /* try the cache */
    231    msg = (UChar*)fetchErrorName(err);
    232 
    233    if(msg)
    234    {
    235        return msg;
    236    }
    237 
    238    if(gBundle == NULL)
    239    {
    240        msg = NULL;
    241    }
    242    else
    243    {
    244        const char *errname = u_errorName(err);
    245        if (errname) {
    246            msg = (UChar*)ures_getStringByKey(gBundle, errname, &msgLen, &subErr);
    247            if(U_FAILURE(subErr))
    248            {
    249                msg = NULL;
    250            }
    251        }
    252    }
    253 
    254    if(msg == NULL)  /* Couldn't find it anywhere.. */
    255    {
    256        char error[128];
    257        textMsg = u_errorName(err);
    258        if (!textMsg) {
    259            sprintf(error, "UNDOCUMENTED ICU ERROR %d", err);
    260            textMsg = error;
    261        }
    262        msg = (UChar*)malloc((strlen(textMsg)+1)*sizeof(msg[0]));
    263        u_charsToUChars(textMsg, msg, (int32_t)(strlen(textMsg)+1));
    264    }
    265 
    266    if(err>=0)
    267        gErrMessages[err] = msg;
    268    else
    269        gInfoMessages[err-U_ERROR_WARNING_START] = msg;
    270 
    271    return msg;
    272 }