Mercurial > sdl-ios-xcode
comparison src/stdlib/SDL_string.c @ 1330:450721ad5436
It's now possible to build SDL without any C runtime at all on Windows,
using Visual C++ 2005
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 06 Feb 2006 08:28:51 +0000 |
parents | |
children | 3692456e7b0f |
comparison
equal
deleted
inserted
replaced
1329:bc67bbf87818 | 1330:450721ad5436 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2006 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 | |
23 | |
24 /* This file contains portable string manipulation functions for SDL */ | |
25 | |
26 #include "SDL_types.h" | |
27 #include "SDL_ctype.h" | |
28 #include "SDL_string.h" | |
29 | |
30 | |
31 #define isupperhex(X) (((X) >= 'A') && ((X) <= 'F')) | |
32 #define islowerhex(X) (((X) >= 'a') && ((X) <= 'f')) | |
33 | |
34 #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL) | |
35 static size_t SDL_ScanLong(const char *text, int radix, long *valuep) | |
36 { | |
37 const char *textstart = text; | |
38 long value = 0; | |
39 SDL_bool negative = SDL_FALSE; | |
40 | |
41 if ( *text == '-' ) { | |
42 negative = SDL_TRUE; | |
43 ++text; | |
44 } | |
45 if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { | |
46 text += 2; | |
47 } | |
48 for ( ; ; ) { | |
49 int v; | |
50 if ( isdigit(*text) ) { | |
51 v = *text - '0'; | |
52 } else if ( radix == 16 && isupperhex(*text) ) { | |
53 v = 10 + (*text - 'A'); | |
54 } else if ( radix == 16 && islowerhex(*text) ) { | |
55 v = 10 + (*text - 'a'); | |
56 } else { | |
57 break; | |
58 } | |
59 value *= radix; | |
60 value += v; | |
61 ++text; | |
62 } | |
63 if ( valuep ) { | |
64 if ( negative && value ) { | |
65 *valuep = -value; | |
66 } else { | |
67 *valuep = value; | |
68 } | |
69 } | |
70 return (text - textstart); | |
71 } | |
72 #endif | |
73 | |
74 #ifndef HAVE_SSCANF | |
75 static size_t SDL_ScanUnsignedLong(const char *text, int radix, unsigned long *valuep) | |
76 { | |
77 const char *textstart = text; | |
78 unsigned long value = 0; | |
79 | |
80 if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { | |
81 text += 2; | |
82 } | |
83 for ( ; ; ) { | |
84 int v; | |
85 if ( isdigit(*text) ) { | |
86 v = *text - '0'; | |
87 } else if ( radix == 16 && isupperhex(*text) ) { | |
88 v = 10 + (*text - 'A'); | |
89 } else if ( radix == 16 && islowerhex(*text) ) { | |
90 v = 10 + (*text - 'a'); | |
91 } else { | |
92 break; | |
93 } | |
94 value *= radix; | |
95 value += v; | |
96 ++text; | |
97 } | |
98 if ( valuep ) { | |
99 *valuep = value; | |
100 } | |
101 return (text - textstart); | |
102 } | |
103 #endif | |
104 | |
105 #ifdef SDL_HAS_64BIT_TYPE | |
106 #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOLL) | |
107 static size_t SDL_ScanLongLong(const char *text, int radix, Sint64 *valuep) | |
108 { | |
109 const char *textstart = text; | |
110 Sint64 value = 0; | |
111 SDL_bool negative = SDL_FALSE; | |
112 | |
113 if ( *text == '-' ) { | |
114 negative = SDL_TRUE; | |
115 ++text; | |
116 } | |
117 if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { | |
118 text += 2; | |
119 } | |
120 for ( ; ; ) { | |
121 int v; | |
122 if ( isdigit(*text) ) { | |
123 v = *text - '0'; | |
124 } else if ( radix == 16 && isupperhex(*text) ) { | |
125 v = 10 + (*text - 'A'); | |
126 } else if ( radix == 16 && islowerhex(*text) ) { | |
127 v = 10 + (*text - 'a'); | |
128 } else { | |
129 break; | |
130 } | |
131 value *= radix; | |
132 value += v; | |
133 ++text; | |
134 } | |
135 if ( valuep ) { | |
136 if ( negative && value ) { | |
137 *valuep = -value; | |
138 } else { | |
139 *valuep = value; | |
140 } | |
141 } | |
142 return (text - textstart); | |
143 } | |
144 #endif | |
145 | |
146 #ifndef HAVE_SSCANF | |
147 static size_t SDL_ScanUnsignedLongLong(const char *text, int radix, Uint64 *valuep) | |
148 { | |
149 const char *textstart = text; | |
150 Uint64 value = 0; | |
151 | |
152 if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { | |
153 text += 2; | |
154 } | |
155 for ( ; ; ) { | |
156 int v; | |
157 if ( isdigit(*text) ) { | |
158 v = *text - '0'; | |
159 } else if ( radix == 16 && isupperhex(*text) ) { | |
160 v = 10 + (*text - 'A'); | |
161 } else if ( radix == 16 && islowerhex(*text) ) { | |
162 v = 10 + (*text - 'a'); | |
163 } else { | |
164 break; | |
165 } | |
166 value *= radix; | |
167 value += v; | |
168 ++text; | |
169 } | |
170 if ( valuep ) { | |
171 *valuep = value; | |
172 } | |
173 return (text - textstart); | |
174 } | |
175 #endif | |
176 #endif /* SDL_HAS_64BIT_TYPE */ | |
177 | |
178 #ifndef HAVE_SSCANF | |
179 static size_t SDL_ScanFloat(const char *text, double *valuep) | |
180 { | |
181 const char *textstart = text; | |
182 unsigned long lvalue = 0; | |
183 double value = 0.0; | |
184 SDL_bool negative = SDL_FALSE; | |
185 | |
186 if ( *text == '-' ) { | |
187 negative = SDL_TRUE; | |
188 ++text; | |
189 } | |
190 text += SDL_ScanUnsignedLong(text, 10, &lvalue); | |
191 value += lvalue; | |
192 if ( *text == '.' ) { | |
193 int mult = 10; | |
194 ++text; | |
195 while ( isdigit(*text) ) { | |
196 lvalue = *text - '0'; | |
197 value += (double)lvalue / mult; | |
198 mult *= 10; | |
199 ++text; | |
200 } | |
201 } | |
202 if ( valuep ) { | |
203 if ( negative && value ) { | |
204 *valuep = -value; | |
205 } else { | |
206 *valuep = value; | |
207 } | |
208 } | |
209 return (text - textstart); | |
210 } | |
211 #endif | |
212 | |
213 #ifndef SDL_memset | |
214 void *SDL_memset(void *dst, int c, size_t len) | |
215 { | |
216 size_t left = (len % 4); | |
217 if ( len >= 4 ) { | |
218 Uint32 value = 0; | |
219 Uint32 *dstp = (Uint32 *)dst; | |
220 int i; | |
221 for (i = 0; i < 4; ++i) { | |
222 value <<= 8; | |
223 value |= c; | |
224 } | |
225 len /= 4; | |
226 while ( len-- ) { | |
227 *dstp++ = value; | |
228 } | |
229 } | |
230 if ( left > 0 ) { | |
231 Uint8 value = (Uint8)c; | |
232 Uint8 *dstp = (Uint8 *)dst; | |
233 switch(left) { | |
234 case 3: | |
235 *dstp++ = value; | |
236 case 2: | |
237 *dstp++ = value; | |
238 case 1: | |
239 *dstp++ = value; | |
240 } | |
241 } | |
242 return dst; | |
243 } | |
244 #endif | |
245 | |
246 #ifndef SDL_memcpy | |
247 void *SDL_memcpy(void *dst, const void *src, size_t len) | |
248 { | |
249 char *srcp = (char *)src; | |
250 char *dstp = (char *)dst; | |
251 while ( len-- ) { | |
252 *dstp++ = *srcp++; | |
253 } | |
254 return dst; | |
255 } | |
256 #endif | |
257 | |
258 #ifndef SDL_revcpy | |
259 void *SDL_revcpy(void *dst, const void *src, size_t len) | |
260 { | |
261 char *srcp = (char *)src; | |
262 char *dstp = (char *)dst; | |
263 srcp += len; | |
264 dstp += len; | |
265 while ( len-- ) { | |
266 *dstp-- = *srcp--; | |
267 } | |
268 return dst; | |
269 } | |
270 #endif | |
271 | |
272 #ifndef SDL_memcmp | |
273 int SDL_memcmp(const void *s1, const void *s2, size_t len) | |
274 { | |
275 char *s1p = (char *)s1; | |
276 char *s2p = (char *)s2; | |
277 while ( len-- ) { | |
278 if ( *s1p != *s2p ) { | |
279 return (*s1p - *s2p); | |
280 } | |
281 ++s1p; | |
282 ++s2p; | |
283 } | |
284 return 0; | |
285 } | |
286 #endif | |
287 | |
288 #ifndef HAVE_STRLEN | |
289 size_t SDL_strlen(const char *string) | |
290 { | |
291 size_t len = 0; | |
292 while ( *string++ ) { | |
293 ++len; | |
294 } | |
295 return len; | |
296 } | |
297 #endif | |
298 | |
299 #ifndef HAVE_STRCPY | |
300 char *SDL_strcpy(char *dst, const char *src) | |
301 { | |
302 char *dstp = dst; | |
303 while ( *src ) { | |
304 *dstp++ = *src++; | |
305 } | |
306 *dstp = '\0'; | |
307 | |
308 return dst; | |
309 } | |
310 #endif | |
311 | |
312 #ifndef HAVE_STRNCPY | |
313 char *SDL_strncpy(char *dst, const char *src, size_t maxlen) | |
314 { | |
315 char *dstp = dst; | |
316 while ( maxlen-- && *src ) { | |
317 *dstp++ = *src++; | |
318 } | |
319 *dstp = '\0'; | |
320 | |
321 return dst; | |
322 } | |
323 #endif | |
324 | |
325 #ifndef HAVE__STRREV | |
326 char *SDL_strrev(char *string) | |
327 { | |
328 size_t len = SDL_strlen(string); | |
329 char *a = &string[0]; | |
330 char *b = &string[len-1]; | |
331 len /= 2; | |
332 while ( len-- ) { | |
333 char c = *a; | |
334 *a++ = *b; | |
335 *b-- = c; | |
336 } | |
337 return string; | |
338 } | |
339 #endif | |
340 | |
341 #ifndef HAVE__STRUPR | |
342 char *SDL_strupr(char *string) | |
343 { | |
344 char *bufp = string; | |
345 while ( *bufp ) { | |
346 *bufp++ = toupper(*bufp); | |
347 } | |
348 return string; | |
349 } | |
350 #endif | |
351 | |
352 #ifndef HAVE__STRLWR | |
353 char *SDL_strlwr(char *string) | |
354 { | |
355 char *bufp = string; | |
356 while ( *bufp ) { | |
357 *bufp++ = tolower(*bufp); | |
358 } | |
359 return string; | |
360 } | |
361 #endif | |
362 | |
363 #ifndef HAVE_STRCHR | |
364 char *SDL_strchr(const char *string, int c) | |
365 { | |
366 while ( *string ) { | |
367 if ( *string == c ) { | |
368 return (char *)string; | |
369 } | |
370 } | |
371 return NULL; | |
372 } | |
373 #endif | |
374 | |
375 #ifndef HAVE_STRRCHR | |
376 char *SDL_strrchr(const char *string, int c) | |
377 { | |
378 const char *bufp = string + strlen(string) - 1; | |
379 while ( bufp >= string ) { | |
380 if ( *bufp == c ) { | |
381 return (char *)bufp; | |
382 } | |
383 } | |
384 return NULL; | |
385 } | |
386 #endif | |
387 | |
388 #ifndef HAVE_STRSTR | |
389 char *SDL_strstr(const char *haystack, const char *needle) | |
390 { | |
391 size_t length = strlen(needle); | |
392 while ( *haystack ) { | |
393 if ( strncmp(haystack, needle, length) == 0 ) { | |
394 return (char *)haystack; | |
395 } | |
396 } | |
397 return NULL; | |
398 } | |
399 #endif | |
400 | |
401 #if !defined(HAVE__LTOA) || !defined(HAVE__I64TOA) || \ | |
402 !defined(HAVE__ULTOA) || !defined(HAVE__UI64TOA) | |
403 static const char ntoa_table[] = { | |
404 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |
405 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', | |
406 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', | |
407 'U', 'V', 'W', 'X', 'Y', 'Z' | |
408 }; | |
409 #endif /* ntoa() conversion table */ | |
410 | |
411 #ifndef HAVE__LTOA | |
412 char *SDL_ltoa(long value, char *string, int radix) | |
413 { | |
414 char *bufp = string; | |
415 | |
416 if ( value < 0 ) { | |
417 *bufp++ = '-'; | |
418 value = -value; | |
419 } | |
420 if ( value ) { | |
421 while ( value > 0 ) { | |
422 *bufp++ = ntoa_table[value % radix]; | |
423 value /= radix; | |
424 } | |
425 } else { | |
426 *bufp++ = '0'; | |
427 } | |
428 *bufp = '\0'; | |
429 | |
430 /* The numbers went into the string backwards. :) */ | |
431 if ( *string == '-' ) { | |
432 _strrev(string+1); | |
433 } else { | |
434 _strrev(string); | |
435 } | |
436 | |
437 return string; | |
438 } | |
439 #endif | |
440 | |
441 #ifndef HAVE__ULTOA | |
442 char *SDL_ultoa(unsigned long value, char *string, int radix) | |
443 { | |
444 char *bufp = string; | |
445 | |
446 if ( value ) { | |
447 while ( value > 0 ) { | |
448 *bufp++ = ntoa_table[value % radix]; | |
449 value /= radix; | |
450 } | |
451 } else { | |
452 *bufp++ = '0'; | |
453 } | |
454 *bufp = '\0'; | |
455 | |
456 /* The numbers went into the string backwards. :) */ | |
457 _strrev(string); | |
458 | |
459 return string; | |
460 } | |
461 #endif | |
462 | |
463 #ifndef HAVE_STRTOL | |
464 long SDL_strtol(const char *string, char **endp, int base) | |
465 { | |
466 size_t len; | |
467 long value; | |
468 | |
469 len = SDL_ScanLong(string, base ? base : 10, &value); | |
470 if ( endp ) { | |
471 *endp = (char *)string + len; | |
472 } | |
473 return value; | |
474 } | |
475 #endif | |
476 | |
477 #ifdef SDL_HAS_64BIT_TYPE | |
478 | |
479 #ifndef HAVE__I64TOA | |
480 char *SDL_lltoa(Sint64 value, char *string, int radix) | |
481 { | |
482 char *bufp = string; | |
483 | |
484 if ( value < 0 ) { | |
485 *bufp++ = '-'; | |
486 value = -value; | |
487 } | |
488 if ( value ) { | |
489 while ( value > 0 ) { | |
490 *bufp++ = ntoa_table[value % radix]; | |
491 value /= radix; | |
492 } | |
493 } else { | |
494 *bufp++ = '0'; | |
495 } | |
496 *bufp = '\0'; | |
497 | |
498 /* The numbers went into the string backwards. :) */ | |
499 if ( *string == '-' ) { | |
500 _strrev(string+1); | |
501 } else { | |
502 _strrev(string); | |
503 } | |
504 | |
505 return string; | |
506 } | |
507 #endif | |
508 | |
509 #ifndef HAVE__UI64TOA | |
510 char *SDL_ulltoa(Uint64 value, char *string, int radix) | |
511 { | |
512 char *bufp = string; | |
513 | |
514 if ( value ) { | |
515 while ( value > 0 ) { | |
516 *bufp++ = ntoa_table[value % radix]; | |
517 value /= radix; | |
518 } | |
519 } else { | |
520 *bufp++ = '0'; | |
521 } | |
522 *bufp = '\0'; | |
523 | |
524 /* The numbers went into the string backwards. :) */ | |
525 _strrev(string); | |
526 | |
527 return string; | |
528 } | |
529 #endif | |
530 | |
531 #ifndef HAVE_STRTOLL | |
532 Sint64 SDL_strtoll(const char *string, char **endp, int base) | |
533 { | |
534 size_t len; | |
535 Sint64 value; | |
536 | |
537 len = SDL_ScanLongLong(string, base ? base : 10, &value); | |
538 if ( endp ) { | |
539 *endp = (char *)string + len; | |
540 } | |
541 return value; | |
542 } | |
543 #endif | |
544 | |
545 #endif /* SDL_HAS_64BIT_TYPE */ | |
546 | |
547 #ifndef HAVE_STRCMP | |
548 int SDL_strcmp(const char *str1, const char *str2) | |
549 { | |
550 while (*str1 && *str2) { | |
551 if ( *str1 != *str2 ) | |
552 break; | |
553 ++str1; | |
554 ++str2; | |
555 } | |
556 return (int)((unsigned char)*str1 - (unsigned char)*str2); | |
557 } | |
558 #endif | |
559 | |
560 #ifndef HAVE_STRNCMP | |
561 int SDL_strncmp(const char *str1, const char *str2, size_t maxlen) | |
562 { | |
563 while ( *str1 && *str2 && maxlen ) { | |
564 if ( *str1 != *str2 ) | |
565 break; | |
566 ++str1; | |
567 ++str2; | |
568 --maxlen; | |
569 } | |
570 if ( ! maxlen ) { | |
571 return 0; | |
572 } | |
573 return (int)((unsigned char)*str1 - (unsigned char)*str2); | |
574 } | |
575 #endif | |
576 | |
577 #ifndef HAVE_STRCASECMP | |
578 int SDL_strcasecmp(const char *str1, const char *str2) | |
579 { | |
580 char a = 0; | |
581 char b = 0; | |
582 while (*str1 && *str2) { | |
583 a = tolower(*str1); | |
584 b = tolower(*str2); | |
585 if ( a != b ) | |
586 break; | |
587 ++str1; | |
588 ++str2; | |
589 } | |
590 return (int)((unsigned char)a - (unsigned char)b); | |
591 } | |
592 #endif | |
593 | |
594 #ifndef HAVE_SSCANF | |
595 int SDL_sscanf(const char *text, const char *fmt, ...) | |
596 { | |
597 va_list ap; | |
598 int retval = 0; | |
599 | |
600 va_start(ap, fmt); | |
601 while ( *fmt ) { | |
602 if ( *fmt == ' ' ) { | |
603 while ( isspace(*text) ) { | |
604 ++text; | |
605 } | |
606 ++fmt; | |
607 continue; | |
608 } | |
609 if ( *fmt == '%' ) { | |
610 SDL_bool done = SDL_FALSE; | |
611 long count = 0; | |
612 int radix = 10; | |
613 enum { | |
614 DO_SHORT, | |
615 DO_INT, | |
616 DO_LONG, | |
617 DO_LONGLONG | |
618 } inttype = DO_INT; | |
619 SDL_bool suppress = SDL_FALSE; | |
620 | |
621 ++fmt; | |
622 if ( *fmt == '%' ) { | |
623 if ( *text == '%' ) { | |
624 ++text; | |
625 ++fmt; | |
626 continue; | |
627 } | |
628 break; | |
629 } | |
630 if ( *fmt == '*' ) { | |
631 suppress = SDL_TRUE; | |
632 ++fmt; | |
633 } | |
634 fmt += SDL_ScanLong(fmt, 10, &count); | |
635 | |
636 if ( *fmt == 'c' ) { | |
637 if ( ! count ) { | |
638 count = 1; | |
639 } | |
640 if ( suppress ) { | |
641 while ( count-- ) { | |
642 ++text; | |
643 } | |
644 } else { | |
645 char *valuep = va_arg(ap, char*); | |
646 while ( count-- ) { | |
647 *valuep++ = *text++; | |
648 } | |
649 ++retval; | |
650 } | |
651 continue; | |
652 } | |
653 | |
654 while ( isspace(*text) ) { | |
655 ++text; | |
656 } | |
657 | |
658 /* FIXME: implement more of the format specifiers */ | |
659 while (!done) { | |
660 switch(*fmt) { | |
661 case '*': | |
662 suppress = SDL_TRUE; | |
663 break; | |
664 case 'h': | |
665 if ( inttype > DO_SHORT ) { | |
666 ++inttype; | |
667 } | |
668 break; | |
669 case 'l': | |
670 if ( inttype < DO_LONGLONG ) { | |
671 ++inttype; | |
672 } | |
673 break; | |
674 case 'I': | |
675 if ( SDL_strncmp(fmt, "I64", 3) == 0 ) { | |
676 fmt += 2; | |
677 inttype = DO_LONGLONG; | |
678 } | |
679 break; | |
680 case 'i': | |
681 { | |
682 int index = 0; | |
683 if ( text[index] == '-' ) { | |
684 ++index; | |
685 } | |
686 if ( text[index] == '0' ) { | |
687 if ( tolower(text[index+1]) == 'x' ) { | |
688 radix = 16; | |
689 } else { | |
690 radix = 8; | |
691 } | |
692 } | |
693 } | |
694 /* Fall through to %d handling */ | |
695 case 'd': | |
696 #ifdef SDL_HAS_64BIT_TYPE | |
697 if ( inttype == DO_LONGLONG ) { | |
698 Sint64 value; | |
699 text += SDL_ScanLongLong(text, radix, &value); | |
700 if ( ! suppress ) { | |
701 Sint64 *valuep = va_arg(ap, Sint64*); | |
702 *valuep = value; | |
703 ++retval; | |
704 } | |
705 } | |
706 else | |
707 #endif /* SDL_HAS_64BIT_TYPE */ | |
708 { | |
709 long value; | |
710 text += SDL_ScanLong(text, radix, &value); | |
711 if ( ! suppress ) { | |
712 switch (inttype) { | |
713 case DO_SHORT: | |
714 { short* valuep = va_arg(ap, short*); | |
715 *valuep = (short)value; | |
716 } | |
717 break; | |
718 case DO_INT: | |
719 { int* valuep = va_arg(ap, int*); | |
720 *valuep = (int)value; | |
721 } | |
722 break; | |
723 case DO_LONG: | |
724 { long* valuep = va_arg(ap, long*); | |
725 *valuep = value; | |
726 } | |
727 break; | |
728 case DO_LONGLONG: | |
729 /* Handled above */ | |
730 break; | |
731 } | |
732 ++retval; | |
733 } | |
734 } | |
735 done = SDL_TRUE; | |
736 break; | |
737 case 'o': | |
738 if ( radix == 10 ) { | |
739 radix = 8; | |
740 } | |
741 /* Fall through to unsigned handling */ | |
742 case 'x': | |
743 case 'X': | |
744 if ( radix == 10 ) { | |
745 radix = 16; | |
746 } | |
747 /* Fall through to unsigned handling */ | |
748 case 'u': | |
749 #ifdef SDL_HAS_64BIT_TYPE | |
750 if ( inttype == DO_LONGLONG ) { | |
751 Uint64 value; | |
752 text += SDL_ScanUnsignedLongLong(text, radix, &value); | |
753 if ( ! suppress ) { | |
754 Uint64 *valuep = va_arg(ap, Uint64*); | |
755 *valuep = value; | |
756 ++retval; | |
757 } | |
758 } | |
759 else | |
760 #endif /* SDL_HAS_64BIT_TYPE */ | |
761 { | |
762 unsigned long value; | |
763 text += SDL_ScanUnsignedLong(text, radix, &value); | |
764 if ( ! suppress ) { | |
765 switch (inttype) { | |
766 case DO_SHORT: | |
767 { short* valuep = va_arg(ap, short*); | |
768 *valuep = (short)value; | |
769 } | |
770 break; | |
771 case DO_INT: | |
772 { int* valuep = va_arg(ap, int*); | |
773 *valuep = (int)value; | |
774 } | |
775 break; | |
776 case DO_LONG: | |
777 { long* valuep = va_arg(ap, long*); | |
778 *valuep = value; | |
779 } | |
780 break; | |
781 case DO_LONGLONG: | |
782 /* Handled above */ | |
783 break; | |
784 } | |
785 ++retval; | |
786 } | |
787 } | |
788 done = SDL_TRUE; | |
789 break; | |
790 case 'p': | |
791 { | |
792 unsigned long value; | |
793 text += SDL_ScanUnsignedLong(text, 16, &value); | |
794 if ( ! suppress ) { | |
795 void** valuep = va_arg(ap, void**); | |
796 *valuep = (void*)value; | |
797 ++retval; | |
798 } | |
799 } | |
800 done = SDL_TRUE; | |
801 break; | |
802 case 'f': | |
803 { | |
804 double value; | |
805 text += SDL_ScanFloat(text, &value); | |
806 if ( ! suppress ) { | |
807 float* valuep = va_arg(ap, float*); | |
808 *valuep = (float)value; | |
809 ++retval; | |
810 } | |
811 } | |
812 done = SDL_TRUE; | |
813 break; | |
814 case 's': | |
815 if ( suppress ) { | |
816 while ( !isspace(*text) ) { | |
817 ++text; | |
818 if ( count ) { | |
819 if ( --count == 0 ) { | |
820 break; | |
821 } | |
822 } | |
823 } | |
824 } else { | |
825 char *valuep = va_arg(ap, char*); | |
826 while ( !isspace(*text) ) { | |
827 *valuep++ = *text++; | |
828 if ( count ) { | |
829 if ( --count == 0 ) { | |
830 break; | |
831 } | |
832 } | |
833 } | |
834 *valuep = '\0'; | |
835 ++retval; | |
836 } | |
837 done = SDL_TRUE; | |
838 break; | |
839 default: | |
840 done = SDL_TRUE; | |
841 break; | |
842 } | |
843 ++fmt; | |
844 } | |
845 continue; | |
846 } | |
847 if ( *text == *fmt ) { | |
848 ++text; | |
849 ++fmt; | |
850 continue; | |
851 } | |
852 /* Text didn't match format specifier */ | |
853 break; | |
854 } | |
855 va_end(ap); | |
856 | |
857 return retval; | |
858 } | |
859 #endif | |
860 | |
861 #ifndef HAVE_SNPRINTF | |
862 int SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...) | |
863 { | |
864 va_list ap; | |
865 int retval; | |
866 | |
867 va_start(ap, fmt); | |
868 retval = SDL_vsnprintf(text, maxlen, fmt, ap); | |
869 va_end(ap); | |
870 | |
871 return retval; | |
872 } | |
873 #endif | |
874 | |
875 #ifndef HAVE_VSNPRINTF | |
876 static size_t SDL_PrintLong(char *text, long value, int radix, size_t maxlen) | |
877 { | |
878 char num[130]; | |
879 size_t size; | |
880 | |
881 _ltoa(value, num, radix); | |
882 size = SDL_strlen(num); | |
883 if ( size > maxlen ) { | |
884 size = maxlen; | |
885 } | |
886 strncpy(text, num, size); | |
887 | |
888 return size; | |
889 } | |
890 static size_t SDL_PrintUnsignedLong(char *text, unsigned long value, int radix, size_t maxlen) | |
891 { | |
892 char num[130]; | |
893 size_t size; | |
894 | |
895 _ultoa(value, num, radix); | |
896 size = SDL_strlen(num); | |
897 if ( size > maxlen ) { | |
898 size = maxlen; | |
899 } | |
900 strncpy(text, num, size); | |
901 | |
902 return size; | |
903 } | |
904 #ifdef SDL_HAS_64BIT_TYPE | |
905 static size_t SDL_PrintLongLong(char *text, Sint64 value, int radix, size_t maxlen) | |
906 { | |
907 char num[130]; | |
908 size_t size; | |
909 | |
910 _i64toa(value, num, radix); | |
911 size = SDL_strlen(num); | |
912 if ( size > maxlen ) { | |
913 size = maxlen; | |
914 } | |
915 strncpy(text, num, size); | |
916 | |
917 return size; | |
918 } | |
919 static size_t SDL_PrintUnsignedLongLong(char *text, Uint64 value, int radix, size_t maxlen) | |
920 { | |
921 char num[130]; | |
922 size_t size; | |
923 | |
924 _ui64toa(value, num, radix); | |
925 size = SDL_strlen(num); | |
926 if ( size > maxlen ) { | |
927 size = maxlen; | |
928 } | |
929 strncpy(text, num, size); | |
930 | |
931 return size; | |
932 } | |
933 #endif /* SDL_HAS_64BIT_TYPE */ | |
934 static size_t SDL_PrintFloat(char *text, double arg, size_t maxlen) | |
935 { | |
936 char *textstart = text; | |
937 if ( arg ) { | |
938 /* This isn't especially accurate, but hey, it's easy. :) */ | |
939 const double precision = 0.00000001; | |
940 size_t len; | |
941 unsigned long value; | |
942 | |
943 if ( arg < 0 ) { | |
944 *text++ = '-'; | |
945 --maxlen; | |
946 arg = -arg; | |
947 } | |
948 value = (unsigned long)arg; | |
949 len = SDL_PrintUnsignedLong(text, value, 10, maxlen); | |
950 text += len; | |
951 maxlen -= len; | |
952 arg -= value; | |
953 if ( arg > precision && maxlen ) { | |
954 int mult = 10; | |
955 *text++ = '.'; | |
956 while ( (arg > precision) && maxlen ) { | |
957 value = (unsigned long)(arg * mult); | |
958 len = SDL_PrintUnsignedLong(text, value, 10, maxlen); | |
959 text += len; | |
960 maxlen -= len; | |
961 arg -= (double)value / mult; | |
962 mult *= 10; | |
963 } | |
964 } | |
965 } else { | |
966 *text++ = '0'; | |
967 } | |
968 return (text - textstart); | |
969 } | |
970 static size_t SDL_PrintString(char *text, const char *string, size_t maxlen) | |
971 { | |
972 char *textstart = text; | |
973 while ( *string && maxlen-- ) { | |
974 *text++ = *string++; | |
975 } | |
976 return (text - textstart); | |
977 } | |
978 int SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap) | |
979 { | |
980 char *textstart = text; | |
981 if ( maxlen <= 0 ) { | |
982 return 0; | |
983 } | |
984 --maxlen; /* For the trailing '\0' */ | |
985 while ( *fmt && maxlen ) { | |
986 if ( *fmt == '%' ) { | |
987 SDL_bool done = SDL_FALSE; | |
988 size_t len = 0; | |
989 SDL_bool do_lowercase = SDL_FALSE; | |
990 int radix = 10; | |
991 enum { | |
992 DO_INT, | |
993 DO_LONG, | |
994 DO_LONGLONG | |
995 } inttype = DO_INT; | |
996 | |
997 ++fmt; | |
998 /* FIXME: implement more of the format specifiers */ | |
999 while (!done) { | |
1000 switch(*fmt) { | |
1001 case '%': | |
1002 *text = '%'; | |
1003 len = 1; | |
1004 done = SDL_TRUE; | |
1005 break; | |
1006 case 'c': | |
1007 /* char is promoted to int when passed through (...) */ | |
1008 *text = (char)va_arg(ap, int); | |
1009 len = 1; | |
1010 done = SDL_TRUE; | |
1011 break; | |
1012 case 'h': | |
1013 /* short is promoted to int when passed through (...) */ | |
1014 break; | |
1015 case 'l': | |
1016 if ( inttype < DO_LONGLONG ) { | |
1017 ++inttype; | |
1018 } | |
1019 break; | |
1020 case 'I': | |
1021 if ( SDL_strncmp(fmt, "I64", 3) == 0 ) { | |
1022 fmt += 2; | |
1023 inttype = DO_LONGLONG; | |
1024 } | |
1025 break; | |
1026 case 'i': | |
1027 case 'd': | |
1028 switch (inttype) { | |
1029 case DO_INT: | |
1030 len = SDL_PrintLong(text, (long)va_arg(ap, int), radix, maxlen); | |
1031 break; | |
1032 case DO_LONG: | |
1033 len = SDL_PrintLong(text, va_arg(ap, long), radix, maxlen); | |
1034 break; | |
1035 case DO_LONGLONG: | |
1036 #ifdef SDL_HAS_64BIT_TYPE | |
1037 len = SDL_PrintLongLong(text, va_arg(ap, Sint64), radix, maxlen); | |
1038 #else | |
1039 len = SDL_PrintLong(text, va_arg(ap, long), radix, maxlen); | |
1040 #endif | |
1041 break; | |
1042 } | |
1043 done = SDL_TRUE; | |
1044 break; | |
1045 case 'p': | |
1046 case 'x': | |
1047 do_lowercase = SDL_TRUE; | |
1048 /* Fall through to 'X' handling */ | |
1049 case 'X': | |
1050 if ( radix == 10 ) { | |
1051 radix = 16; | |
1052 } | |
1053 if ( *fmt == 'p' ) { | |
1054 inttype = DO_LONG; | |
1055 } | |
1056 /* Fall through to unsigned handling */ | |
1057 case 'o': | |
1058 if ( radix == 10 ) { | |
1059 radix = 8; | |
1060 } | |
1061 /* Fall through to unsigned handling */ | |
1062 case 'u': | |
1063 switch (inttype) { | |
1064 case DO_INT: | |
1065 len = SDL_PrintUnsignedLong(text, (unsigned long)va_arg(ap, unsigned int), radix, maxlen); | |
1066 break; | |
1067 case DO_LONG: | |
1068 len = SDL_PrintUnsignedLong(text, va_arg(ap, unsigned long), radix, maxlen); | |
1069 break; | |
1070 case DO_LONGLONG: | |
1071 #ifdef SDL_HAS_64BIT_TYPE | |
1072 len = SDL_PrintUnsignedLongLong(text, va_arg(ap, Uint64), radix, maxlen); | |
1073 #else | |
1074 len = SDL_PrintUnsignedLong(text, va_arg(ap, unsigned long), radix, maxlen); | |
1075 #endif | |
1076 break; | |
1077 } | |
1078 if ( do_lowercase ) { | |
1079 _strlwr(text); | |
1080 } | |
1081 done = SDL_TRUE; | |
1082 break; | |
1083 case 'f': | |
1084 len = SDL_PrintFloat(text, va_arg(ap, double), maxlen); | |
1085 done = SDL_TRUE; | |
1086 break; | |
1087 case 's': | |
1088 len = SDL_PrintString(text, va_arg(ap, char*), maxlen); | |
1089 done = SDL_TRUE; | |
1090 break; | |
1091 default: | |
1092 done = SDL_TRUE; | |
1093 break; | |
1094 } | |
1095 ++fmt; | |
1096 } | |
1097 text += len; | |
1098 maxlen -= len; | |
1099 } else { | |
1100 *text++ = *fmt++; | |
1101 --maxlen; | |
1102 } | |
1103 } | |
1104 *text = '\0'; | |
1105 | |
1106 return (text - textstart); | |
1107 } | |
1108 #endif |