]>
Commit | Line | Data |
---|---|---|
f3c0d7a5 A |
1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
b75a7d8f A |
3 | /* |
4 | ********************************************************************** | |
2ca993e8 | 5 | * Copyright (C) 1998-2016, International Business Machines Corporation |
b75a7d8f A |
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" | |
374ca955 | 23 | #include "unicode/putil.h" |
2ca993e8 | 24 | #include "cmemory.h" |
b75a7d8f A |
25 | #include "cstring.h" |
26 | ||
27 | #include <stdlib.h> | |
28 | #include <stdarg.h> | |
29 | #include <stdio.h> | |
30 | #include <string.h> | |
31 | ||
b75a7d8f A |
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 | ||
b75a7d8f A |
88 | static UResourceBundle *gBundle = NULL; |
89 | ||
90 | U_STRING_DECL(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38); | |
91 | ||
374ca955 | 92 | U_CFUNC UResourceBundle *u_wmsg_setPath(const char *path, UErrorCode *err) |
b75a7d8f A |
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 | ||
b75a7d8f A |
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 */ | |
374ca955 | 122 | U_CFUNC int u_wmsg(FILE *fp, const char *tag, ... ) |
b75a7d8f A |
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]; | |
b331163b | 131 | int32_t resultLength = UPRV_LENGTHOF(result); |
b75a7d8f A |
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 | { | |
b75a7d8f A |
145 | return -1; |
146 | } | |
147 | ||
148 | #if UCONFIG_NO_FORMATTING | |
2ca993e8 | 149 | resultLength = UPRV_LENGTHOF(gNoFormatting); |
b331163b | 150 | if((msgLen + resultLength) <= UPRV_LENGTHOF(result)) { |
b75a7d8f A |
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 | |
3d1f044b | 159 | (void)gNoFormatting; // suppress -Wunused-variable |
b75a7d8f A |
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 .. */ | |
374ca955 | 197 | UChar **gInfoMessages = NULL; |
b75a7d8f | 198 | |
374ca955 | 199 | UChar **gErrMessages = NULL; |
b75a7d8f A |
200 | |
201 | static const UChar *fetchErrorName(UErrorCode err) | |
202 | { | |
374ca955 A |
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 | } | |
b75a7d8f A |
211 | if(err>=0) |
212 | return gErrMessages[err]; | |
213 | else | |
214 | return gInfoMessages[err-U_ERROR_WARNING_START]; | |
215 | } | |
216 | ||
374ca955 | 217 | U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err) |
b75a7d8f A |
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 | } |