src/file/SDL_rwops.c
author David Ludwig <dludwig@pobox.com>
Sun, 27 Oct 2013 21:26:46 -0400
changeset 8535 e8ee0708ef5c
parent 8477 ad08f0d710f3
parent 7828 1451063c8ecd
child 8582 c3e9a2b93517
permissions -rw-r--r--
WinRT: merged with SDL 2.0.1 codebase
dludwig@8477
     1
/*
dludwig@8477
     2
  Simple DirectMedia Layer
dludwig@8477
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
dludwig@8477
     4
dludwig@8477
     5
  This software is provided 'as-is', without any express or implied
dludwig@8477
     6
  warranty.  In no event will the authors be held liable for any damages
dludwig@8477
     7
  arising from the use of this software.
dludwig@8477
     8
dludwig@8477
     9
  Permission is granted to anyone to use this software for any purpose,
dludwig@8477
    10
  including commercial applications, and to alter it and redistribute it
dludwig@8477
    11
  freely, subject to the following restrictions:
dludwig@8477
    12
dludwig@8477
    13
  1. The origin of this software must not be misrepresented; you must not
dludwig@8477
    14
     claim that you wrote the original software. If you use this software
dludwig@8477
    15
     in a product, an acknowledgment in the product documentation would be
dludwig@8477
    16
     appreciated but is not required.
dludwig@8477
    17
  2. Altered source versions must be plainly marked as such, and must not be
dludwig@8477
    18
     misrepresented as being the original software.
dludwig@8477
    19
  3. This notice may not be removed or altered from any source distribution.
dludwig@8477
    20
*/
dludwig@8477
    21
/* Need this so Linux systems define fseek64o, ftell64o and off64_t */
dludwig@8477
    22
#define _LARGEFILE64_SOURCE
dludwig@8477
    23
#include "SDL_config.h"
dludwig@8477
    24
dludwig@8535
    25
#if defined(__WIN32__)
dludwig@8535
    26
#include "../core/windows/SDL_windows.h"
dludwig@8535
    27
#endif
dludwig@8535
    28
dludwig@8535
    29
dludwig@8477
    30
/* This file provides a general interface for SDL to read and write
dludwig@8477
    31
   data sources.  It can easily be extended to files, memory, etc.
dludwig@8477
    32
*/
dludwig@8477
    33
dludwig@8477
    34
#include "SDL_endian.h"
dludwig@8477
    35
#include "SDL_rwops.h"
dludwig@8477
    36
dludwig@8477
    37
#ifdef __APPLE__
dludwig@8477
    38
#include "cocoa/SDL_rwopsbundlesupport.h"
dludwig@8477
    39
#endif /* __APPLE__ */
dludwig@8477
    40
dludwig@8477
    41
#ifdef ANDROID
dludwig@8477
    42
#include "../core/android/SDL_android.h"
dludwig@8477
    43
#include "SDL_system.h"
dludwig@8477
    44
#endif
dludwig@8477
    45
dludwig@8477
    46
#ifdef __WIN32__
dludwig@8477
    47
dludwig@8477
    48
/* Functions to read/write Win32 API file pointers */
dludwig@8477
    49
dludwig@8477
    50
#ifndef INVALID_SET_FILE_POINTER
dludwig@8477
    51
#define INVALID_SET_FILE_POINTER 0xFFFFFFFF
dludwig@8477
    52
#endif
dludwig@8477
    53
dludwig@8477
    54
#define READAHEAD_BUFFER_SIZE   1024
dludwig@8477
    55
dludwig@8477
    56
static int SDLCALL
dludwig@8477
    57
