Home | History | Annotate | Download | only in uconv
      1 /*
      2 **********************************************************************
      3 * Copyright (C) 1998-2004, 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 const char *gPath = 0;
     88 static UResourceBundle *gBundle = NULL;
     89 
     90 U_STRING_DECL(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38);
     91 
     92 U_CFUNC UResourceBundle *u_wmsg_setPath(const char *path, UErrorCode *err)
     93 {
     94   if(U_FAILURE(*err))
     95   {
     96     return 0;
     97   }
     98 
     99   if(gBundle != NULL)
    100   {
    101     *err = U_ILLEGAL_ARGUMENT_ERROR;
    102     return 0;
    103   }
    104   else
    105   {
    106     UResourceBundle *b = NULL;
    107     b = ures_open(path, NULL, err);
    108     if(U_FAILURE(*err))
    109     {
    110          return 0;
    111     }
    112 
    113     gPath = uprv_strdup(path);
    114     gBundle = b;
    115 
    116     U_STRING_INIT(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38);
    117   }
    118 
    119   return gBundle;
    120 }
    121 
    122 /* Format a message and print it's output to fp */
    123 U_CFUNC int u_wmsg(FILE *fp, const char *tag, ... )
    124 {
    125     const UChar *msg;
    126     int32_t      msgLen;
    127     UErrorCode  err = U_ZERO_ERROR;
    128 #if !UCONFIG_NO_FORMATTING
    129     va_list ap;
    130 #endif
    131     UChar   result[4096];
    132     int32_t resultLength = LENGTHOF(result);
    133 
    134     if(gBundle == NULL)
    135     {
    136 #if 0
    137         fprintf(stderr, "u_wmsg: No path set!!\n"); /* FIXME: codepage?? */
    138 #endif
    139         return -1;
    140     }
    141 
    142     msg = ures_getStringByKey(gBundle, tag, &msgLen, &err);
    143 
    144     if(U_FAILURE(err))
    145     {
    146 #if 0
    147         fprintf(stderr, "u_wmsg: failed to load tag [%s] [%s] [%s]!!\n", tag,  u_errorName(err), gPath);
    148 #endif
    149         return -1;
    150     }
    151 
    152 #if UCONFIG_NO_FORMATTING
    153     resultLength = sizeof(gNoFormatting) / U_SIZEOF_UCHAR;
    154     if((msgLen + resultLength) <= LENGTHOF(result)) {
    155         memcpy(result, msg, msgLen * U_SIZEOF_UCHAR);
    156         memcpy(result + msgLen, gNoFormatting, resultLength);
    157         resultLength += msgLen;
    158         uprint(result, resultLength, fp, &err);
    159     } else {
    160         uprint(msg,msgLen, fp, &err);
    161     }
    162 #else
    163     va_start(ap, tag);
    164 
    165     resultLength = u_vformatMessage(uloc_getDefault(), msg, msgLen, result, resultLength, ap, &err);
    166 
    167     va_end(ap);
    168 
    169     if(U_FAILURE(err))
    170     {
    171 #if 0
    172         fprintf(stderr, "u_wmsg: failed to format %s:%s, err %s\n",
    173             uloc_getDefault(),
    174             tag,
    175             u_errorName(err));
    176 #endif
    177         err = U_ZERO_ERROR;
    178         uprint(msg,msgLen, fp, &err);
    179         return -1;
    180     }
    181 
    182     uprint(result, resultLength, fp, &err);
    183 #endif
    184 
    185     if(U_FAILURE(err))
    186     {
    187 #if 0
    188         fprintf(stderr, "u_wmsg: failed to print %s: %s, err %s\n",
    189             uloc_getDefault(),
    190             tag,
    191             u_errorName(err));
    192 #endif
    193         return -1;
    194     }
    195 
    196     return 0;
    197 }
    198 
    199 /* these will break if the # of messages change. simply add or remove 0's .. */
    200 UChar **gInfoMessages = NULL;
    201 
    202 UChar **gErrMessages = NULL;
    203 
    204 static const UChar *fetchErrorName(UErrorCode err)
    205 {
    206     if (!gInfoMessages) {
    207         gInfoMessages = (UChar **)malloc((U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
    208         memset(gInfoMessages, 0, (U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
    209     }
    210     if (!gErrMessages) {
    211         gErrMessages = (UChar **)malloc(U_ERROR_LIMIT*sizeof(UChar*));
    212         memset(gErrMessages, 0, U_ERROR_LIMIT*sizeof(UChar*));
    213     }
    214     if(err>=0)
    215         return gErrMessages[err];
    216     else
    217         return gInfoMessages[err-U_ERROR_WARNING_START];
    218 }
    219 
    220 U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err)
    221 {
    222     UChar *msg;
    223     int32_t msgLen;
    224     UErrorCode subErr = U_ZERO_ERROR;
    225     const char *textMsg = NULL;
    226 
    227     /* try the cache */
    228     msg = (UChar*)fetchErrorName(err);
    229 
    230     if(msg)
    231     {
    232         return msg;
    233     }
    234 
    235     if(gBundle == NULL)
    236     {
    237         msg = NULL;
    238     }
    239     else
    240     {
    241         const char *errname = u_errorName(err);
    242         if (errname) {
    243             msg = (UChar*)ures_getStringByKey(gBundle, errname, &msgLen, &subErr);
    244             if(U_FAILURE(subErr))
    245             {
    246                 msg = NULL;
    247             }
    248         }
    249     }
    250 
    251     if(msg == NULL)  /* Couldn't find it anywhere.. */
    252     {
    253         char error[128];
    254         textMsg = u_errorName(err);
    255         if (!textMsg) {
    256             sprintf(error, "UNDOCUMENTED ICU ERROR %d", err);
    257             textMsg = error;
    258         }
    259         msg = (UChar*)malloc((strlen(textMsg)+1)*sizeof(msg[0]));
    260         u_charsToUChars(textMsg, msg, (int32_t)(strlen(textMsg)+1));
    261     }
    262 
    263     if(err>=0)
    264         gErrMessages[err] = msg;
    265     else
    266         gInfoMessages[err-U_ERROR_WARNING_START] = msg;
    267 
    268     return msg;
    269 }
    270