src/stdlib/SDL_string.c
author Ozkan Sezer <sezeroz@gmail.com>
Sun, 14 Oct 2018 15:25:04 +0300
branchSDL-1.2
changeset 12325 c4f2eeda176f
parent 12050 f68904a749c9
child 13014 35a99e8ae9c4
permissions -rw-r--r--
remove symlink for libSDL-1.0.so.0 from the rpm spec file.

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