windows_file_open(SDL_RWops * context, const char *filename, const char *mode)
dludwig@8477
    58
{
dludwig@8477
    59
    UINT old_error_mode;
dludwig@8477
    60
    HANDLE h;
dludwig@8477
    61
    DWORD r_right, w_right;
dludwig@8477
    62
    DWORD must_exist, truncate;
dludwig@8477
    63
    int a_mode;
dludwig@8477
    64
dludwig@8477
    65
    if (!context)
dludwig@8477
    66
        return -1;              /* failed (invalid call) */
dludwig@8477
    67
dludwig@8477
    68
    context->hidden.windowsio.h = INVALID_HANDLE_VALUE;   /* mark this as unusable */
dludwig@8477
    69
    context->hidden.windowsio.buffer.data = NULL;
dludwig@8477
    70
    context->hidden.windowsio.buffer.size = 0;
dludwig@8477
    71
    context->hidden.windowsio.buffer.left = 0;
dludwig@8477
    72
dludwig@8477
    73
    /* "r" = reading, file must exist */
dludwig@8477
    74
    /* "w" = writing, truncate existing, file may not exist */
dludwig@8477
    75
    /* "r+"= reading or writing, file must exist            */
dludwig@8477
    76
    /* "a" = writing, append file may not exist             */
dludwig@8477
    77
    /* "a+"= append + read, file may not exist              */
dludwig@8477
    78
    /* "w+" = read, write, truncate. file may not exist    */
dludwig@8477
    79
dludwig@8477
    80
    must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
dludwig@8477
    81
    truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
dludwig@8477
    82
    r_right = (SDL_strchr(mode, '+') != NULL
dludwig@8477
    83
               || must_exist) ? GENERIC_READ : 0;
dludwig@8477
    84
    a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
dludwig@8477
    85
    w_right = (a_mode || SDL_strchr(mode, '+')
dludwig@8477
    86
               || truncate) ? GENERIC_WRITE : 0;
dludwig@8477
    87
dludwig@8477
    88
    if (!r_right && !w_right)   /* inconsistent mode */
dludwig@8477
    89
        return -1;              /* failed (invalid call) */
dludwig@8477
    90
dludwig@8477
    91
    context->hidden.windowsio.buffer.data =
dludwig@8477
    92
        (char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
dludwig@8477
    93
    if (!context->hidden.windowsio.buffer.data) {
dludwig@8477
    94
        return SDL_OutOfMemory();
dludwig@8477
    95
    }
dludwig@8477
    96
    /* Do not open a dialog box if failure */
dludwig@8477
    97
    old_error_mode =
dludwig@8477
    98
        SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
dludwig@8477
    99
dludwig@8477
   100
    {
dludwig@8477
   101
        LPTSTR tstr = WIN_UTF8ToString(filename);
dludwig@8477
   102
        h = CreateFile(tstr, (w_right | r_right),
dludwig@8477
   103
                       (w_right) ? 0 : FILE_SHARE_READ, NULL,
dludwig@8477
   104
                       (must_exist | truncate | a_mode),
dludwig@8477
   105
                       FILE_ATTRIBUTE_NORMAL, NULL);
dludwig@8477
   106
        SDL_free(tstr);
dludwig@8477
   107
    }
dludwig@8477
   108
dludwig@8477
   109
    /* restore old behavior */
dludwig@8477
   110
    SetErrorMode(old_error_mode);
dludwig@8477
   111
dludwig@8477
   112
    if (h == INVALID_HANDLE_VALUE) {
dludwig@8477
   113
        SDL_free(context->hidden.windowsio.buffer.data);
dludwig@8477
   114
        context->hidden.windowsio.buffer.data = NULL;
dludwig@8477
   115
        SDL_SetError("Couldn't open %s", filename);
dludwig@8477
   116
        return -2;              /* failed (CreateFile) */
dludwig@8477
   117
    }
dludwig@8477
   118
    context->hidden.windowsio.h = h;
dludwig@8477
   119
    context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE;
dludwig@8477
   120
dludwig@8477
   121
    return 0;                   /* ok */
dludwig@8477
   122
}
dludwig@8477
   123
dludwig@8477
   124
static Sint64 SDLCALL
dludwig@8477
   125
windows_file_size(SDL_RWops * context)
dludwig@8477
   126
{
dludwig@8477
   127
    LARGE_INTEGER size;
dludwig@8477
   128
dludwig@8477
   129
    if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
dludwig@8477
   130
        return SDL_SetError("windows_file_size: invalid context/file not opened");
dludwig@8477
   131
    }
dludwig@8477
   132
dludwig@8477
   133
    if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) {
dludwig@8477
   134
        return WIN_SetError("windows_file_size");
dludwig@8477
   135
    }
dludwig@8477
   136
dludwig@8477
   137
    return size.QuadPart;
dludwig@8477
   138
}
dludwig@8477
   139
dludwig@8477
   140
static Sint64 SDLCALL
dludwig@8477
   141
windows_file_seek(SDL_RWops * context, Sint64 offset, int whence)
dludwig@8477
   142
{
dludwig@8477
   143
    DWORD windowswhence;
dludwig@8477
   144
    LARGE_INTEGER windowsoffset;
dludwig@8477
   145
dludwig@8477
   146
    if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
dludwig@8477
   147
        return SDL_SetError("windows_file_seek: invalid context/file not opened");
dludwig@8477
   148
    }
dludwig@8477
   149
dludwig@8477
   150
    /* FIXME: We may be able to satisfy the seek within buffered data */
dludwig@8477
   151
    if (whence == RW_SEEK_CUR && context->hidden.windowsio.buffer.left) {
dludwig@8477
   152
        offset -= (long)context->hidden.windowsio.buffer.left;
dludwig@8477
   153
    }
dludwig@8477
   154
    context->hidden.windowsio.buffer.left = 0;
dludwig@8477
   155
dludwig@8477
   156
    switch (whence) {
dludwig@8477
   157
    case RW_SEEK_SET:
dludwig@8477
   158
        windowswhence = FILE_BEGIN;
dludwig@8477
   159
        break;
dludwig@8477
   160
    case RW_SEEK_CUR:
dludwig@8477
   161
        windowswhence = FILE_CURRENT;
dludwig@8477
   162
        break;
dludwig@8477
   163
    case RW_SEEK_END:
dludwig@8477
   164
        windowswhence = FILE_END;
dludwig@8477
   165
        break;
dludwig@8477
   166
    default:
dludwig@8477
   167
        return SDL_SetError("windows_file_seek: Unknown value for 'whence'");
dludwig@8477
   168
    }
dludwig@8477
   169
dludwig@8477
   170
    windowsoffset.QuadPart = offset;
dludwig@8477
   171
    if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) {
dludwig@8477
   172
        return WIN_SetError("windows_file_seek");
dludwig@8477
   173
    }
dludwig@8477
   174
    return windowsoffset.QuadPart;
dludwig@8477
   175
}
dludwig@8477
   176
dludwig@8477
   177
static size_t SDLCALL
dludwig@8477
   178
