extra_rwops.c
author Ozkan Sezer <sezero@users.sourceforge.net>
Wed, 24 May 2017 11:28:05 -0400
changeset 599 f0d57c9b72d8
parent 552 2e8907ff98e9
child 601 5b36839bb796
permissions -rw-r--r--
timidity.c: fix potential buffer overrun in RWgets

(num_read check was off-by-one.) also simplify the procedure a bit.
(transplanted from 0c4026dd32742e8b7d33fb96d40fe3c03b02f90c)
icculus@8
     1
/*
icculus@8
     2
 * SDL_sound -- An abstract sound format decoding API.
icculus@8
     3
 * Copyright (C) 2001  Ryan C. Gordon.
icculus@8
     4
 *
icculus@8
     5
 * This library is free software; you can redistribute it and/or
icculus@8
     6
 * modify it under the terms of the GNU Lesser General Public
icculus@8
     7
 * License as published by the Free Software Foundation; either
icculus@8
     8
 * version 2.1 of the License, or (at your option) any later version.
icculus@8
     9
 *
icculus@8
    10
 * This library is distributed in the hope that it will be useful,
icculus@8
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
icculus@8
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
icculus@8
    13
 * Lesser General Public License for more details.
icculus@8
    14
 *
icculus@8
    15
 * You should have received a copy of the GNU Lesser General Public
icculus@8
    16
 * License along with this library; if not, write to the Free Software
icculus@8
    17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
icculus@8
    18
 */
icculus@8
    19
icculus@8
    20
/*
icculus@8
    21
 * Some extra RWops that are needed or are just handy to have.
icculus@8
    22
 *
icculus@552
    23
 * Please see the file LICENSE.txt in the source's root directory.
icculus@8
    24
 *
icculus@526
    25
 *  This file written by Ryan C. Gordon. (icculus@icculus.org)
icculus@8
    26
 */
icculus@8
    27
icculus@8
    28
#include <stdio.h>
icculus@8
    29
#include <stdlib.h>
icculus@8
    30
#include "SDL.h"
icculus@8
    31
icculus@8
    32
icculus@8
    33
    /*
icculus@8
    34
     * The Reference Counter RWops...
icculus@8
    35
     */
icculus@8
    36
icculus@8
    37
icculus@8
    38
typedef struct
icculus@8
    39
{
icculus@8
    40
    SDL_RWops *rw;  /* The actual RWops we're refcounting... */
icculus@8
    41
    int refcount;   /* The refcount; starts at 1. If goes to 0, delete. */
icculus@8
    42
} RWRefCounterData;
icculus@8
    43
icculus@8
    44
icculus@8
    45
/* Just pass through to the actual SDL_RWops's method... */
icculus@8
    46
static int refcounter_seek(SDL_RWops *rw, int offset, int whence)
icculus@8
    47
{
icculus@8
    48
    RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
icculus@8
    49
    return(data->rw->seek(data->rw, offset, whence));
icculus@8
    50
} /* refcounter_seek */
icculus@8
    51
icculus@8
    52
icculus@8
    53
/* Just pass through to the actual SDL_RWops's method... */
icculus@8
    54
static int refcounter_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
icculus@8
    55
{
icculus@8
    56
    RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
icculus@8
    57
    return(data->rw->read(data->rw, ptr, size, maxnum));
icculus@8
    58
} /* refcounter_read */
icculus@8
    59
icculus@8
    60
icculus@8
    61
/* Just pass through to the actual SDL_RWops's method... */
icculus@8
    62
static int refcounter_write(SDL_RWops *rw, const void *ptr, int size, int num)
icculus@8
    63
{
icculus@8
    64
    RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
icculus@8
    65
    return(data->rw->write(data->rw, ptr, size, num));
icculus@8
    66
} /* refcounter_write */
icculus@8
    67
icculus@8
    68
icculus@8
    69
/*
icculus@8
    70
 * Decrement the reference count. If there are no more references, pass
icculus@8
    71
 *   through to the actual SDL_RWops's method, and then clean ourselves up.
icculus@8
    72
 */
icculus@8
    73
static int refcounter_close(SDL_RWops *rw)
icculus@8
    74
{
icculus@8
    75
    int retval = 0;
icculus@8
    76
    RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
icculus@8
    77
    data->refcount--;
icculus@8
    78
    if (data->refcount <= 0)
icculus@8
    79
    {
icculus@8
    80
        retval = data->rw->close(data->rw);
icculus@8
    81
        free(data);
icculus@8
    82
        SDL_FreeRW(rw);
icculus@8
    83
    } /* if */
icculus@8
    84
icculus@8
    85
    return(retval);
icculus@8
    86
} /* refcounter_close */
icculus@8
    87
icculus@8
    88
icculus@8
    89
void RWops_RWRefCounter_addRef(SDL_RWops *rw)
icculus@8
    90
{
icculus@8
    91
    RWRefCounterData *data = (RWRefCounterData *) rw->hidden.unknown.data1;
icculus@8
    92
    data->refcount++;
icculus@8
    93
} /* RWops_RWRefCounter_addRef */
icculus@8
    94
icculus@8
    95
icculus@8
    96
