]> git.saurik.com Git - apple/icu.git/blob - icuSources/extra/uconv/uwmsg.c
ICU-64232.0.1.tar.gz
[apple/icu.git] / icuSources / extra / uconv / uwmsg.c
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 <stdlib.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #define BUF_SIZE 128
33
34 /* Print a ustring to the specified FILE* in the default codepage */
35 static void
36 uprint(const UChar *s,
37 int32_t sourceLen,
38 FILE *f,
39 UErrorCode *status)
40 {
41 /* converter */
42 UConverter *converter;
43 char buf [BUF_SIZE];
44 const UChar *mySource;
45 const UChar *mySourceEnd;
46 char *myTarget;
47 int32_t arraySize;
48
49 if(s == 0) return;
50
51 /* set up the conversion parameters */
52 mySource = s;
53 mySourceEnd = mySource + sourceLen;
54 myTarget = buf;
55 arraySize = BUF_SIZE;
56
57 /* open a default converter */
58 converter = ucnv_open(0, status);
59
60 /* if we failed, clean up and exit */
61 if(U_FAILURE(*status)) goto finish;
62
63 /* perform the conversion */
64 do {
65 /* reset the error code */
66 *status = U_ZERO_ERROR;
67
68 /* perform the conversion */
69 ucnv_fromUnicode(converter, &myTarget, myTarget + arraySize,
70 &mySource, mySourceEnd, NULL,
71 TRUE, status);
72
73 /* Write the converted data to the FILE* */
74 fwrite(buf, sizeof(char), myTarget - buf, f);
75
76 /* update the conversion parameters*/
77 myTarget = buf;
78 arraySize = BUF_SIZE;
79 }
80 while(*status == U_BUFFER_OVERFLOW_ERROR);
81
82 finish:
83
84 /* close the converter */
85 ucnv_close(converter);
86 }
87
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 gBundle = b;
114
115 U_STRING_INIT(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38);
116 }
117
118 return gBundle;
119 }
120
121 /* Format a message and print it's output to fp */
122 U_CFUNC int u_wmsg(FILE *fp, const char *tag, ... )
123 {
124 const UChar *msg;
125 int32_t msgLen;
126 UErrorCode err = U_ZERO_ERROR;
127 #if !UCONFIG_NO_FORMATTING
128 va_list ap;
129 #endif
130 UChar result[4096];
131 int32_t resultLength = UPRV_LENGTHOF(result);
132
133 if(gBundle == NULL)
134 {
135 #if 0
136 fprintf(stderr, "u_wmsg: No path set!!\n"); /* FIXME: codepage?? */
137 #endif
138 return -1;
139 }
140
141 msg = ures_getStringByKey(gBundle, tag, &msgLen, &err);
142
143 if(U_FAILURE(err))
144 {
145 return -1;
146 }
147
148 #if UCONFIG_NO_FORMATTING
149 resultLength = UPRV_LENGTHOF(gNoFormatting);
150 if((msgLen + resultLength) <= UPRV_LENGTHOF(result)) {
151 memcpy(result, msg, msgLen * U_SIZEOF_UCHAR);
152 memcpy(result + msgLen, gNoFormatting, resultLength);
153 resultLength += msgLen;
154 uprint(result, resultLength, fp, &err);
155 } else {
156 uprint(msg,msgLen, fp, &err);
157 }
158 #else
159 (void)gNoFormatting; // suppress -Wunused-variable
160 va_start(ap, tag);
161
162 resultLength = u_vformatMessage(uloc_getDefault(), msg, msgLen, result, resultLength, ap, &err);
163
164 va_end(ap);
165
166 if(U_FAILURE(err))
167 {
168 #if 0
169 fprintf(stderr, "u_wmsg: failed to format %s:%s, err %s\n",
170 uloc_getDefault(),
171 tag,
172 u_errorName(err));
173 #endif
174 err = U_ZERO_ERROR;
175 uprint(msg,msgLen, fp, &err);
176 return -1;
177 }
178
179 uprint(result, resultLength, fp, &err);
180 #endif
181
182 if(U_FAILURE(err))
183 {
184 #if 0
185 fprintf(stderr, "u_wmsg: failed to print %s: %s, err %s\n",
186 uloc_getDefault(),
187 tag,
188 u_errorName(err));
189 #endif
190 return -1;
191 }
192
193 return 0;
194 }
195
196 /* these will break if the # of messages change. simply add or remove 0's .. */
197 UChar **gInfoMessages = NULL;
198
199 UChar **gErrMessages = NULL;
200
201 static const UChar *fetchErrorName(UErrorCode err)
202 {
203 if (!gInfoMessages) {
204 gInfoMessages = (UChar **)malloc((U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
205 memset(gInfoMessages, 0, (U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
206 }
207 if (!gErrMessages) {
208 gErrMessages = (UChar **)malloc(U_ERROR_LIMIT*sizeof(UChar*));
209 memset(gErrMessages, 0, U_ERROR_LIMIT*sizeof(UChar*));
210 }
211 if(err>=0)
212 return gErrMessages[err];
213 else
214 return gInfoMessages[err-U_ERROR_WARNING_START];
215 }
216
217 U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err)
218 {
219 UChar *msg;
220 int32_t msgLen;
221 UErrorCode subErr = U_ZERO_ERROR;
222 const char *textMsg = NULL;
223
224 /* try the cache */
225 msg = (UChar*)fetchErrorName(err);
226
227 if(msg)
228 {
229 return msg;
230 }
231
232 if(gBundle == NULL)
233 {
234 msg = NULL;
235 }
236 else
237 {
238 const char *errname = u_errorName(err);
239 if (errname) {
240 msg = (UChar*)ures_getStringByKey(gBundle, errname, &msgLen, &subErr);
241 if(U_FAILURE(subErr))
242 {
243 msg = NULL;
244 }
245 }
246 }
247
248 if(msg == NULL) /* Couldn't find it anywhere.. */
249 {
250 char error[128];
251 textMsg = u_errorName(err);
252 if (!textMsg) {
253 sprintf(error, "UNDOCUMENTED ICU ERROR %d", err);
254 textMsg = error;
255 }
256 msg = (UChar*)malloc((strlen(textMsg)+1)*sizeof(msg[0]));
257 u_charsToUChars(textMsg, msg, (int32_t)(strlen(textMsg)+1));
258 }
259
260 if(err>=0)
261 gErrMessages[err] = msg;
262 else
263 gInfoMessages[err-U_ERROR_WARNING_START] = msg;
264
265 return msg;
266 }