windows_file_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
dludwig@8477
   179
{
dludwig@8477
   180
    size_t total_need;
dludwig@8477
   181
    size_t total_read = 0;
dludwig@8477
   182
    size_t read_ahead;
dludwig@8477
   183
    DWORD byte_read;
dludwig@8477
   184
dludwig@8477
   185
    total_need = size * maxnum;
dludwig@8477
   186
dludwig@8477
   187
    if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
dludwig@8477
   188
        || !total_need)
dludwig@8477
   189
        return 0;
dludwig@8477
   190
dludwig@8477
   191
    if (context->hidden.windowsio.buffer.left > 0) {
dludwig@8477
   192
        void *data = (char *) context->hidden.windowsio.buffer.data +
dludwig@8477
   193
            context->hidden.windowsio.buffer.size -
dludwig@8477
   194
            context->hidden.windowsio.buffer.left;
dludwig@8477
   195
        read_ahead =
dludwig@8477
   196
            SDL_min(total_need, context->hidden.windowsio.buffer.left);
dludwig@8477
   197
        SDL_memcpy(ptr, data, read_ahead);
dludwig@8477
   198
        context->hidden.windowsio.buffer.left -= read_ahead;
dludwig@8477
   199
dludwig@8477
   200
        if (read_ahead == total_need) {
dludwig@8477
   201
            return maxnum;
dludwig@8477
   202
        }
dludwig@8477
   203
        ptr = (char *) ptr + read_ahead;
dludwig@8477
   204
        total_need -= read_ahead;
dludwig@8477
   205
        total_read += read_ahead;
dludwig@8477
   206
    }
dludwig@8477
   207
dludwig@8477
   208
    if (total_need < READAHEAD_BUFFER_SIZE) {
dludwig@8477
   209
        if (!ReadFile
dludwig@8477
   210
            (context->hidden.windowsio.h, context->hidden.windowsio.buffer.data,
dludwig@8477
   211
             READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
dludwig@8477
   212
            SDL_Error(SDL_EFREAD);
dludwig@8477
   213
            return 0;
dludwig@8477
   214
        }
dludwig@8477
   215
        read_ahead = SDL_min(total_need, (int) byte_read);
dludwig@8477
   216
        SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead);
dludwig@8477
   217
        context->hidden.windowsio.buffer.size = byte_read;
dludwig@8477
   218
        context->hidden.windowsio.buffer.left = byte_read - read_ahead;
dludwig@8477
   219
        total_read += read_ahead;
dludwig@8477
   220
    } else {
dludwig@8477
   221
        if (!ReadFile
dludwig@8477
   222
            (context->hidden.windowsio.h, ptr, (DWORD)total_need, &byte_read, NULL)) {
dludwig@8477
   223
            SDL_Error(SDL_EFREAD);
dludwig@8477
   224
            return 0;
dludwig@8477
   225
        }
dludwig@8477
   226
        total_read += byte_read;
dludwig@8477
   227
    }
dludwig@8477
   228
    return (total_read / size);
dludwig@8477
   229
}
dludwig@8477
   230
dludwig@8477
   231
static size_t SDLCALL
dludwig@8477
   232
windows_file_write(SDL_RWops * context, const void *ptr, size_t size,
dludwig@8477
   233
                 size_t num)
dludwig@8477
   234
{
dludwig@8477
   235
dludwig@8477
   236
    size_t total_bytes;
dludwig@8477
   237
    DWORD byte_written;
dludwig@8477
   238
    size_t nwritten;
dludwig@8477
   239
dludwig@8477
   240
    total_bytes = size * num;
dludwig@8477
   241
dludwig@8477
   242
    if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
dludwig@8477
   243
        || total_bytes <= 0 || !size)
dludwig@8477
   244
        return 0;
dludwig@8477
   245
dludwig@8477
   246
    if (context->hidden.windowsio.buffer.left) {
dludwig@8477
   247
        SetFilePointer(context->hidden.windowsio.h,
dludwig@8477
   248
                       -(LONG)context->hidden.windowsio.buffer.left, NULL,
dludwig@8477
   249
                       FILE_CURRENT);
dludwig@8477
   250
        context->hidden.windowsio.buffer.left = 0;
dludwig@8477
   251
    }
dludwig@8477
   252
dludwig@8477
   253
    /* if in append mode, we must go to the EOF before write */
dludwig@8477
   254
    if (context->hidden.windowsio.append) {
dludwig@8477
   255
        if (SetFilePointer(context->hidden.windowsio.h, 0L, NULL, FILE_END) ==
dludwig@8477
   256
            INVALID_SET_FILE_POINTER) {
dludwig@8477
   257
            SDL_Error(SDL_EFWRITE);
dludwig@8477
   258
            return 0;
dludwig@8477
   259
        }
dludwig@8477
   260
    }
dludwig@8477
   261
dludwig@8477
   262
    if (!WriteFile
dludwig@8477
   263
        (context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) {
dludwig@8477
   264
        SDL_Error(SDL_EFWRITE);
dludwig@8477
   265
        return 0;
dludwig@8477
   266
    }
dludwig@8477
   267
dludwig@8477
   268
    nwritten = byte_written / size;
dludwig@8477
   269
    return nwritten;
dludwig@8477
   270
}
dludwig@8477
   271
dludwig@8477
   272
static int SDLCALL
dludwig@8477
   273
