]>
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 | |
159 | va_start(ap, tag); | |
160 | ||
161 | resultLength = u_vformatMessage(uloc_getDefault(), msg, msgLen, result, resultLength, ap, &err); | |
162 | ||
163 | va_end(ap); | |
164 | ||
165 | if(U_FAILURE(err)) | |
166 | { | |
167 | #if 0 | |
168 | fprintf(stderr, "u_wmsg: failed to format %s:%s, err %s\n", | |
169 | uloc_getDefault(), | |
170 | tag, | |
171 | u_errorName(err)); | |
172 | #endif | |
173 | err = U_ZERO_ERROR; | |
174 | uprint(msg,msgLen, fp, &err); | |
175 | return -1; | |
176 | } | |
177 | ||
178 | uprint(result, resultLength, fp, &err); | |
179 | #endif | |
180 | ||
181 | if(U_FAILURE(err)) | |
182 | { | |
183 | #if 0 | |
184 | fprintf(stderr, "u_wmsg: failed to print %s: %s, err %s\n", | |
185 | uloc_getDefault(), | |
186 | tag, | |
187 | u_errorName(err)); | |
188 | #endif | |
189 | return -1; | |
190 | } | |
191 | ||
192 | return 0; | |
193 | } | |
194 | ||
195 | /* these will break if the # of messages change. simply add or remove 0's .. */ | |
374ca955 | 196 | UChar **gInfoMessages = NULL; |
b75a7d8f | 197 | |
374ca955 | 198 | UChar **gErrMessages = NULL; |
b75a7d8f A |
199 | |
200 | static const UChar *fetchErrorName(UErrorCode err) | |
201 | { | |
374ca955 A |
202 | if (!gInfoMessages) { |
203 | gInfoMessages = (UChar **)malloc((U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*)); | |
204 | memset(gInfoMessages, 0, (U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*)); | |
205 | } | |
206 | if (!gErrMessages) { | |
207 | gErrMessages = (UChar **)malloc(U_ERROR_LIMIT*sizeof(UChar*)); | |
208 | memset(gErrMessages, 0, U_ERROR_LIMIT*sizeof(UChar*)); | |
209 | } | |
b75a7d8f A |
210 | if(err>=0) |
211 | return gErrMessages[err]; | |
212 | else | |
213 | return gInfoMessages[err-U_ERROR_WARNING_START]; | |
214 | } | |
215 | ||
374ca955 | 216 | U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err) |
b75a7d8f A |
217 | { |
218 | UChar *msg; | |
219 | int32_t msgLen; | |
220 | UErrorCode subErr = U_ZERO_ERROR; | |
221 | const char *textMsg = NULL; | |
222 | ||
223 | /* try the cache */ | |
224 | msg = (UChar*)fetchErrorName(err); | |
225 | ||
226 | if(msg) | |
227 | { | |
228 | return msg; | |
229 | } | |
230 | ||
231 | if(gBundle == NULL) | |
232 | { | |
233 | msg = NULL; | |
234 | } | |
235 | else | |
236 | { | |
237 | const char *errname = u_errorName(err); | |
238 | if (errname) { | |
239 | msg = (UChar*)ures_getStringByKey(gBundle, errname, &msgLen, &subErr); | |
240 | if(U_FAILURE(subErr)) | |
241 | { | |
242 | msg = NULL; | |
243 | } | |
244 | } | |
245 | } | |
246 | ||
247 | if(msg == NULL) /* Couldn't find it anywhere.. */ | |
248 | { | |
249 | char error[128]; | |
250 | textMsg = u_errorName(err); | |
251 | if (!textMsg) { | |
252 | sprintf(error, "UNDOCUMENTED ICU ERROR %d", err); | |
253 | textMsg = error; | |
254 | } | |
255 | msg = (UChar*)malloc((strlen(textMsg)+1)*sizeof(msg[0])); | |
256 | u_charsToUChars(textMsg, msg, (int32_t)(strlen(textMsg)+1)); | |
257 | } | |
258 | ||
259 | if(err>=0) | |
260 | gErrMessages[err] = msg; | |
261 | else | |
262 | gInfoMessages[err-U_ERROR_WARNING_START] = msg; | |
263 | ||
264 | return msg; | |
265 | } |