diff options
Diffstat (limited to '')
-rw-r--r-- | intl/icu/source/extra/uconv/uwmsg.c | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/intl/icu/source/extra/uconv/uwmsg.c b/intl/icu/source/extra/uconv/uwmsg.c new file mode 100644 index 0000000000..2f611e94eb --- /dev/null +++ b/intl/icu/source/extra/uconv/uwmsg.c @@ -0,0 +1,267 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (C) 1998-2016, International Business Machines Corporation +* and others. All Rights Reserved. +********************************************************************** +* +* File uwmsg.c +* +* Modification History: +* +* Date Name Description +* 06/14/99 stephen Creation. +******************************************************************************* +*/ + +#include "unicode/ucnv.h" +#include "unicode/ustring.h" +#include "unicode/umsg.h" +#include "unicode/uwmsg.h" +#include "unicode/ures.h" +#include "unicode/putil.h" +#include "cmemory.h" +#include "cstring.h" + +#include <stdbool.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#define BUF_SIZE 128 + +/* Print a ustring to the specified FILE* in the default codepage */ +static void +uprint(const UChar *s, + int32_t sourceLen, + FILE *f, + UErrorCode *status) +{ + /* converter */ + UConverter *converter; + char buf [BUF_SIZE]; + const UChar *mySource; + const UChar *mySourceEnd; + char *myTarget; + int32_t arraySize; + + if(s == 0) return; + + /* set up the conversion parameters */ + mySource = s; + mySourceEnd = mySource + sourceLen; + myTarget = buf; + arraySize = BUF_SIZE; + + /* open a default converter */ + converter = ucnv_open(0, status); + + /* if we failed, clean up and exit */ + if(U_FAILURE(*status)) goto finish; + + /* perform the conversion */ + do { + /* reset the error code */ + *status = U_ZERO_ERROR; + + /* perform the conversion */ + ucnv_fromUnicode(converter, &myTarget, myTarget + arraySize, + &mySource, mySourceEnd, NULL, + true, status); + + /* Write the converted data to the FILE* */ + fwrite(buf, sizeof(char), myTarget - buf, f); + + /* update the conversion parameters*/ + myTarget = buf; + arraySize = BUF_SIZE; + } + while(*status == U_BUFFER_OVERFLOW_ERROR); + +finish: + + /* close the converter */ + ucnv_close(converter); +} + +static UResourceBundle *gBundle = NULL; + +U_STRING_DECL(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38); + +U_CFUNC UResourceBundle *u_wmsg_setPath(const char *path, UErrorCode *err) +{ + if(U_FAILURE(*err)) + { + return 0; + } + + if(gBundle != NULL) + { + *err = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + else + { + UResourceBundle *b = NULL; + b = ures_open(path, NULL, err); + if(U_FAILURE(*err)) + { + return 0; + } + + gBundle = b; + + U_STRING_INIT(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38); + } + + return gBundle; +} + +/* Format a message and print it's output to fp */ +U_CFUNC int u_wmsg(FILE *fp, const char *tag, ... ) +{ + const UChar *msg; + int32_t msgLen; + UErrorCode err = U_ZERO_ERROR; +#if !UCONFIG_NO_FORMATTING + va_list ap; +#endif + UChar result[4096]; + int32_t resultLength = UPRV_LENGTHOF(result); + + if(gBundle == NULL) + { +#if 0 + fprintf(stderr, "u_wmsg: No path set!!\n"); /* FIXME: codepage?? */ +#endif + return -1; + } + + msg = ures_getStringByKey(gBundle, tag, &msgLen, &err); + + if(U_FAILURE(err)) + { + return -1; + } + +#if UCONFIG_NO_FORMATTING + resultLength = UPRV_LENGTHOF(gNoFormatting); + if((msgLen + resultLength) <= UPRV_LENGTHOF(result)) { + memcpy(result, msg, msgLen * U_SIZEOF_UCHAR); + memcpy(result + msgLen, gNoFormatting, resultLength); + resultLength += msgLen; + uprint(result, resultLength, fp, &err); + } else { + uprint(msg,msgLen, fp, &err); + } +#else + (void)gNoFormatting; // suppress -Wunused-variable + va_start(ap, tag); + + resultLength = u_vformatMessage(uloc_getDefault(), msg, msgLen, result, resultLength, ap, &err); + + va_end(ap); + + if(U_FAILURE(err)) + { +#if 0 + fprintf(stderr, "u_wmsg: failed to format %s:%s, err %s\n", + uloc_getDefault(), + tag, + u_errorName(err)); +#endif + err = U_ZERO_ERROR; + uprint(msg,msgLen, fp, &err); + return -1; + } + + uprint(result, resultLength, fp, &err); +#endif + + if(U_FAILURE(err)) + { +#if 0 + fprintf(stderr, "u_wmsg: failed to print %s: %s, err %s\n", + uloc_getDefault(), + tag, + u_errorName(err)); +#endif + return -1; + } + + return 0; +} + +/* these will break if the # of messages change. simply add or remove 0's .. */ +UChar **gInfoMessages = NULL; + +UChar **gErrMessages = NULL; + +static const UChar *fetchErrorName(UErrorCode err) +{ + if (!gInfoMessages) { + gInfoMessages = (UChar **)malloc((U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*)); + memset(gInfoMessages, 0, (U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*)); + } + if (!gErrMessages) { + gErrMessages = (UChar **)malloc(U_ERROR_LIMIT*sizeof(UChar*)); + memset(gErrMessages, 0, U_ERROR_LIMIT*sizeof(UChar*)); + } + if(err>=0) + return gErrMessages[err]; + else + return gInfoMessages[err-U_ERROR_WARNING_START]; +} + +U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err) +{ + UChar *msg; + int32_t msgLen; + UErrorCode subErr = U_ZERO_ERROR; + const char *textMsg = NULL; + + /* try the cache */ + msg = (UChar*)fetchErrorName(err); + + if(msg) + { + return msg; + } + + if(gBundle == NULL) + { + msg = NULL; + } + else + { + const char *errname = u_errorName(err); + if (errname) { + msg = (UChar*)ures_getStringByKey(gBundle, errname, &msgLen, &subErr); + if(U_FAILURE(subErr)) + { + msg = NULL; + } + } + } + + if(msg == NULL) /* Couldn't find it anywhere.. */ + { + char error[128]; + textMsg = u_errorName(err); + if (!textMsg) { + sprintf(error, "UNDOCUMENTED ICU ERROR %d", err); + textMsg = error; + } + msg = (UChar*)malloc((strlen(textMsg)+1)*sizeof(msg[0])); + u_charsToUChars(textMsg, msg, (int32_t)(strlen(textMsg)+1)); + } + + if(err>=0) + gErrMessages[err] = msg; + else + gInfoMessages[err-U_ERROR_WARNING_START] = msg; + + return msg; +} |