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