windows_file_close(SDL_RWops * context)
dludwig@8477
   274
{
dludwig@8477
   275
dludwig@8477
   276
    if (context) {
dludwig@8477
   277
        if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) {
dludwig@8477
   278
            CloseHandle(context->hidden.windowsio.h);
dludwig@8477
   279
            context->hidden.windowsio.h = INVALID_HANDLE_VALUE;   /* to be sure */
dludwig@8477
   280
        }
dludwig@8535
   281
        SDL_free(context->hidden.windowsio.buffer.data);
dludwig@8535
   282
        context->hidden.windowsio.buffer.data = NULL;
dludwig@8477
   283
        SDL_FreeRW(context);
dludwig@8477
   284
    }
dludwig@8477
   285
    return (0);
dludwig@8477
   286
}
dludwig@8477
   287
#endif /* __WIN32__ */
dludwig@8477
   288
dludwig@8477
   289
#ifdef HAVE_STDIO_H
dludwig@8477
   290
dludwig@8477
   291
/* Functions to read/write stdio file pointers */
dludwig@8477
   292
dludwig@8477
   293
static Sint64 SDLCALL
dludwig@8477
   294
stdio_size(SDL_RWops * context)
dludwig@8477
   295
{
dludwig@8477
   296
    Sint64 pos, size;
dludwig@8477
   297
dludwig@8477
   298
    pos = SDL_RWseek(context, 0, RW_SEEK_CUR);
dludwig@8477
   299
    if (pos < 0) {
dludwig@8477
   300
        return -1;
dludwig@8477
   301
    }
dludwig@8477
   302
    size = SDL_RWseek(context, 0, RW_SEEK_END);
dludwig@8477
   303
dludwig@8477
   304
    SDL_RWseek(context, pos, RW_SEEK_SET);
dludwig@8477
   305
    return size;
dludwig@8477
   306
}
dludwig@8477
   307
dludwig@8477
   308
static Sint64 SDLCALL
dludwig@8477
   309
stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
dludwig@8477
   310
{
dludwig@8477
   311
#ifdef HAVE_FSEEKO64
dludwig@8477
   312
    if (fseeko64(context->hidden.stdio.fp, (off64_t)offset, whence) == 0) {
dludwig@8477
   313
        return ftello64(context->hidden.stdio.fp);
dludwig@8477
   314
    }
dludwig@8477
   315
#elif defined(HAVE_FSEEKO)
dludwig@8477
   316
    if (fseeko(context->hidden.stdio.fp, (off_t)offset, whence) == 0) {
dludwig@8477
   317
        return ftello(context->hidden.stdio.fp);
dludwig@8477
   318
    }
dludwig@8477
   319
#elif defined(HAVE__FSEEKI64)
dludwig@8477
   320
    if (_fseeki64(context->hidden.stdio.fp, offset, whence) == 0) {
dludwig@8477
   321
        return _ftelli64(context->hidden.stdio.fp);
dludwig@8477
   322
    }
dludwig@8477
   323
#else
dludwig@8477
   324
    if (fseek(context->hidden.stdio.fp, offset, whence) == 0) {
dludwig@8477
   325
        return (ftell(context->hidden.stdio.fp));
dludwig@8477
   326
    }
dludwig@8477
   327
#endif
dludwig@8477
   328
    return SDL_Error(SDL_EFSEEK);
dludwig@8477
   329
}
dludwig@8477
   330
dludwig@8477
   331
static size_t SDLCALL
dludwig@8477
   332
stdio_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
dludwig@8477
   333
{
dludwig@8477
   334
    size_t nread;
dludwig@8477
   335
dludwig@8477
   336
    nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
dludwig@8477
   337
    if (nread == 0 && ferror(context->hidden.stdio.fp)) {
dludwig@8477
   338
        SDL_Error(SDL_EFREAD);
dludwig@8477
   339
    }
dludwig@8477
   340
    return (nread);
dludwig@8477
   341
}
dludwig@8477
   342
dludwig@8477
   343
static size_t SDLCALL
dludwig@8477
   344
stdio_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
dludwig@8477
   345
{
dludwig@8477
   346
    size_t nwrote;
dludwig@8477
   347
dludwig@8477
   348
    nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
dludwig@8477
   349
    if (nwrote == 0 && ferror(context->hidden.stdio.fp)) {
dludwig@8477
   350
        SDL_Error(SDL_EFWRITE);
dludwig@8477
   351
    }
dludwig@8477
   352
    return (nwrote);
dludwig@8477
   353
}
dludwig@8477
   354
dludwig@8477
   355
static int SDLCALL
dludwig@8477
   356
stdio_close(SDL_RWops * context)
dludwig@8477
   357
{
dludwig@8477
   358
    int status = 0;
dludwig@8477
   359
    if (context) {
dludwig@8477
   360
        if (context->hidden.stdio.autoclose) {
dludwig@8477
   361
            /* WARNING:  Check the return value here! */
dludwig@8477
   362
            if (fclose(context->hidden.stdio.fp) != 0) {
dludwig@8477
   363
                status = SDL_Error(SDL_EFWRITE);
dludwig@8477
   364
            }
dludwig@8477
   365
        }
dludwig@8477
   366
        SDL_FreeRW(context);
dludwig@8477
   367
    }
dludwig@8477
   368
    return status;
dludwig@8477
   369
}
dludwig@8477
   370
#endif /* !HAVE_STDIO_H */
dludwig@8477
   371
dludwig@8477
   372
/* Functions to read/write memory pointers */
dludwig@8477
   373
dludwig@8477
   374
static Sint64 SDLCALL
dludwig@8477
   375
