diff options
author | Franklin Wei <git@fwei.tk> | 2017-01-21 15:18:31 -0500 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2017-12-23 21:01:26 -0500 |
commit | a855d6202536ff28e5aae4f22a0f31d8f5b325d0 (patch) | |
tree | 8c75f224dd64ed360505afa8843d016b0d75000b /apps/plugins/sdl/src/stdlib/SDL_string.c | |
parent | 01c6dcf6c7b9bb1ad2fa0450f99bacc5f3d3e04b (diff) | |
download | rockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.tar.gz rockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.zip |
Port of Duke Nukem 3D
This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL
for Rockbox.
Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9
Diffstat (limited to 'apps/plugins/sdl/src/stdlib/SDL_string.c')
-rw-r--r-- | apps/plugins/sdl/src/stdlib/SDL_string.c | 1248 |
1 files changed, 1248 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/stdlib/SDL_string.c b/apps/plugins/sdl/src/stdlib/SDL_string.c new file mode 100644 index 0000000000..550a623a95 --- /dev/null +++ b/apps/plugins/sdl/src/stdlib/SDL_string.c | |||
@@ -0,0 +1,1248 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | /* This file contains portable string manipulation functions for SDL */ | ||
25 | |||
26 | #include "SDL_stdinc.h" | ||
27 | |||
28 | |||
29 | #define SDL_isupperhex(X) (((X) >= 'A') && ((X) <= 'F')) | ||
30 | #define SDL_islowerhex(X) (((X) >= 'a') && ((X) <= 'f')) | ||
31 | |||
32 | #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL) | ||
33 | static size_t SDL_ScanLong(const char *text, int radix, long *valuep) | ||
34 | { | ||
35 | const char *textstart = text; | ||
36 | long value = 0; | ||
37 | SDL_bool negative = SDL_FALSE; | ||
38 | |||
39 | if ( *text == '-' ) { | ||
40 | negative = SDL_TRUE; | ||
41 | ++text; | ||
42 | } | ||
43 | if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { | ||
44 | text += 2; | ||
45 | } | ||
46 | for ( ; ; ) { | ||
47 | int v; | ||
48 | if ( SDL_isdigit((unsigned char) *text) ) { | ||
49 | v = *text - '0'; | ||
50 | } else if ( radix == 16 && SDL_isupperhex(*text) ) { | ||
51 | v = 10 + (*text - 'A'); | ||
52 | } else if ( radix == 16 && SDL_islowerhex(*text) ) { | ||
53 | v = 10 + (*text - 'a'); | ||
54 | } else { | ||
55 | break; | ||
56 | } | ||
57 | value *= radix; | ||
58 | value += v; | ||
59 | ++text; | ||
60 | } | ||
61 | if ( valuep ) { | ||
62 | if ( negative && value ) { | ||
63 | *valuep = -value; | ||
64 | } else { | ||
65 | *valuep = value; | ||
66 | } | ||
67 | } | ||
68 | return (text - textstart); | ||
69 | } | ||
70 | #endif | ||
71 | |||
72 | #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOUL) || !defined(HAVE_STRTOD) | ||
73 | static size_t SDL_ScanUnsignedLong(const char *text, int radix, unsigned long *valuep) | ||
74 | { | ||
75 | const char *textstart = text; | ||
76 | unsigned long value = 0; | ||
77 | |||
78 | if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { | ||
79 | text += 2; | ||
80 | } | ||
81 | for ( ; ; ) { | ||
82 | int v; | ||
83 | if ( SDL_isdigit((unsigned char) *text) ) { | ||
84 | v = *text - '0'; | ||
85 | } else if ( radix == 16 && SDL_isupperhex(*text) ) { | ||
86 | v = 10 + (*text - 'A'); | ||
87 | } else if ( radix == 16 && SDL_islowerhex(*text) ) { | ||
88 | v = 10 + (*text - 'a'); | ||
89 | } else { | ||
90 | break; | ||
91 | } | ||
92 | value *= radix; | ||
93 | value += v; | ||
94 | ++text; | ||
95 | } | ||
96 | if ( valuep ) { | ||
97 | *valuep = value; | ||
98 | } | ||
99 | return (text - textstart); | ||
100 | } | ||
101 | #endif | ||
102 | |||
103 | #ifndef HAVE_SSCANF | ||
104 | static size_t SDL_ScanUintPtrT(const char *text, int radix, uintptr_t *valuep) | ||
105 | { | ||
106 | const char *textstart = text; | ||
107 | uintptr_t value = 0; | ||
108 | |||
109 | if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { | ||
110 | text += 2; | ||
111 | } | ||
112 | for ( ; ; ) { | ||
113 | int v; | ||
114 | if ( SDL_isdigit((unsigned char) *text) ) { | ||
115 | v = *text - '0'; | ||
116 | } else if ( radix == 16 && SDL_isupperhex(*text) ) { | ||
117 | v = 10 + (*text - 'A'); | ||
118 | } else if ( radix == 16 && SDL_islowerhex(*text) ) { | ||
119 | v = 10 + (*text - 'a'); | ||
120 | } else { | ||
121 | break; | ||
122 | } | ||
123 | value *= radix; | ||
124 | value += v; | ||
125 | ++text; | ||
126 | } | ||
127 | if ( valuep ) { | ||
128 | *valuep = value; | ||
129 | } | ||
130 | return (text - textstart); | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | #ifdef SDL_HAS_64BIT_TYPE | ||
135 | #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOLL) | ||
136 | static size_t SDL_ScanLongLong(const char *text, int radix, Sint64 *valuep) | ||
137 | { | ||
138 | const char *textstart = text; | ||
139 | Sint64 value = 0; | ||
140 | SDL_bool negative = SDL_FALSE; | ||
141 | |||
142 | if ( *text == '-' ) { | ||
143 | negative = SDL_TRUE; | ||
144 | ++text; | ||
145 | } | ||
146 | if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { | ||
147 | text += 2; | ||
148 | } | ||
149 | for ( ; ; ) { | ||
150 | int v; | ||
151 | if ( SDL_isdigit((unsigned char) *text) ) { | ||
152 | v = *text - '0'; | ||
153 | } else if ( radix == 16 && SDL_isupperhex(*text) ) { | ||
154 | v = 10 + (*text - 'A'); | ||
155 | } else if ( radix == 16 && SDL_islowerhex(*text) ) { | ||
156 | v = 10 + (*text - 'a'); | ||
157 | } else { | ||
158 | break; | ||
159 | } | ||
160 | value *= radix; | ||
161 | value += v; | ||
162 | ++text; | ||
163 | } | ||
164 | if ( valuep ) { | ||
165 | if ( negative && value ) { | ||
166 | *valuep = -value; | ||
167 | } else { | ||
168 | *valuep = value; | ||
169 | } | ||
170 | } | ||
171 | return (text - textstart); | ||
172 | } | ||
173 | #endif | ||
174 | |||
175 | #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOULL) | ||
176 | static size_t SDL_ScanUnsignedLongLong(const char *text, int radix, Uint64 *valuep) | ||
177 | { | ||
178 | const char *textstart = text; | ||
179 | Uint64 value = 0; | ||
180 | |||
181 | if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { | ||
182 | text += 2; | ||
183 | } | ||
184 | for ( ; ; ) { | ||
185 | int v; | ||
186 | if ( SDL_isdigit((unsigned char) *text) ) { | ||
187 | v = *text - '0'; | ||
188 | } else if ( radix == 16 && SDL_isupperhex(*text) ) { | ||
189 | v = 10 + (*text - 'A'); | ||
190 | } else if ( radix == 16 && SDL_islowerhex(*text) ) { | ||
191 | v = 10 + (*text - 'a'); | ||
192 | } else { | ||
193 | break; | ||
194 | } | ||
195 | value *= radix; | ||
196 | value += v; | ||
197 | ++text; | ||
198 | } | ||
199 | if ( valuep ) { | ||
200 | *valuep = value; | ||
201 | } | ||
202 | return (text - textstart); | ||
203 | } | ||
204 | #endif | ||
205 | #endif /* SDL_HAS_64BIT_TYPE */ | ||
206 | |||
207 | #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOD) | ||
208 | static size_t SDL_ScanFloat(const char *text, double *valuep) | ||
209 | { | ||
210 | const char *textstart = text; | ||
211 | unsigned long lvalue = 0; | ||
212 | double value = 0.0; | ||
213 | SDL_bool negative = SDL_FALSE; | ||
214 | |||
215 | if ( *text == '-' ) { | ||
216 | negative = SDL_TRUE; | ||
217 | ++text; | ||
218 | } | ||
219 | text += SDL_ScanUnsignedLong(text, 10, &lvalue); | ||
220 | value += lvalue; | ||
221 | if ( *text == '.' ) { | ||
222 | int mult = 10; | ||
223 | ++text; | ||
224 | while ( SDL_isdigit((unsigned char) *text) ) { | ||
225 | lvalue = *text - '0'; | ||
226 | value += (double)lvalue / mult; | ||
227 | mult *= 10; | ||
228 | ++text; | ||
229 | } | ||
230 | } | ||
231 | if ( valuep ) { | ||
232 | if ( negative && value ) { | ||
233 | *valuep = -value; | ||
234 | } else { | ||
235 | *valuep = value; | ||
236 | } | ||
237 | } | ||
238 | return (text - textstart); | ||
239 | } | ||
240 | #endif | ||
241 | |||
242 | #ifndef SDL_memset | ||
243 | void *SDL_memset(void *dst, int c, size_t len) | ||
244 | { | ||
245 | size_t left = (len % 4); | ||
246 | if ( len >= 4 ) { | ||
247 | Uint32 value = 0; | ||
248 | Uint32 *dstp = (Uint32 *)dst; | ||
249 | int i; | ||
250 | for (i = 0; i < 4; ++i) { | ||
251 | value <<= 8; | ||
252 | value |= c; | ||
253 | } | ||
254 | len /= 4; | ||
255 | while ( len-- ) { | ||
256 | *dstp++ = value; | ||
257 | } | ||
258 | } | ||
259 | if ( left > 0 ) { | ||
260 | Uint8 value = (Uint8)c; | ||
261 | Uint8 *dstp = (Uint8 *)dst; | ||
262 | switch(left) { | ||
263 | case 3: | ||
264 | *dstp++ = value; | ||
265 | case 2: | ||
266 | *dstp++ = value; | ||
267 | case 1: | ||
268 | *dstp++ = value; | ||
269 | } | ||
270 | } | ||
271 | return dst; | ||
272 | } | ||
273 | #endif | ||
274 | |||
275 | #ifndef SDL_memcpy | ||
276 | void *SDL_memcpy(void *dst, const void *src, size_t len) | ||
277 | { | ||
278 | char *srcp = (char *)src; | ||
279 | char *dstp = (char *)dst; | ||
280 | while ( len-- ) { | ||
281 | *dstp++ = *srcp++; | ||
282 | } | ||
283 | return dst; | ||
284 | } | ||
285 | #endif | ||
286 | |||
287 | #ifndef SDL_revcpy | ||
288 | void *SDL_revcpy(void *dst, const void *src, size_t len) | ||
289 | { | ||
290 | char *srcp = (char *)src; | ||
291 | char *dstp = (char *)dst; | ||
292 | srcp += len-1; | ||
293 | dstp += len-1; | ||
294 | while ( len-- ) { | ||
295 | *dstp-- = *srcp--; | ||
296 | } | ||
297 | return dst; | ||
298 | } | ||
299 | #endif | ||
300 | |||
301 | #ifndef SDL_memcmp | ||
302 | int SDL_memcmp(const void *s1, const void *s2, size_t len) | ||
303 | { | ||
304 | char *s1p = (char *)s1; | ||
305 | char *s2p = (char *)s2; | ||
306 | while ( len-- ) { | ||
307 | if ( *s1p != *s2p ) { | ||
308 | return (*s1p - *s2p); | ||
309 | } | ||
310 | ++s1p; | ||
311 | ++s2p; | ||
312 | } | ||
313 | return 0; | ||
314 | } | ||
315 | #endif | ||
316 | |||
317 | #ifndef HAVE_STRLEN | ||
318 | size_t SDL_strlen(const char *string) | ||
319 | { | ||
320 | size_t len = 0; | ||
321 | while ( *string++ ) { | ||
322 | ++len; | ||
323 | } | ||
324 | return len; | ||
325 | } | ||
326 | #endif | ||
327 | |||
328 | #ifndef HAVE_STRLCPY | ||
329 | size_t SDL_strlcpy(char *dst, const char *src, size_t maxlen) | ||
330 | { | ||
331 | size_t srclen = SDL_strlen(src); | ||
332 | if ( maxlen > 0 ) { | ||
333 | size_t len = SDL_min(srclen, maxlen-1); | ||
334 | SDL_memcpy(dst, src, len); | ||
335 | dst[len] = '\0'; | ||
336 | } | ||
337 | return srclen; | ||
338 | } | ||
339 | #endif | ||
340 | |||
341 | #ifndef HAVE_STRLCAT | ||
342 | size_t SDL_strlcat(char *dst, const char *src, size_t maxlen) | ||
343 | { | ||
344 | size_t dstlen = SDL_strlen(dst); | ||
345 | size_t srclen = SDL_strlen(src); | ||
346 | if ( dstlen < maxlen ) { | ||
347 | SDL_strlcpy(dst+dstlen, src, maxlen-dstlen); | ||
348 | } | ||
349 | return dstlen+srclen; | ||
350 | } | ||
351 | #endif | ||
352 | |||
353 | #ifndef HAVE_STRDUP | ||
354 | char *SDL_strdup(const char *string) | ||
355 | { | ||
356 | size_t len = SDL_strlen(string)+1; | ||
357 | char *newstr = SDL_malloc(len); | ||
358 | if ( newstr ) { | ||
359 | SDL_strlcpy(newstr, string, len); | ||
360 | } | ||
361 | return newstr; | ||
362 | } | ||
363 | #endif | ||
364 | |||
365 | #ifndef HAVE__STRREV | ||
366 | char *SDL_strrev(char *string) | ||
367 | { | ||
368 | size_t len = SDL_strlen(string); | ||
369 | char *a = &string[0]; | ||
370 | char *b = &string[len-1]; | ||
371 | len /= 2; | ||
372 | while ( len-- ) { | ||
373 | char c = *a; | ||
374 | *a++ = *b; | ||
375 | *b-- = c; | ||
376 | } | ||
377 | return string; | ||
378 | } | ||
379 | #endif | ||
380 | |||
381 | #ifndef HAVE__STRUPR | ||
382 | char *SDL_strupr(char *string) | ||
383 | { | ||
384 | char *bufp = string; | ||
385 | while ( *bufp ) { | ||
386 | *bufp = SDL_toupper((unsigned char) *bufp); | ||
387 | ++bufp; | ||
388 | } | ||
389 | return string; | ||
390 | } | ||
391 | #endif | ||
392 | |||
393 | #ifndef HAVE__STRLWR | ||
394 | char *SDL_strlwr(char *string) | ||
395 | { | ||
396 | char *bufp = string; | ||
397 | while ( *bufp ) { | ||
398 | *bufp = SDL_tolower((unsigned char) *bufp); | ||
399 | ++bufp; | ||
400 | } | ||
401 | return string; | ||
402 | } | ||
403 | #endif | ||
404 | |||
405 | #ifndef HAVE_STRCHR | ||
406 | char *SDL_strchr(const char *string, int c) | ||
407 | { | ||
408 | while ( *string ) { | ||
409 | if ( *string == c ) { | ||
410 | return (char *)string; | ||
411 | } | ||
412 | ++string; | ||
413 | } | ||
414 | return NULL; | ||
415 | } | ||
416 | #endif | ||
417 | |||
418 | #ifndef HAVE_STRRCHR | ||
419 | char *SDL_strrchr(const char *string, int c) | ||
420 | { | ||
421 | const char *bufp = string + SDL_strlen(string) - 1; | ||
422 | while ( bufp >= string ) { | ||
423 | if ( *bufp == c ) { | ||
424 | return (char *)bufp; | ||
425 | } | ||
426 | --bufp; | ||
427 | } | ||
428 | return NULL; | ||
429 | } | ||
430 | #endif | ||
431 | |||
432 | #ifndef HAVE_STRSTR | ||
433 | char *SDL_strstr(const char *haystack, const char *needle) | ||
434 | { | ||
435 | size_t length = SDL_strlen(needle); | ||
436 | while ( *haystack ) { | ||
437 | if ( SDL_strncmp(haystack, needle, length) == 0 ) { | ||
438 | return (char *)haystack; | ||
439 | } | ||
440 | ++haystack; | ||
441 | } | ||
442 | return NULL; | ||
443 | } | ||
444 | #endif | ||
445 | |||
446 | #if !defined(HAVE__LTOA) || !defined(HAVE__I64TOA) || \ | ||
447 | !defined(HAVE__ULTOA) || !defined(HAVE__UI64TOA) | ||
448 | static const char ntoa_table[] = { | ||
449 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | ||
450 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', | ||
451 | 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', | ||
452 | 'U', 'V', 'W', 'X', 'Y', 'Z' | ||
453 | }; | ||
454 | #endif /* ntoa() conversion table */ | ||
455 | |||
456 | #ifndef HAVE__LTOA | ||
457 | char *SDL_ltoa(long value, char *string, int radix) | ||
458 | { | ||
459 | char *bufp = string; | ||
460 | |||
461 | if ( value < 0 ) { | ||
462 | *bufp++ = '-'; | ||
463 | value = -value; | ||
464 | } | ||
465 | if ( value ) { | ||
466 | while ( value > 0 ) { | ||
467 | *bufp++ = ntoa_table[value % radix]; | ||
468 | value /= radix; | ||
469 | } | ||
470 | } else { | ||
471 | *bufp++ = '0'; | ||
472 | } | ||
473 | *bufp = '\0'; | ||
474 | |||
475 | /* The numbers went into the string backwards. :) */ | ||
476 | if ( *string == '-' ) { | ||
477 | SDL_strrev(string+1); | ||
478 | } else { | ||
479 | SDL_strrev(string); | ||
480 | } | ||
481 | |||
482 | return string; | ||
483 | } | ||
484 | #endif | ||
485 | |||
486 | #ifndef HAVE__ULTOA | ||
487 | char *SDL_ultoa(unsigned long value, char *string, int radix) | ||
488 | { | ||
489 | char *bufp = string; | ||
490 | |||
491 | if ( value ) { | ||
492 | while ( value > 0 ) { | ||
493 | *bufp++ = ntoa_table[value % radix]; | ||
494 | value /= radix; | ||
495 | } | ||
496 | } else { | ||
497 | *bufp++ = '0'; | ||
498 | } | ||
499 | *bufp = '\0'; | ||
500 | |||
501 | /* The numbers went into the string backwards. :) */ | ||
502 | SDL_strrev(string); | ||
503 | |||
504 | return string; | ||
505 | } | ||
506 | #endif | ||
507 | |||
508 | #ifndef HAVE_STRTOL | ||
509 | long SDL_strtol(const char *string, char **endp, int base) | ||
510 | { | ||
511 | size_t len; | ||
512 | long value; | ||
513 | |||
514 | if ( !base ) { | ||
515 | if ( (SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0) ) { | ||
516 | base = 16; | ||
517 | } else { | ||
518 | base = 10; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | len = SDL_ScanLong(string, base, &value); | ||
523 | if ( endp ) { | ||
524 | *endp = (char *)string + len; | ||
525 | } | ||
526 | return value; | ||
527 | } | ||
528 | #endif | ||
529 | |||
530 | #ifndef HAVE_STRTOUL | ||
531 | unsigned long SDL_strtoul(const char *string, char **endp, int base) | ||
532 | { | ||
533 | size_t len; | ||
534 | unsigned long value; | ||
535 | |||
536 | if ( !base ) { | ||
537 | if ( (SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0) ) { | ||
538 | base = 16; | ||
539 | } else { | ||
540 | base = 10; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | len = SDL_ScanUnsignedLong(string, base, &value); | ||
545 | if ( endp ) { | ||
546 | *endp = (char *)string + len; | ||
547 | } | ||
548 | return value; | ||
549 | } | ||
550 | #endif | ||
551 | |||
552 | #ifdef SDL_HAS_64BIT_TYPE | ||
553 | |||
554 | #ifndef HAVE__I64TOA | ||
555 | char *SDL_lltoa(Sint64 value, char *string, int radix) | ||
556 | { | ||
557 | char *bufp = string; | ||
558 | |||
559 | if ( value < 0 ) { | ||
560 | *bufp++ = '-'; | ||
561 | value = -value; | ||
562 | } | ||
563 | if ( value ) { | ||
564 | while ( value > 0 ) { | ||
565 | *bufp++ = ntoa_table[value % radix]; | ||
566 | value /= radix; | ||
567 | } | ||
568 | } else { | ||
569 | *bufp++ = '0'; | ||
570 | } | ||
571 | *bufp = '\0'; | ||
572 | |||
573 | /* The numbers went into the string backwards. :) */ | ||
574 | if ( *string == '-' ) { | ||
575 | SDL_strrev(string+1); | ||
576 | } else { | ||
577 | SDL_strrev(string); | ||
578 | } | ||
579 | |||
580 | return string; | ||
581 | } | ||
582 | #endif | ||
583 | |||
584 | #ifndef HAVE__UI64TOA | ||
585 | char *SDL_ulltoa(Uint64 value, char *string, int radix) | ||
586 | { | ||
587 | char *bufp = string; | ||
588 | |||
589 | if ( value ) { | ||
590 | while ( value > 0 ) { | ||
591 | *bufp++ = ntoa_table[value % radix]; | ||
592 | value /= radix; | ||
593 | } | ||
594 | } else { | ||
595 | *bufp++ = '0'; | ||
596 | } | ||
597 | *bufp = '\0'; | ||
598 | |||
599 | /* The numbers went into the string backwards. :) */ | ||
600 | SDL_strrev(string); | ||
601 | |||
602 | return string; | ||
603 | } | ||
604 | #endif | ||
605 | |||
606 | #ifndef HAVE_STRTOLL | ||
607 | Sint64 SDL_strtoll(const char *string, char **endp, int base) | ||
608 | { | ||
609 | size_t len; | ||
610 | Sint64 value; | ||
611 | |||
612 | if ( !base ) { | ||
613 | if ( (SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0) ) { | ||
614 | base = 16; | ||
615 | } else { | ||
616 | base = 10; | ||
617 | } | ||
618 | } | ||
619 | |||
620 | len = SDL_ScanLongLong(string, base, &value); | ||
621 | if ( endp ) { | ||
622 | *endp = (char *)string + len; | ||
623 | } | ||
624 | return value; | ||
625 | } | ||
626 | #endif | ||
627 | |||
628 | #ifndef HAVE_STRTOULL | ||
629 | Uint64 SDL_strtoull(const char *string, char **endp, int base) | ||
630 | { | ||
631 | size_t len; | ||
632 | Uint64 value; | ||
633 | |||
634 | if ( !base ) { | ||
635 | if ( (SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0) ) { | ||
636 | base = 16; | ||
637 | } else { | ||
638 | base = 10; | ||
639 | } | ||
640 | } | ||
641 | |||
642 | len = SDL_ScanUnsignedLongLong(string, base, &value); | ||
643 | if ( endp ) { | ||
644 | *endp = (char *)string + len; | ||
645 | } | ||
646 | return value; | ||
647 | } | ||
648 | #endif | ||
649 | |||
650 | #endif /* SDL_HAS_64BIT_TYPE */ | ||
651 | |||
652 | #ifndef HAVE_STRTOD | ||
653 | double SDL_strtod(const char *string, char **endp) | ||
654 | { | ||
655 | size_t len; | ||
656 | double value; | ||
657 | |||
658 | len = SDL_ScanFloat(string, &value); | ||
659 | if ( endp ) { | ||
660 | *endp = (char *)string + len; | ||
661 | } | ||
662 | return value; | ||
663 | } | ||
664 | #endif | ||
665 | |||
666 | #ifndef HAVE_STRCMP | ||
667 | int SDL_strcmp(const char *str1, const char *str2) | ||
668 | { | ||
669 | while (*str1 && *str2) { | ||
670 | if ( *str1 != *str2 ) | ||
671 | break; | ||
672 | ++str1; | ||
673 | ++str2; | ||
674 | } | ||
675 | return (int)((unsigned char)*str1 - (unsigned char)*str2); | ||
676 | } | ||
677 | #endif | ||
678 | |||
679 | #ifndef HAVE_STRNCMP | ||
680 | int SDL_strncmp(const char *str1, const char *str2, size_t maxlen) | ||
681 | { | ||
682 | while ( *str1 && *str2 && maxlen ) { | ||
683 | if ( *str1 != *str2 ) | ||
684 | break; | ||
685 | ++str1; | ||
686 | ++str2; | ||
687 | --maxlen; | ||
688 | } | ||
689 | if ( ! maxlen ) { | ||
690 | return 0; | ||
691 | } | ||
692 | return (int)((unsigned char)*str1 - (unsigned char)*str2); | ||
693 | } | ||
694 | #endif | ||
695 | |||
696 | #if !defined(HAVE_STRCASECMP) && !defined(HAVE__STRICMP) | ||
697 | int SDL_strcasecmp(const char *str1, const char *str2) | ||
698 | { | ||
699 | char a = 0; | ||
700 | char b = 0; | ||
701 | while ( *str1 && *str2 ) { | ||
702 | a = SDL_tolower((unsigned char) *str1); | ||
703 | b = SDL_tolower((unsigned char) *str2); | ||
704 | if ( a != b ) | ||
705 | break; | ||
706 | ++str1; | ||
707 | ++str2; | ||
708 | } | ||
709 | return (int)((unsigned char)a - (unsigned char)b); | ||
710 | } | ||
711 | #endif | ||
712 | |||
713 | #if !defined(HAVE_STRNCASECMP) && !defined(HAVE__STRNICMP) | ||
714 | int SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen) | ||
715 | { | ||
716 | char a = 0; | ||
717 | char b = 0; | ||
718 | while ( *str1 && *str2 && maxlen ) { | ||
719 | a = SDL_tolower((unsigned char) *str1); | ||
720 | b = SDL_tolower((unsigned char) *str2); | ||
721 | if ( a != b ) | ||
722 | break; | ||
723 | ++str1; | ||
724 | ++str2; | ||
725 | --maxlen; | ||
726 | } | ||
727 | return (int)((unsigned char)a - (unsigned char)b); | ||
728 | } | ||
729 | #endif | ||
730 | |||
731 | #ifndef HAVE_SSCANF | ||
732 | int SDL_sscanf(const char *text, const char *fmt, ...) | ||
733 | { | ||
734 | va_list ap; | ||
735 | int retval = 0; | ||
736 | |||
737 | va_start(ap, fmt); | ||
738 | while ( *fmt ) { | ||
739 | if ( *fmt == ' ' ) { | ||
740 | while ( SDL_isspace((unsigned char) *text) ) { | ||
741 | ++text; | ||
742 | } | ||
743 | ++fmt; | ||
744 | continue; | ||
745 | } | ||
746 | if ( *fmt == '%' ) { | ||
747 | SDL_bool done = SDL_FALSE; | ||
748 | long count = 0; | ||
749 | int radix = 10; | ||
750 | enum { | ||
751 | DO_SHORT, | ||
752 | DO_INT, | ||
753 | DO_LONG, | ||
754 | DO_LONGLONG | ||
755 | } inttype = DO_INT; | ||
756 | SDL_bool suppress = SDL_FALSE; | ||
757 | |||
758 | ++fmt; | ||
759 | if ( *fmt == '%' ) { | ||
760 | if ( *text == '%' ) { | ||
761 | ++text; | ||
762 | ++fmt; | ||
763 | continue; | ||
764 | } | ||
765 | break; | ||
766 | } | ||
767 | if ( *fmt == '*' ) { | ||
768 | suppress = SDL_TRUE; | ||
769 | ++fmt; | ||
770 | } | ||
771 | fmt += SDL_ScanLong(fmt, 10, &count); | ||
772 | |||
773 | if ( *fmt == 'c' ) { | ||
774 | if ( ! count ) { | ||
775 | count = 1; | ||
776 | } | ||
777 | if ( suppress ) { | ||
778 | while ( count-- ) { | ||
779 | ++text; | ||
780 | } | ||
781 | } else { | ||
782 | char *valuep = va_arg(ap, char*); | ||
783 | while ( count-- ) { | ||
784 | *valuep++ = *text++; | ||
785 | } | ||
786 | ++retval; | ||
787 | } | ||
788 | continue; | ||
789 | } | ||
790 | |||
791 | while ( SDL_isspace((unsigned char) *text) ) { | ||
792 | ++text; | ||
793 | } | ||
794 | |||
795 | /* FIXME: implement more of the format specifiers */ | ||
796 | while (!done) { | ||
797 | switch(*fmt) { | ||
798 | case '*': | ||
799 | suppress = SDL_TRUE; | ||
800 | break; | ||
801 | case 'h': | ||
802 | if ( inttype > DO_SHORT ) { | ||
803 | ++inttype; | ||
804 | } | ||
805 | break; | ||
806 | case 'l': | ||
807 | if ( inttype < DO_LONGLONG ) { | ||
808 | ++inttype; | ||
809 | } | ||
810 | break; | ||
811 | case 'I': | ||
812 | if ( SDL_strncmp(fmt, "I64", 3) == 0 ) { | ||
813 | fmt += 2; | ||
814 | inttype = DO_LONGLONG; | ||
815 | } | ||
816 | break; | ||
817 | case 'i': | ||
818 | { | ||
819 | int index = 0; | ||
820 | if ( text[index] == '-' ) { | ||
821 | ++index; | ||
822 | } | ||
823 | if ( text[index] == '0' ) { | ||
824 | if ( SDL_tolower((unsigned char) text[index+1]) == 'x' ) { | ||
825 | radix = 16; | ||
826 | } else { | ||
827 | radix = 8; | ||
828 | } | ||
829 | } | ||
830 | } | ||
831 | /* Fall through to %d handling */ | ||
832 | case 'd': | ||
833 | #ifdef SDL_HAS_64BIT_TYPE | ||
834 | if ( inttype == DO_LONGLONG ) { | ||
835 | Sint64 value; | ||
836 | text += SDL_ScanLongLong(text, radix, &value); | ||
837 | if ( ! suppress ) { | ||
838 | Sint64 *valuep = va_arg(ap, Sint64*); | ||
839 | *valuep = value; | ||
840 | ++retval; | ||
841 | } | ||
842 | } | ||
843 | else | ||
844 | #endif /* SDL_HAS_64BIT_TYPE */ | ||
845 | { | ||
846 | long value; | ||
847 | text += SDL_ScanLong(text, radix, &value); | ||
848 | if ( ! suppress ) { | ||
849 | switch (inttype) { | ||
850 | case DO_SHORT: | ||
851 | { short* valuep = va_arg(ap, short*); | ||
852 | *valuep = (short)value; | ||
853 | } | ||
854 | break; | ||
855 | case DO_INT: | ||
856 | { int* valuep = va_arg(ap, int*); | ||
857 | *valuep = (int)value; | ||
858 | } | ||
859 | break; | ||
860 | case DO_LONG: | ||
861 | { long* valuep = va_arg(ap, long*); | ||
862 | *valuep = value; | ||
863 | } | ||
864 | break; | ||
865 | case DO_LONGLONG: | ||
866 | /* Handled above */ | ||
867 | break; | ||
868 | } | ||
869 | ++retval; | ||
870 | } | ||
871 | } | ||
872 | done = SDL_TRUE; | ||
873 | break; | ||
874 | case 'o': | ||
875 | if ( radix == 10 ) { | ||
876 | radix = 8; | ||
877 | } | ||
878 | /* Fall through to unsigned handling */ | ||
879 | case 'x': | ||
880 | case 'X': | ||
881 | if ( radix == 10 ) { | ||
882 | radix = 16; | ||
883 | } | ||
884 | /* Fall through to unsigned handling */ | ||
885 | case 'u': | ||
886 | #ifdef SDL_HAS_64BIT_TYPE | ||
887 | if ( inttype == DO_LONGLONG ) { | ||
888 | Uint64 value; | ||
889 | text += SDL_ScanUnsignedLongLong(text, radix, &value); | ||
890 | if ( ! suppress ) { | ||
891 | Uint64 *valuep = va_arg(ap, Uint64*); | ||
892 | *valuep = value; | ||
893 | ++retval; | ||
894 | } | ||
895 | } | ||
896 | else | ||
897 | #endif /* SDL_HAS_64BIT_TYPE */ | ||
898 | { | ||
899 | unsigned long value; | ||
900 | text += SDL_ScanUnsignedLong(text, radix, &value); | ||
901 | if ( ! suppress ) { | ||
902 | switch (inttype) { | ||
903 | case DO_SHORT: | ||
904 | { short* valuep = va_arg(ap, short*); | ||
905 | *valuep = (short)value; | ||
906 | } | ||
907 | break; | ||
908 | case DO_INT: | ||
909 | { int* valuep = va_arg(ap, int*); | ||
910 | *valuep = (int)value; | ||
911 | } | ||
912 | break; | ||
913 | case DO_LONG: | ||
914 | { long* valuep = va_arg(ap, long*); | ||
915 | *valuep = value; | ||
916 | } | ||
917 | break; | ||
918 | case DO_LONGLONG: | ||
919 | /* Handled above */ | ||
920 | break; | ||
921 | } | ||
922 | ++retval; | ||
923 | } | ||
924 | } | ||
925 | done = SDL_TRUE; | ||
926 | break; | ||
927 | case 'p': | ||
928 | { | ||
929 | uintptr_t value; | ||
930 | text += SDL_ScanUintPtrT(text, 16, &value); | ||
931 | if ( ! suppress ) { | ||
932 | void** valuep = va_arg(ap, void**); | ||
933 | *valuep = (void*)value; | ||
934 | ++retval; | ||
935 | } | ||
936 | } | ||
937 | done = SDL_TRUE; | ||
938 | break; | ||
939 | case 'f': | ||
940 | { | ||
941 | double value; | ||
942 | text += SDL_ScanFloat(text, &value); | ||
943 | if ( ! suppress ) { | ||
944 | float* valuep = va_arg(ap, float*); | ||
945 | *valuep = (float)value; | ||
946 | ++retval; | ||
947 | } | ||
948 | } | ||
949 | done = SDL_TRUE; | ||
950 | break; | ||
951 | case 's': | ||
952 | if ( suppress ) { | ||
953 | while ( !SDL_isspace((unsigned char) *text) ) { | ||
954 | ++text; | ||
955 | if ( count ) { | ||
956 | if ( --count == 0 ) { | ||
957 | break; | ||
958 | } | ||
959 | } | ||
960 | } | ||
961 | } else { | ||
962 | char *valuep = va_arg(ap, char*); | ||
963 | while ( !SDL_isspace((unsigned char) *text) ) { | ||
964 | *valuep++ = *text++; | ||
965 | if ( count ) { | ||
966 | if ( --count == 0 ) { | ||
967 | break; | ||
968 | } | ||
969 | } | ||
970 | } | ||
971 | *valuep = '\0'; | ||
972 | ++retval; | ||
973 | } | ||
974 | done = SDL_TRUE; | ||
975 | break; | ||
976 | default: | ||
977 | done = SDL_TRUE; | ||
978 | break; | ||
979 | } | ||
980 | ++fmt; | ||
981 | } | ||
982 | continue; | ||
983 | } | ||
984 | if ( *text == *fmt ) { | ||
985 | ++text; | ||
986 | ++fmt; | ||
987 | continue; | ||
988 | } | ||
989 | /* Text didn't match format specifier */ | ||
990 | break; | ||
991 | } | ||
992 | va_end(ap); | ||
993 | |||
994 | return retval; | ||
995 | } | ||
996 | #endif | ||
997 | |||
998 | #ifndef HAVE_SNPRINTF | ||
999 | int SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...) | ||
1000 | { | ||
1001 | va_list ap; | ||
1002 | int retval; | ||
1003 | |||
1004 | va_start(ap, fmt); | ||
1005 | retval = SDL_vsnprintf(text, maxlen, fmt, ap); | ||
1006 | va_end(ap); | ||
1007 | |||
1008 | return retval; | ||
1009 | } | ||
1010 | #endif | ||
1011 | |||
1012 | #ifndef HAVE_VSNPRINTF | ||
1013 | static size_t SDL_PrintLong(char *text, long value, int radix, size_t maxlen) | ||
1014 | { | ||
1015 | char num[130]; | ||
1016 | size_t size; | ||
1017 | |||
1018 | SDL_ltoa(value, num, radix); | ||
1019 | size = SDL_strlen(num); | ||
1020 | if ( size >= maxlen ) { | ||
1021 | size = maxlen-1; | ||
1022 | } | ||
1023 | SDL_strlcpy(text, num, size+1); | ||
1024 | |||
1025 | return size; | ||
1026 | } | ||
1027 | static size_t SDL_PrintUnsignedLong(char *text, unsigned long value, int radix, size_t maxlen) | ||
1028 | { | ||
1029 | char num[130]; | ||
1030 | size_t size; | ||
1031 | |||
1032 | SDL_ultoa(value, num, radix); | ||
1033 | size = SDL_strlen(num); | ||
1034 | if ( size >= maxlen ) { | ||
1035 | size = maxlen-1; | ||
1036 | } | ||
1037 | SDL_strlcpy(text, num, size+1); | ||
1038 | |||
1039 | return size; | ||
1040 | } | ||
1041 | #ifdef SDL_HAS_64BIT_TYPE | ||
1042 | static size_t SDL_PrintLongLong(char *text, Sint64 value, int radix, size_t maxlen) | ||
1043 | { | ||
1044 | char num[130]; | ||
1045 | size_t size; | ||
1046 | |||
1047 | SDL_lltoa(value, num, radix); | ||
1048 | size = SDL_strlen(num); | ||
1049 | if ( size >= maxlen ) { | ||
1050 | size = maxlen-1; | ||
1051 | } | ||
1052 | SDL_strlcpy(text, num, size+1); | ||
1053 | |||
1054 | return size; | ||
1055 | } | ||
1056 | static size_t SDL_PrintUnsignedLongLong(char *text, Uint64 value, int radix, size_t maxlen) | ||
1057 | { | ||
1058 | char num[130]; | ||
1059 | size_t size; | ||
1060 | |||
1061 | SDL_ulltoa(value, num, radix); | ||
1062 | size = SDL_strlen(num); | ||
1063 | if ( size >= maxlen ) { | ||
1064 | size = maxlen-1; | ||
1065 | } | ||
1066 | SDL_strlcpy(text, num, size+1); | ||
1067 | |||
1068 | return size; | ||
1069 | } | ||
1070 | #endif /* SDL_HAS_64BIT_TYPE */ | ||
1071 | static size_t SDL_PrintFloat(char *text, double arg, size_t maxlen) | ||
1072 | { | ||
1073 | char *textstart = text; | ||
1074 | if ( arg ) { | ||
1075 | /* This isn't especially accurate, but hey, it's easy. :) */ | ||
1076 | const double precision = 0.00000001; | ||
1077 | size_t len; | ||
1078 | unsigned long value; | ||
1079 | |||
1080 | if ( arg < 0 ) { | ||
1081 | *text++ = '-'; | ||
1082 | --maxlen; | ||
1083 | arg = -arg; | ||
1084 | } | ||
1085 | value = (unsigned long)arg; | ||
1086 | len = SDL_PrintUnsignedLong(text, value, 10, maxlen); | ||
1087 | text += len; | ||
1088 | maxlen -= len; | ||
1089 | arg -= value; | ||
1090 | if ( arg > precision && maxlen ) { | ||
1091 | int mult = 10; | ||
1092 | *text++ = '.'; | ||
1093 | while ( (arg > precision) && maxlen ) { | ||
1094 | value = (unsigned long)(arg * mult); | ||
1095 | len = SDL_PrintUnsignedLong(text, value, 10, maxlen); | ||
1096 | text += len; | ||
1097 | maxlen -= len; | ||
1098 | arg -= (double)value / mult; | ||
1099 | mult *= 10; | ||
1100 | } | ||
1101 | } | ||
1102 | } else { | ||
1103 | *text++ = '0'; | ||
1104 | } | ||
1105 | return (text - textstart); | ||
1106 | } | ||
1107 | static size_t SDL_PrintString(char *text, const char *string, size_t maxlen) | ||
1108 | { | ||
1109 | char *textstart = text; | ||
1110 | while ( *string && maxlen-- ) { | ||
1111 | *text++ = *string++; | ||
1112 | } | ||
1113 | return (text - textstart); | ||
1114 | } | ||
1115 | int SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap) | ||
1116 | { | ||
1117 | char *textstart = text; | ||
1118 | if ( maxlen <= 0 ) { | ||
1119 | return 0; | ||
1120 | } | ||
1121 | --maxlen; /* For the trailing '\0' */ | ||
1122 | while ( *fmt && maxlen ) { | ||
1123 | if ( *fmt == '%' ) { | ||
1124 | SDL_bool done = SDL_FALSE; | ||
1125 | size_t len = 0; | ||
1126 | SDL_bool do_lowercase = SDL_FALSE; | ||
1127 | int radix = 10; | ||
1128 | enum { | ||
1129 | DO_INT, | ||
1130 | DO_LONG, | ||
1131 | DO_LONGLONG | ||
1132 | } inttype = DO_INT; | ||
1133 | |||
1134 | ++fmt; | ||
1135 | /* FIXME: implement more of the format specifiers */ | ||
1136 | while ( *fmt == '.' || (*fmt >= '0' && *fmt <= '9') ) { | ||
1137 | ++fmt; | ||
1138 | } | ||
1139 | while (!done) { | ||
1140 | switch(*fmt) { | ||
1141 | case '%': | ||
1142 | *text = '%'; | ||
1143 | len = 1; | ||
1144 | done = SDL_TRUE; | ||
1145 | break; | ||
1146 | case 'c': | ||
1147 | /* char is promoted to int when passed through (...) */ | ||
1148 | *text = (char)va_arg(ap, int); | ||
1149 | len = 1; | ||
1150 | done = SDL_TRUE; | ||
1151 | break; | ||
1152 | case 'h': | ||
1153 | /* short is promoted to int when passed through (...) */ | ||
1154 | break; | ||
1155 | case 'l': | ||
1156 | if ( inttype < DO_LONGLONG ) { | ||
1157 | ++inttype; | ||
1158 | } | ||
1159 | break; | ||
1160 | case 'I': | ||
1161 | if ( SDL_strncmp(fmt, "I64", 3) == 0 ) { | ||
1162 | fmt += 2; | ||
1163 | inttype = DO_LONGLONG; | ||
1164 | } | ||
1165 | break; | ||
1166 | case 'i': | ||
1167 | case 'd': | ||
1168 | switch (inttype) { | ||
1169 | case DO_INT: | ||
1170 | len = SDL_PrintLong(text, (long)va_arg(ap, int), radix, maxlen); | ||
1171 | break; | ||
1172 | case DO_LONG: | ||
1173 | len = SDL_PrintLong(text, va_arg(ap, long), radix, maxlen); | ||
1174 | break; | ||
1175 | case DO_LONGLONG: | ||
1176 | #ifdef SDL_HAS_64BIT_TYPE | ||
1177 | len = SDL_PrintLongLong(text, va_arg(ap, Sint64), radix, maxlen); | ||
1178 | #else | ||
1179 | len = SDL_PrintLong(text, va_arg(ap, long), radix, maxlen); | ||
1180 | #endif | ||
1181 | break; | ||
1182 | } | ||
1183 | done = SDL_TRUE; | ||
1184 | break; | ||
1185 | case 'p': | ||
1186 | case 'x': | ||
1187 | do_lowercase = SDL_TRUE; | ||
1188 | /* Fall through to 'X' handling */ | ||
1189 | case 'X': | ||
1190 | if ( radix == 10 ) { | ||
1191 | radix = 16; | ||
1192 | } | ||
1193 | if ( *fmt == 'p' ) { | ||
1194 | inttype = DO_LONG; | ||
1195 | } | ||
1196 | /* Fall through to unsigned handling */ | ||
1197 | case 'o': | ||
1198 | if ( radix == 10 ) { | ||
1199 | radix = 8; | ||
1200 | } | ||
1201 | /* Fall through to unsigned handling */ | ||
1202 | case 'u': | ||
1203 | switch (inttype) { | ||
1204 | case DO_INT: | ||
1205 | len = SDL_PrintUnsignedLong(text, (unsigned long)va_arg(ap, unsigned int), radix, maxlen); | ||
1206 | break; | ||
1207 | case DO_LONG: | ||
1208 | len = SDL_PrintUnsignedLong(text, va_arg(ap, unsigned long), radix, maxlen); | ||
1209 | break; | ||
1210 | case DO_LONGLONG: | ||
1211 | #ifdef SDL_HAS_64BIT_TYPE | ||
1212 | len = SDL_PrintUnsignedLongLong(text, va_arg(ap, Uint64), radix, maxlen); | ||
1213 | #else | ||
1214 | len = SDL_PrintUnsignedLong(text, va_arg(ap, unsigned long), radix, maxlen); | ||
1215 | #endif | ||
1216 | break; | ||
1217 | } | ||
1218 | if ( do_lowercase ) { | ||
1219 | SDL_strlwr(text); | ||
1220 | } | ||
1221 | done = SDL_TRUE; | ||
1222 | break; | ||
1223 | case 'f': | ||
1224 | len = SDL_PrintFloat(text, va_arg(ap, double), maxlen); | ||
1225 | done = SDL_TRUE; | ||
1226 | break; | ||
1227 | case 's': | ||
1228 | len = SDL_PrintString(text, va_arg(ap, char*), maxlen); | ||
1229 | done = SDL_TRUE; | ||
1230 | break; | ||
1231 | default: | ||
1232 | done = SDL_TRUE; | ||
1233 | break; | ||
1234 | } | ||
1235 | ++fmt; | ||
1236 | } | ||
1237 | text += len; | ||
1238 | maxlen -= len; | ||
1239 | } else { | ||
1240 | *text++ = *fmt++; | ||
1241 | --maxlen; | ||
1242 | } | ||
1243 | } | ||
1244 | *text = '\0'; | ||
1245 | |||
1246 | return (text - textstart); | ||
1247 | } | ||
1248 | #endif | ||