comparison src/SDL_error.c @ 1818:7995cc87b777

Fixed some bugs in string handling Cleaned up error message code, UTF-8 is used instead of UCS2 Added detection for MPEG Layer 3 audio for more informative errors.
author Sam Lantinga <slouken@libsdl.org>
date Thu, 11 May 2006 21:03:23 +0000
parents 97d0966f4bf7
children e25445333ccf
comparison
equal deleted inserted replaced
1817:0ab4c830141f 1818:7995cc87b777
37 37
38 #define SDL_ERRBUFIZE 1024 38 #define SDL_ERRBUFIZE 1024
39 39
40 /* Private functions */ 40 /* Private functions */
41 41
42 static void SDL_LookupString(const Uint8 *key, Uint16 *buf, int buflen) 42 static const char *SDL_LookupString(const char *key)
43 { 43 {
44 /* FIXME: Add code to lookup key in language string hash-table */ 44 /* FIXME: Add code to lookup key in language string hash-table */
45 45 return key;
46 /* Key not found in language string hash-table */
47 while ( *key && (--buflen > 0) ) {
48 *buf++ = *key++;
49 }
50 *buf = 0; /* NULL terminate string */
51 } 46 }
52 47
53 /* Public functions */ 48 /* Public functions */
54 49
55 void SDL_SetError (const char *fmt, ...) 50 void SDL_SetError (const char *fmt, ...)
64 59
65 va_start(ap, fmt); 60 va_start(ap, fmt);
66 error->argc = 0; 61 error->argc = 0;
67 while ( *fmt ) { 62 while ( *fmt ) {
68 if ( *fmt++ == '%' ) { 63 if ( *fmt++ == '%' ) {
64 while ( *fmt == '.' || (*fmt >= '0' && *fmt <= '9') ) {
65 ++fmt;
66 }
69 switch (*fmt++) { 67 switch (*fmt++) {
70 case 0: /* Malformed format string.. */ 68 case 0: /* Malformed format string.. */
71 --fmt; 69 --fmt;
72 break; 70 break;
73 #if 0 /* What is a character anyway? (UNICODE issues) */
74 case 'c': 71 case 'c':
75 error->args[error->argc++].value_c = 72 case 'i':
76 va_arg(ap, unsigned char);
77 break;
78 #endif
79 case 'd': 73 case 'd':
74 case 'u':
75 case 'o':
76 case 'x':
77 case 'X':
80 error->args[error->argc++].value_i = 78 error->args[error->argc++].value_i =
81 va_arg(ap, int); 79 va_arg(ap, int);
82 break; 80 break;
83 case 'f': 81 case 'f':
84 error->args[error->argc++].value_f = 82 error->args[error->argc++].value_f =
112 #ifdef DEBUG_ERROR 110 #ifdef DEBUG_ERROR
113 fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError()); 111 fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError());
114 #endif 112 #endif
115 } 113 }
116 114
117 /* Print out an integer value to a UNICODE buffer */
118 static int PrintInt(Uint16 *str, unsigned int maxlen, int value)
119 {
120 char tmp[128];
121 int len, i;
122
123 SDL_snprintf(tmp, SDL_arraysize(tmp), "%d", value);
124 len = 0;
125 if ( SDL_strlen(tmp) < maxlen ) {
126 for ( i=0; tmp[i]; ++i ) {
127 *str++ = tmp[i];
128 ++len;
129 }
130 }
131 return(len);
132 }
133 /* Print out a double value to a UNICODE buffer */
134 static int PrintDouble(Uint16 *str, unsigned int maxlen, double value)
135 {
136 char tmp[128];
137 int len, i;
138
139 SDL_snprintf(tmp, SDL_arraysize(tmp), "%f", value);
140 len = 0;
141 if ( SDL_strlen(tmp) < maxlen ) {
142 for ( i=0; tmp[i]; ++i ) {
143 *str++ = tmp[i];
144 ++len;
145 }
146 }
147 return(len);
148 }
149 /* Print out a pointer value to a UNICODE buffer */
150 static int PrintPointer(Uint16 *str, unsigned int maxlen, void *value)
151 {
152 char tmp[128];
153 int len, i;
154
155 SDL_snprintf(tmp, SDL_arraysize(tmp), "%p", value);
156 len = 0;
157 if ( SDL_strlen(tmp) < maxlen ) {
158 for ( i=0; tmp[i]; ++i ) {
159 *str++ = tmp[i];
160 ++len;
161 }
162 }
163 return(len);
164 }
165
166 /* This function has a bit more overhead than most error functions 115 /* This function has a bit more overhead than most error functions
167 so that it supports internationalization and thread-safe errors. 116 so that it supports internationalization and thread-safe errors.
168 */ 117 */
169 Uint16 *SDL_GetErrorMsgUNICODE(Uint16 *errstr, unsigned int maxlen) 118 char *SDL_GetErrorMsg(char *errstr, unsigned int maxlen)
170 { 119 {
171 SDL_error *error; 120 SDL_error *error;
172 121
173 /* Clear the error string */ 122 /* Clear the error string */
174 *errstr = 0; --maxlen; 123 *errstr = '\0'; --maxlen;
175 124
176 /* Get the thread-safe error, and print it out */ 125 /* Get the thread-safe error, and print it out */
177 error = SDL_GetErrBuf(); 126 error = SDL_GetErrBuf();
178 if ( error->error ) { 127 if ( error->error ) {
179 Uint16 translated[ERR_MAX_STRLEN], *fmt, *msg; 128 const char *fmt;
129 char *msg = errstr;
180 int len; 130 int len;
181 int argi; 131 int argi;
182 132
183 /* Print out the UNICODE error message */ 133 fmt = SDL_LookupString(error->key);
184 SDL_LookupString(error->key, translated, sizeof(translated));
185 msg = errstr;
186 argi = 0; 134 argi = 0;
187 for ( fmt=translated; *fmt && (maxlen > 0); ) { 135 while ( *fmt && (maxlen > 0) ) {
188 if ( *fmt == '%' ) { 136 if ( *fmt == '%' ) {
189 switch (fmt[1]) { 137 char tmp[32], *spot = tmp;
190 case 'S': /* Special SKIP operand */ 138 *spot++ = *fmt++;
191 argi += (fmt[2] - '0'); 139 while ( *fmt == '.' || (*fmt >= '0' && *fmt <= '9') && spot < (tmp+SDL_arraysize(tmp)-2) ) {
192 ++fmt; 140 *spot++ = *fmt++;
193 break; 141 }
142 *spot++ = *fmt++;
143 *spot++ = '\0';
144 switch (spot[-2]) {
194 case '%': 145 case '%':
195 *msg++ = '%'; 146 *msg++ = '%';
196 maxlen -= 1; 147 maxlen -= 1;
197 break; 148 break;
198 #if 0 /* What is a character anyway? (UNICODE issues) */
199 case 'c': 149 case 'c':
200 *msg++ = (unsigned char) 150 case 'i':
201 error->args[argi++].value_c; 151 case 'd':
202 maxlen -= 1; 152 case 'u':
203 break; 153 case 'o':
204 #endif 154 case 'x':
205 case 'd': 155 case 'X':
206 len = PrintInt(msg, maxlen, 156 len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_i);
207 error->args[argi++].value_i);
208 msg += len; 157 msg += len;
209 maxlen -= len; 158 maxlen -= len;
210 break; 159 break;
211 case 'f': 160 case 'f':
212 len = PrintDouble(msg, maxlen, 161 len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_f);
213 error->args[argi++].value_f);
214 msg += len; 162 msg += len;
215 maxlen -= len; 163 maxlen -= len;
216 break; 164 break;
217 case 'p': 165 case 'p':
218 len = PrintPointer(msg, maxlen, 166 len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_ptr);
219 error->args[argi++].value_ptr); 167 msg += len;
220 msg += len; 168 maxlen -= len;
221 maxlen -= len; 169 break;
222 break; 170 case 's':
223 case 's': /* UNICODE string */ 171 len = SDL_snprintf(msg, maxlen, tmp, SDL_LookupString(error->args[argi++].buf));
224 { Uint16 buf[ERR_MAX_STRLEN], *str; 172 msg += len;
225 SDL_LookupString(error->args[argi++].buf, buf, sizeof(buf)); 173 maxlen -= len;
226 str = buf;
227 while ( *str && (maxlen > 0) ) {
228 *msg++ = *str++;
229 maxlen -= 1;
230 }
231 }
232 break; 174 break;
233 } 175 }
234 fmt += 2;
235 } else { 176 } else {
236 *msg++ = *fmt++; 177 *msg++ = *fmt++;
237 maxlen -= 1; 178 maxlen -= 1;
238 } 179 }
239 } 180 }
240 *msg = 0; /* NULL terminate the string */ 181 *msg = 0; /* NULL terminate the string */
241 } 182 }
242 return(errstr);
243 }
244
245 Uint8 *SDL_GetErrorMsg(Uint8 *errstr, unsigned int maxlen)
246 {
247 Uint16 *errstr16;
248 unsigned int i;
249
250 /* Allocate the UNICODE buffer */
251 errstr16 = (Uint16 *)SDL_malloc(maxlen * (sizeof *errstr16));
252 if ( ! errstr16 ) {
253 SDL_strlcpy((char *)errstr, "Out of memory", maxlen);
254 return(errstr);
255 }
256
257 /* Get the error message */
258 SDL_GetErrorMsgUNICODE(errstr16, maxlen);
259
260 /* Convert from UNICODE to Latin1 encoding */
261 for ( i=0; i<maxlen; ++i ) {
262 errstr[i] = (Uint8)errstr16[i];
263 }
264
265 /* Free UNICODE buffer (if necessary) */
266 SDL_free(errstr16);
267
268 return(errstr); 183 return(errstr);
269 } 184 }
270 185
271 /* Available for backwards compatibility */ 186 /* Available for backwards compatibility */
272 char *SDL_GetError (void) 187 char *SDL_GetError (void)