mem_size(SDL_RWops * context)
dludwig@8477
   376
{
dludwig@8477
   377
    return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base);
dludwig@8477
   378
}
dludwig@8477
   379
dludwig@8477
   380
static Sint64 SDLCALL
dludwig@8477
   381
mem_seek(SDL_RWops * context, Sint64 offset, int whence)
dludwig@8477
   382
{
dludwig@8477
   383
    Uint8 *newpos;
dludwig@8477
   384
dludwig@8477
   385
    switch (whence) {
dludwig@8477
   386
    case RW_SEEK_SET:
dludwig@8477
   387
        newpos = context->hidden.mem.base + offset;
dludwig@8477
   388
        break;
dludwig@8477
   389
    case RW_SEEK_CUR:
dludwig@8477
   390
        newpos = context->hidden.mem.here + offset;
dludwig@8477
   391
        break;
dludwig@8477
   392
    case RW_SEEK_END:
dludwig@8477
   393
        newpos = context->hidden.mem.stop + offset;
dludwig@8477
   394
        break;
dludwig@8477
   395
    default:
dludwig@8477
   396
        return SDL_SetError("Unknown value for 'whence'");
dludwig@8477
   397
    }
dludwig@8477
   398
    if (newpos < context->hidden.mem.base) {
dludwig@8477
   399
        newpos = context->hidden.mem.base;
dludwig@8477
   400
    }
dludwig@8477
   401
    if (newpos > context->hidden.mem.stop) {
dludwig@8477
   402
        newpos = context->hidden.mem.stop;
dludwig@8477
   403
    }
dludwig@8477
   404
    context->hidden.mem.here = newpos;
dludwig@8477
   405
    return (Sint64)(context->hidden.mem.here - context->hidden.mem.base);
dludwig@8477
   406
}
dludwig@8477
   407
dludwig@8477
   408
static size_t SDLCALL
dludwig@8477
   409
mem_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
dludwig@8477
   410
{
dludwig@8477
   411
    size_t total_bytes;
dludwig@8477
   412
    size_t mem_available;
dludwig@8477
   413
dludwig@8477
   414
    total_bytes = (maxnum * size);
dludwig@8477
   415
    if ((maxnum <= 0) || (size <= 0)
dludwig@8477
   416
        || ((total_bytes / maxnum) != (size_t) size)) {
dludwig@8477
   417
        return 0;
dludwig@8477
   418
    }
dludwig@8477
   419
dludwig@8477
   420
    mem_available = (context->hidden.mem.stop - context->hidden.mem.here);
dludwig@8477
   421
    if (total_bytes > mem_available) {
dludwig@8477
   422
        total_bytes = mem_available;
dludwig@8477
   423
    }
dludwig@8477
   424
dludwig@8477
   425
    SDL_memcpy(ptr, context->hidden.mem.here, total_bytes);
dludwig@8477
   426
    context->hidden.mem.here += total_bytes;
dludwig@8477
   427
dludwig@8477
   428
    return (total_bytes / size);
dludwig@8477
   429
}
dludwig@8477
   430
dludwig@8477
   431
static size_t SDLCALL
dludwig@8477
   432
mem_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
dludwig@8477
   433
{
dludwig@8477
   434
    if ((context->hidden.mem.here + (num * size)) > context->hidden.mem.stop) {
dludwig@8477
   435
        num = (context->hidden.mem.stop - context->hidden.mem.here) / size;
dludwig@8477
   436
    }
dludwig@8477
   437
    SDL_memcpy(context->hidden.mem.here, ptr, num * size);
dludwig@8477
   438
    context->hidden.mem.here += num * size;
dludwig@8477
   439
    return (num);
dludwig@8477
   440
}
dludwig@8477
   441
dludwig@8477
   442
static size_t SDLCALL
dludwig@8477
   443
mem_writeconst(SDL_RWops * context, const void *ptr, size_t size, size_t num)
dludwig@8477
   444
{
dludwig@8477
   445
    SDL_SetError("Can't write to read-only memory");
dludwig@8477
   446
    return (0);
dludwig@8477
   447
}
dludwig@8477
   448
dludwig@8477
   449
static int SDLCALL
dludwig@8477
   450
mem_close(SDL_RWops * context)
dludwig@8477
   451
{
dludwig@8477
   452
    if (context) {
dludwig@8477
   453
        SDL_FreeRW(context);
dludwig@8477
   454
    }
dludwig@8477
   455
    return (0);
dludwig@8477
   456
}
dludwig@8477
   457
dludwig@8477
   458
dludwig@8477
   459
/* Functions to create SDL_RWops structures from various data sources */
dludwig@8477
   460
dludwig@8477
   461
SDL_RWops *
dludwig@8477
   462