SDL_RWops *RWops_RWRefCounter_new(SDL_RWops *rw)
icculus@8
    97
{
icculus@8
    98
    SDL_RWops *retval = NULL;
icculus@8
    99
icculus@8
   100
    if (rw == NULL)
icculus@8
   101
    {
icculus@8
   102
        SDL_SetError("NULL argument to RWops_RWRefCounter_new().");
icculus@8
   103
        return(NULL);
icculus@8
   104
    } /* if */
icculus@8
   105
icculus@8
   106
    retval = SDL_AllocRW();
icculus@8
   107
    if (retval != NULL)
icculus@8
   108
    {
icculus@8
   109
        RWRefCounterData *data;
icculus@8
   110
        data = (RWRefCounterData *) malloc(sizeof (RWRefCounterData));
icculus@8
   111
        if (data == NULL)
icculus@8
   112
        {
icculus@83
   113
            SDL_SetError("Out of memory.");
icculus@8
   114
            SDL_FreeRW(retval);
icculus@8
   115
            retval = NULL;
icculus@8
   116
        } /* if */
icculus@8
   117
        else
icculus@8
   118
        {
icculus@8
   119
            data->rw = rw;
icculus@8
   120
            data->refcount = 1;
icculus@8
   121
            retval->hidden.unknown.data1 = data;
icculus@8
   122
            retval->seek = refcounter_seek;
icculus@8
   123
            retval->read = refcounter_read;
icculus@8
   124
            retval->write = refcounter_write;
icculus@8
   125
            retval->close = refcounter_close;
icculus@8
   126
        } /* else */
icculus@8
   127
    } /* if */
icculus@8
   128
icculus@8
   129
    return(retval);
icculus@8
   130
} /* RWops_RWRefCounter_new */
icculus@8
   131
icculus@8
   132
icculus@485
   133
icculus@485
   134
    /*
icculus@485
   135
     * RWops pooling...
icculus@485
   136
     */
icculus@485
   137
icculus@485
   138
static SDL_RWops *rwops_pool = NULL;
icculus@485
   139
static SDL_mutex *rwops_pool_mutex = NULL;
icculus@485
   140
icculus@491
   141
SDL_RWops *RWops_pooled_alloc(void)
icculus@491
   142
{
icculus@491
   143
    SDL_RWops *rw;
icculus@491
   144
    if (rwops_pool_mutex == NULL)
icculus@491
   145
        return(NULL);  /* never initialized. */
icculus@491
   146
icculus@491
   147
    SDL_LockMutex(rwops_pool_mutex);
icculus@491
   148
    rw = rwops_pool;
icculus@491
   149
    if (rw)
icculus@491
   150
        rwops_pool = (SDL_RWops *) (rw->hidden.unknown.data1);
icculus@491
   151
    SDL_UnlockMutex(rwops_pool_mutex);
icculus@491
   152
icculus@491
   153
    if (!rw)
icculus@491
   154
        rw = (SDL_RWops *) malloc(sizeof (SDL_RWops));
icculus@491
   155
icculus@491
   156
    return(rw);
icculus@491
   157
} /* RWops_pooled_alloc */
icculus@491
   158
icculus@491
   159
icculus@491
   160
void RWops_pooled_free(SDL_RWops *rw)
icculus@491
   161
{
icculus@491
   162
    if (rwops_pool_mutex == NULL)
icculus@491
   163
        return;  /* never initialized...why are we here? */
icculus@491
   164
icculus@491
   165
    if (rw == NULL)
icculus@491
   166
        return;
icculus@491
   167
icculus@491
   168
    SDL_LockMutex(rwops_pool_mutex);
icculus@491
   169
    rw->hidden.unknown.data1 = rwops_pool;
icculus@491
   170
    rwops_pool = rw;
icculus@491
   171
    SDL_UnlockMutex(rwops_pool_mutex);
icculus@491
   172
} /* RWops_pooled_free */
icculus@491
   173
icculus@491
   174
icculus@485
   175
int RWops_pooled_init(void)
icculus@485
   176
{
icculus@485
   177
    const int preallocate = 50;
icculus@485
   178
    int i;
icculus@485
   179
icculus@485
   180
    rwops_pool_mutex = SDL_CreateMutex();
icculus@485
   181
    if (rwops_pool_mutex == NULL)
icculus@485
   182
        return(0);
icculus@485
   183
icculus@485
   184
    for (i = 0; i < preallocate; i++)
icculus@490
   185
        RWops_pooled_free(RWops_pooled_alloc());
icculus@485
   186
icculus@485
   187
    return(1);
icculus@485
   188
} /* RWops_pooled_init */
icculus@485
   189
icculus@485
   190
icculus@485
   191
void RWops_pooled_deinit(void)
icculus@485
   192
{
icculus@485
   193
    SDL_RWops *cur;
icculus@485
   194
    SDL_RWops *next;
icculus@485
   195
icculus@485
   196
    if (rwops_pool_mutex == NULL)
icculus@485
   197
        return;  /* never initialized. */
icculus@485
   198
icculus@485
   199
    SDL_LockMutex(rwops_pool_mutex);
icculus@485
   200
    /* all allocated rwops must be in the pool now, or the memory leaks. */
icculus@485
   201
    cur = rwops_pool;
icculus@485
   202
    rwops_pool = NULL;
icculus@485
   203
    SDL_UnlockMutex(rwops_pool_mutex);
icculus@485
   204
    SDL_DestroyMutex(rwops_pool_mutex);
icculus@485
   205
    rwops_pool_mutex = NULL;
icculus@485
   206
icculus@485
   207
    while (cur)
icculus@485
   208
    {
icculus@485
   209
        next = (SDL_RWops *) (cur->hidden.unknown.data1);
icculus@485
   210
        free(cur);
icculus@485
   211
        cur = next;
icculus@485
   212
    } /* while */
icculus@485
   213
} /* RWops_pooled_deinit */
icculus@485
   214
icculus@8
   215
/* end of extra_rwops.c ... */
icculus@8
   216
icculus@8
   217