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