SDL_RWFromFile(const char *file, const char *mode)
dludwig@8477
   463
{
dludwig@8477
   464
    SDL_RWops *rwops = NULL;
dludwig@8477
   465
    if (!file || !*file || !mode || !*mode) {
dludwig@8477
   466
        SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
dludwig@8477
   467
        return NULL;
dludwig@8477
   468
    }
dludwig@8477
   469
#if defined(ANDROID)
dludwig@8477
   470
#ifdef HAVE_STDIO_H
dludwig@8477
   471
    /* Try to open the file on the filesystem first */
dludwig@8477
   472
    if (*file == '/') {
dludwig@8477
   473
        FILE *fp = fopen(file, mode);
dludwig@8477
   474
        if (fp) {
dludwig@8477
   475
            return SDL_RWFromFP(fp, 1);
dludwig@8477
   476
        }
dludwig@8477
   477
    } else {
dludwig@8477
   478
        /* Try opening it from internal storage if it's a relative path */
dludwig@8477
   479
        char *path;
dludwig@8477
   480
        FILE *fp;
dludwig@8477
   481
dludwig@8477
   482
        path = SDL_stack_alloc(char, PATH_MAX);
dludwig@8477
   483
        if (path) {
dludwig@8477
   484
            SDL_snprintf(path, PATH_MAX, "%s/%s",
dludwig@8477
   485
                         SDL_AndroidGetInternalStoragePath(), file);
dludwig@8477
   486
            fp = fopen(path, mode);
dludwig@8477
   487
            SDL_stack_free(path);
dludwig@8477
   488
            if (fp) {
dludwig@8477
   489
                return SDL_RWFromFP(fp, 1);
dludwig@8477
   490
            }
dludwig@8477
   491
        }
dludwig@8477
   492
    }
dludwig@8477
   493
#endif /* HAVE_STDIO_H */
dludwig@8477
   494
dludwig@8477
   495
    /* Try to open the file from the asset system */
dludwig@8477
   496
    rwops = SDL_AllocRW();
dludwig@8477
   497
    if (!rwops)
dludwig@8477
   498
        return NULL;            /* SDL_SetError already setup by SDL_AllocRW() */
dludwig@8477
   499
    if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
dludwig@8477
   500
        SDL_FreeRW(rwops);
dludwig@8477
   501
        return NULL;
dludwig@8477
   502
    }
dludwig@8477
   503
    rwops->size = Android_JNI_FileSize;
dludwig@8477
   504
    rwops->seek = Android_JNI_FileSeek;
dludwig@8477
   505
    rwops->read = Android_JNI_FileRead;
dludwig@8477
   506
    rwops->write = Android_JNI_FileWrite;
dludwig@8477
   507
    rwops->close = Android_JNI_FileClose;
dludwig@8477
   508
    rwops->type = SDL_RWOPS_JNIFILE;
dludwig@8477
   509
dludwig@8477
   510
#elif defined(__WIN32__)
dludwig@8477
   511
    rwops = SDL_AllocRW();
dludwig@8477
   512
    if (!rwops)
dludwig@8477
   513
        return NULL;            /* SDL_SetError already setup by SDL_AllocRW() */
dludwig@8477
   514
    if (windows_file_open(rwops, file, mode) < 0) {
dludwig@8477
   515
        SDL_FreeRW(rwops);
dludwig@8477
   516
        return NULL;
dludwig@8477
   517
    }
dludwig@8477
   518
    rwops->size = windows_file_size;
dludwig@8477
   519
    rwops->seek = windows_file_seek;
dludwig@8477
   520
    rwops->read = windows_file_read;
dludwig@8477
   521
    rwops->write = windows_file_write;
dludwig@8477
   522
    rwops->close = windows_file_close;
dludwig@8477
   523
    rwops->type = SDL_RWOPS_WINFILE;
dludwig@8477
   524
dludwig@8477
   525
#elif HAVE_STDIO_H
dludwig@8477
   526
    {
dludwig@8477
   527
        #ifdef __APPLE__
dludwig@8477
   528
        FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode);
dludwig@8477
   529
        #elif __WINRT__
dludwig@8477
   530
        FILE *fp = NULL;
dludwig@8477
   531
        fopen_s(&fp, file, mode);
dludwig@8477
   532
        #else
dludwig@8477
   533
        FILE *fp = fopen(file, mode);
dludwig@8477
   534
        #endif
dludwig@8477
   535
        if (fp == NULL) {
dludwig@8477
   536
            SDL_SetError("Couldn't open %s", file);
dludwig@8477
   537
        } else {
dludwig@8477
   538
            rwops = SDL_RWFromFP(fp, 1);
dludwig@8477
   539
        }
dludwig@8477
   540
    }
dludwig@8477
   541
#else
dludwig@8477
   542
    SDL_SetError("SDL not compiled with stdio support");
dludwig@8477
   543
#endif /* !HAVE_STDIO_H */
dludwig@8477
   544
dludwig@8477
   545
    return (rwops);
dludwig@8477
   546
}
dludwig@8477
   547
dludwig@8477
   548
#ifdef HAVE_STDIO_H
dludwig@8477
   549
SDL_RWops *
dludwig@8477
   550
SDL_RWFromFP(FILE * fp, SDL_bool autoclose)
dludwig@8477
   551
{
dludwig@8477
   552
    SDL_RWops *rwops = NULL;
dludwig@8477
   553
dludwig@8477
   554
    rwops = SDL_AllocRW();
dludwig@8477
   555
    if (rwops != NULL) {
dludwig@8477
   556
        rwops->size = stdio_size;
dludwig@8477
   557
        rwops->seek = stdio_seek;
dludwig@8477
   558
        rwops->read = stdio_read;
dludwig@8477
   559
        rwops->write = stdio_write;
dludwig@8477
   560
        rwops->close = stdio_close;
dludwig@8477
   561
        rwops->hidden.stdio.fp = fp;
dludwig@8477
   562
        rwops->hidden.stdio.autoclose = autoclose;
dludwig@8477
   563
        rwops->type = SDL_RWOPS_STDFILE;
dludwig@8477
   564
    }
dludwig@8477
   565
    return (rwops);
dludwig@8477
   566
}
dludwig@8477
   567
