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