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