#else
dludwig@8477
   568
SDL_RWops *
dludwig@8477
   569
SDL_RWFromFP(void * fp, SDL_bool autoclose)
dludwig@8477
   570
{
dludwig@8477
   571
    SDL_SetError("SDL not compiled with stdio support");
dludwig@8477
   572
    return NULL;
dludwig@8477
   573
}
dludwig@8477
   574
#endif /* HAVE_STDIO_H */
dludwig@8477
   575
dludwig@8477
   576
SDL_RWops *
dludwig@8477
   577
SDL_RWFromMem(void *mem, int size)
dludwig@8477
   578
{
dludwig@8477
   579
    SDL_RWops *rwops = NULL;
dludwig@8477
   580
    if (!mem) {
dludwig@8477
   581
      SDL_InvalidParamError("mem");
dludwig@8477
   582
      return (rwops);
dludwig@8477
   583
    }
dludwig@8477
   584
    if (!size) {
dludwig@8477
   585
      SDL_InvalidParamError("size");
dludwig@8477
   586
      return (rwops);
dludwig@8477
   587
    }
dludwig@8477
   588
dludwig@8477
   589
    rwops = SDL_AllocRW();
dludwig@8477
   590
    if (rwops != NULL) {
dludwig@8477
   591
        rwops->size = mem_size;
dludwig@8477
   592
        rwops->seek = mem_seek;
dludwig@8477
   593
        rwops->read = mem_read;
dludwig@8477
   594
        rwops->write = mem_write;
dludwig@8477
   595
        rwops->close = mem_close;
dludwig@8477
   596
        rwops->hidden.mem.base = (Uint8 *) mem;
dludwig@8477
   597
        rwops->hidden.mem.here = rwops->hidden.mem.base;
dludwig@8477
   598
        rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
dludwig@8477
   599
        rwops->type = SDL_RWOPS_MEMORY;
dludwig@8477
   600
    }
dludwig@8477
   601
    return (rwops);
dludwig@8477
   602
}
dludwig@8477
   603
dludwig@8477
   604
SDL_RWops *
dludwig@8477
   605
SDL_RWFromConstMem(const void *mem, int size)
dludwig@8477
   606
{
dludwig@8477
   607
    SDL_RWops *rwops = NULL;
dludwig@8477
   608
    if (!mem) {
dludwig@8477
   609
      SDL_InvalidParamError("mem");
dludwig@8477
   610
      return (rwops);
dludwig@8477
   611
    }
dludwig@8477
   612
    if (!size) {
dludwig@8477
   613
      SDL_InvalidParamError("size");
dludwig@8477
   614
      return (rwops);
dludwig@8477
   615
    }
dludwig@8477
   616
dludwig@8477
   617
    rwops = SDL_AllocRW();
dludwig@8477
   618
    if (rwops != NULL) {
dludwig@8477
   619
        rwops->size = mem_size;
dludwig@8477
   620
        rwops->seek = mem_seek;
dludwig@8477
   621
        rwops->read = mem_read;
dludwig@8477
   622
        rwops->write = mem_writeconst;
dludwig@8477
   623
        rwops->close = mem_close;
dludwig@8477
   624
        rwops->hidden.mem.base = (Uint8 *) mem;
dludwig@8477
   625
        rwops->hidden.mem.here = rwops->hidden.mem.base;
dludwig@8477
   626
        rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
dludwig@8477
   627
        rwops->type = SDL_RWOPS_MEMORY_RO;
dludwig@8477
   628
    }
dludwig@8477
   629
    return (rwops);
dludwig@8477
   630
}
dludwig@8477
   631
dludwig@8477
   632
SDL_RWops *
dludwig@8477
   633
SDL_AllocRW(void)
dludwig@8477
   634
{
dludwig@8477
   635
    SDL_RWops *area;
dludwig@8477
   636
dludwig@8477
   637
    area = (SDL_RWops *) SDL_malloc(sizeof *area);
dludwig@8477
   638
    if (area == NULL) {
dludwig@8477
   639
        SDL_OutOfMemory();
dludwig@8477
   640
    } else {
dludwig@8477
   641
        area->type = SDL_RWOPS_UNKNOWN;
dludwig@8477
   642
    }
dludwig@8477
   643
    return (area);
dludwig@8477
   644
}
dludwig@8477
   645
dludwig@8477
   646
void
dludwig@8477
   647
SDL_FreeRW(SDL_RWops * area)
dludwig@8477
   648
{
dludwig@8477
   649
    SDL_free(area);
dludwig@8477
   650
}
dludwig@8477
   651
dludwig@8477
   652
/* Functions for dynamically reading and writing endian-specific values */
dludwig@8477
   653
dludwig@8477
   654
Uint8
dludwig@8477
   655
SDL_ReadU8(SDL_RWops * src)
dludwig@8477
   656
{
dludwig@8477
   657
    Uint8 value = 0;
dludwig@8477
   658
dludwig@8477
   659
    SDL_RWread(src, &value, (sizeof value), 1);
dludwig@8477
   660
    return value;
dludwig@8477
   661
}
dludwig@8477
   662
dludwig@8477
   663
Uint16
dludwig@8477
   664
SDL_ReadLE16(SDL_RWops * src)
dludwig@8477
   665
{
dludwig@8477
   666
    Uint16 value = 0;
dludwig@8477
   667
dludwig@8477
   668
    SDL_RWread(src, &value, (sizeof value), 1);
dludwig@8477
   669
    return (SDL_SwapLE16(value));
dludwig@8477
   670
}
dludwig@8477
   671
dludwig@8477
   672
Uint16
dludwig@8477
   673
SDL_ReadBE16(SDL_RWops * src)
dludwig@8477
   674
{
dludwig@8477
   675
    Uint16 value = 0;
dludwig@8477
   676
dludwig@8477
   677
    SDL_RWread(src, &value, (sizeof value), 1);
dludwig@8477
   678
    return (SDL_SwapBE16(value));
dludwig@8477
   679
}
dludwig@8477
   680
dludwig@8477
   681
Uint32
dludwig@8477
   682
SDL_ReadLE32(SDL_RWops * src)
dludwig@8477
   683
{
dludwig@8477
   684
    Uint32 value = 0;
dludwig@8477
   685
dludwig@8477
   686
    SDL_RWread(src, &value, (sizeof value), 1);
dludwig@8477
   687
    return (SDL_SwapLE32(value));
dludwig@8477
   688
}
dludwig@8477
   689
dludwig@8477
   690
Uint32
dludwig@8477
   691
SDL_ReadBE32(SDL_RWops * src)
dludwig@8477
   692
{
dludwig@8477
   693
    Uint32 value = 0;
dludwig@8477
   694
dludwig@8477
   695
    SDL_RWread(src, &value, (sizeof value), 1);
dludwig@8477
   696
    return (SDL_SwapBE32(value));
dludwig@8477
   697
}
dludwig@8477
   698
dludwig@8477
   699
Uint64
dludwig@8477
   700
SDL_ReadLE64(SDL_RWops * src)
dludwig@8477
   701
{
dludwig@8477
   702
    Uint64 value = 0;
dludwig@8477
   703
dludwig@8477
   704
    SDL_RWread(src, &value, (sizeof value), 1);
dludwig@8477
   705
    return (SDL_SwapLE64(value));
dludwig@8477
   706
}
dludwig@8477
   707
dludwig@8477
   708
Uint64
dludwig@8477
   709
SDL_ReadBE64(SDL_RWops * src)
dludwig@8477
   710
{
dludwig@8477
   711
    Uint64 value = 0;
dludwig@8477
   712
dludwig@8477
   713
    SDL_RWread(src, &value, (sizeof value), 1);
dludwig@8477
   714
    return (SDL_SwapBE64(value));
dludwig@8477
   715
}
dludwig@8477
   716
dludwig@8477
   717
size_t
dludwig@8477
   718
SDL_WriteU8(SDL_RWops * dst, Uint8 value)
dludwig@8477
   719
{
dludwig@8477
   720
    return (SDL_RWwrite(dst, &value, (sizeof value), 1));
dludwig@8477
   721
}
dludwig@8477
   722
dludwig@8477
   723
size_t
dludwig@8477
   724
SDL_WriteLE16(SDL_RWops * dst, Uint16 value)
dludwig@8477
   725
{
dludwig@8477
   726
    value = SDL_SwapLE16(value);
dludwig@8477
   727
    return (SDL_RWwrite(dst, &value, (sizeof value), 1));
dludwig@8477
   728
}
dludwig@8477
   729
dludwig@8477
   730
size_t
dludwig@8477
   731
SDL_WriteBE16(SDL_RWops * dst, Uint16 value)
dludwig@8477
   732
{
dludwig@8477
   733
    value = SDL_SwapBE16(value);
dludwig@8477
   734
    return (SDL_RWwrite(dst, &value, (sizeof value), 1));
dludwig@8477
   735
}
dludwig@8477
   736
dludwig@8477
   737
size_t
dludwig@8477
   738
SDL_WriteLE32(SDL_RWops * dst, Uint32 value)
dludwig@8477
   739
{
dludwig@8477
   740
    value = SDL_SwapLE32(value);
dludwig@8477
   741
    return (SDL_RWwrite(dst, &value, (sizeof value), 1));
dludwig@8477
   742
}
dludwig@8477
   743
dludwig@8477
   744
size_t
dludwig@8477
   745
SDL_WriteBE32(SDL_RWops * dst, Uint32 value)
dludwig@8477
   746
{
dludwig@8477
   747
    value = SDL_SwapBE32(value);
dludwig@8477
   748
    return (SDL_RWwrite(dst, &value, (sizeof value), 1));
dludwig@8477
   749
}
dludwig@8477
   750
dludwig@8477
   751
size_t
dludwig@8477
   752
SDL_WriteLE64(SDL_RWops * dst, Uint64 value)
dludwig@8477
   753
{
dludwig@8477
   754
    value = SDL_SwapLE64(value);
dludwig@8477
   755
    return (SDL_RWwrite(dst, &value, (sizeof value), 1));
dludwig@8477
   756
}
dludwig@8477
   757
dludwig@8477
   758
size_t
dludwig@8477
   759
SDL_WriteBE64(SDL_RWops * dst, Uint64 value)
dludwig@8477
   760
{
dludwig@8477
   761
    value = SDL_SwapBE64(value);
dludwig@8477
   762
    return (SDL_RWwrite(dst, &value, (sizeof value), 1));
dludwig@8477
   763
}
dludwig@8477
   764
dludwig@8477
   765
/* vi: set ts=4 sw=4 expandtab: */