~ubuntu-branches/ubuntu/gutsy/pygame/gutsy

« back to all changes in this revision

Viewing changes to src/rwobject.c

  • Committer: Bazaar Package Importer
  • Author(s): Ed Boraas
  • Date: 2002-02-20 06:39:24 UTC
  • Revision ID: james.westby@ubuntu.com-20020220063924-amlzj7tqkeods4eq
Tags: upstream-1.4
ImportĀ upstreamĀ versionĀ 1.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    pygame - Python Game Library
 
3
    Copyright (C) 2000-2001  Pete Shinners
 
4
 
 
5
    This library is free software; you can redistribute it and/or
 
6
    modify it under the terms of the GNU Library General Public
 
7
    License as published by the Free Software Foundation; either
 
8
    version 2 of the License, or (at your option) any later version.
 
9
 
 
10
    This library is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
    Library General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU Library General Public
 
16
    License along with this library; if not, write to the Free
 
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
    Pete Shinners
 
20
    pete@shinners.org
 
21
*/
 
22
 
 
23
/*
 
24
 *  SDL_RWops support for python objects
 
25
 */
 
26
#define PYGAMEAPI_RWOBJECT_INTERNAL
 
27
#include "pygame.h"
 
28
 
 
29
 
 
30
typedef struct
 
31
{
 
32
        PyObject* read;
 
33
        PyObject* write;
 
34
        PyObject* seek;
 
35
        PyObject* tell;
 
36
        PyObject* close;
 
37
#ifdef WITH_THREAD
 
38
        PyThreadState* thread;
 
39
#endif
 
40
}RWHelper;
 
41
 
 
42
 
 
43
static int rw_seek(SDL_RWops* context, int offset, int whence);
 
44
static int rw_read(SDL_RWops* context, void* ptr, int size, int maxnum);
 
45
static int rw_write(SDL_RWops* context, const void* ptr, int size, int maxnum);
 
46
static int rw_close(SDL_RWops* context);
 
47
 
 
48
#ifdef WITH_THREAD
 
49
static int rw_seek_th(SDL_RWops* context, int offset, int whence);
 
50
static int rw_read_th(SDL_RWops* context, void* ptr, int size, int maxnum);
 
51
static int rw_write_th(SDL_RWops* context, const void* ptr, int size, int maxnum);
 
52
static int rw_close_th(SDL_RWops* context);
 
53
#endif
 
54
 
 
55
 
 
56
static SDL_RWops* get_standard_rwop(PyObject* obj)
 
57
{
 
58
        if(PyString_Check(obj) || PyUnicode_Check(obj))
 
59
        {
 
60
                int result;
 
61
                char* name;
 
62
                PyObject* tuple = PyTuple_New(1);
 
63
                PyTuple_SET_ITEM(tuple, 0, obj);
 
64
                Py_INCREF(obj);
 
65
                if(!tuple) return NULL;
 
66
                result = PyArg_ParseTuple(tuple, "s", &name);
 
67
                Py_DECREF(tuple);
 
68
                if(!result)
 
69
                        return NULL;
 
70
                return SDL_RWFromFile(name, "rb");
 
71
        }
 
72
        else if(PyFile_Check(obj))
 
73
                return SDL_RWFromFP(PyFile_AsFile(obj), 1);
 
74
 
 
75
        return NULL;
 
76
}
 
77
 
 
78
static void fetch_object_methods(RWHelper* helper, PyObject* obj)
 
79
{
 
80
        helper->read = helper->write = helper->seek =
 
81
                                helper->tell = helper->close = NULL;
 
82
        if(PyObject_HasAttrString(obj, "read"))
 
83
        {
 
84
                helper->read = PyObject_GetAttrString(obj, "read");
 
85
                if(helper->read && !PyCallable_Check(helper->read))
 
86
                        helper->read = NULL;
 
87
        }
 
88
        if(PyObject_HasAttrString(obj, "write"))
 
89
        {
 
90
                helper->write = PyObject_GetAttrString(obj, "write");
 
91
                if(helper->write && !PyCallable_Check(helper->write))
 
92
                        helper->write = NULL;
 
93
        }
 
94
        if(PyObject_HasAttrString(obj, "seek"))
 
95
        {
 
96
                helper->seek = PyObject_GetAttrString(obj, "seek");
 
97
                if(helper->seek && !PyCallable_Check(helper->seek))
 
98
                        helper->seek = NULL;
 
99
        }
 
100
        if(PyObject_HasAttrString(obj, "tell"))
 
101
        {
 
102
                helper->tell = PyObject_GetAttrString(obj, "tell");
 
103
                if(helper->tell && !PyCallable_Check(helper->tell))
 
104
                        helper->tell = NULL;
 
105
        }
 
106
        if(PyObject_HasAttrString(obj, "close"))
 
107
        {
 
108
                helper->close = PyObject_GetAttrString(obj, "close");
 
109
                if(helper->close && !PyCallable_Check(helper->close))
 
110
                        helper->close = NULL;
 
111
        }
 
112
}
 
113
 
 
114
 
 
115
static SDL_RWops* RWopsFromPython(PyObject* obj)
 
116
{
 
117
        SDL_RWops* rw;
 
118
        RWHelper* helper;
 
119
 
 
120
        if(!obj)
 
121
                return (SDL_RWops*)RAISE(PyExc_TypeError, "Invalid filetype object");
 
122
        rw = get_standard_rwop(obj);
 
123
        if(rw) return rw;
 
124
 
 
125
 
 
126
        helper = PyMem_New(RWHelper, 1);
 
127
        fetch_object_methods(helper, obj);
 
128
 
 
129
        rw = SDL_AllocRW();
 
130
        rw->hidden.unknown.data1 = (void*)helper;
 
131
        rw->seek = rw_seek;
 
132
        rw->read = rw_read;
 
133
        rw->write = rw_write;
 
134
        rw->close = rw_close;
 
135
 
 
136
        return rw;
 
137
}
 
138
 
 
139
 
 
140
static int RWopsCheckPython(SDL_RWops* rw)
 
141
{
 
142
        return rw->close == rw_close;
 
143
}
 
144
 
 
145
 
 
146
static int rw_seek(SDL_RWops* context, int offset, int whence)
 
147
{
 
148
        RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
 
149
        PyObject* result;
 
150
        int retval;
 
151
 
 
152
        if(!helper->seek || !helper->tell)
 
153
                return -1;
 
154
 
 
155
        if(!(offset == 0 && whence == SEEK_CUR)) /*being called only for 'tell'*/
 
156
        {
 
157
                result = PyObject_CallFunction(helper->seek, "ii", offset, whence);
 
158
                if(!result)
 
159
                        return -1;
 
160
                Py_DECREF(result);
 
161
        }
 
162
 
 
163
        result = PyObject_CallFunction(helper->tell, NULL);
 
164
        if(!result)
 
165
                return -1;
 
166
 
 
167
        retval = PyInt_AsLong(result);
 
168
        Py_DECREF(result);
 
169
 
 
170
        return retval;
 
171
}
 
172
 
 
173
 
 
174
static int rw_read(SDL_RWops* context, void* ptr, int size, int maxnum)
 
175
{
 
176
        RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
 
177
        PyObject* result;
 
178
        int retval;
 
179
 
 
180
        if(!helper->read)
 
181
                return -1;
 
182
 
 
183
        result = PyObject_CallFunction(helper->read, "i", size * maxnum);
 
184
        if(!result)
 
185
                return -1;
 
186
                
 
187
        if(!PyString_Check(result))
 
188
        {
 
189
                Py_DECREF(result);
 
190
                return -1;
 
191
        }
 
192
                
 
193
        retval = PyString_GET_SIZE(result);
 
194
        memcpy(ptr, PyString_AsString(result), retval);
 
195
        retval /= size;
 
196
 
 
197
        Py_DECREF(result);
 
198
        return retval;
 
199
}
 
200
 
 
201
 
 
202
static int rw_write(SDL_RWops* context, const void* ptr, int size, int num)
 
203
{
 
204
        RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
 
205
        PyObject* result;
 
206
 
 
207
        if(!helper->write)
 
208
                return -1;
 
209
 
 
210
        result = PyObject_CallFunction(helper->write, "s#", ptr, size * num);
 
211
        if(!result)
 
212
                return -1;
 
213
 
 
214
        Py_DECREF(result);
 
215
        return num;
 
216
}
 
217
 
 
218
 
 
219
static int rw_close(SDL_RWops* context)
 
220
{
 
221
        RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
 
222
        PyObject* result;
 
223
        int retval = 0;
 
224
 
 
225
        if(helper->close)
 
226
        {
 
227
                result = PyObject_CallFunction(helper->close, NULL);
 
228
                if(result)
 
229
                        retval = -1;
 
230
                Py_XDECREF(result);
 
231
        }
 
232
 
 
233
        Py_XDECREF(helper->seek);
 
234
        Py_XDECREF(helper->tell);
 
235
        Py_XDECREF(helper->write);
 
236
        Py_XDECREF(helper->read);
 
237
        Py_XDECREF(helper->close);
 
238
        PyMem_Del(helper);
 
239
        SDL_FreeRW(context);
 
240
        return retval;
 
241
}
 
242
 
 
243
 
 
244
 
 
245
 
 
246
 
 
247
 
 
248
static SDL_RWops* RWopsFromPythonThreaded(PyObject* obj)
 
249
{
 
250
        SDL_RWops* rw;
 
251
        RWHelper* helper;
 
252
        PyInterpreterState* interp;
 
253
        PyThreadState* thread;
 
254
    
 
255
        if(!obj)
 
256
                return (SDL_RWops*)RAISE(PyExc_TypeError, "Invalid filetype object");
 
257
 
 
258
        rw = get_standard_rwop(obj);
 
259
        if(rw)
 
260
                return rw;
 
261
        
 
262
#ifndef WITH_THREAD
 
263
        return (SDL_RWops*)RAISE(PyExc_NotImplementedError, "Python built without thread support");
 
264
#else
 
265
        helper = PyMem_New(RWHelper, 1);
 
266
        fetch_object_methods(helper, obj);
 
267
        
 
268
        rw = SDL_AllocRW();
 
269
        rw->hidden.unknown.data1 = (void*)helper;
 
270
        rw->seek = rw_seek_th;
 
271
        rw->read = rw_read_th;
 
272
        rw->write = rw_write_th;
 
273
        rw->close = rw_close_th;
 
274
 
 
275
        PyEval_InitThreads();
 
276
        thread = PyThreadState_Get();
 
277
        interp = thread->interp;
 
278
        helper->thread = PyThreadState_New(interp);
 
279
 
 
280
        return rw;
 
281
#endif
 
282
}
 
283
 
 
284
 
 
285
static int RWopsCheckPythonThreaded(SDL_RWops* rw)
 
286
{
 
287
#ifdef WITH_THREAD
 
288
        return rw->close == rw_close_th;
 
289
#else
 
290
        return 0;
 
291
#endif
 
292
}
 
293
 
 
294
#ifdef WITH_THREAD
 
295
static int rw_seek_th(SDL_RWops* context, int offset, int whence)
 
296
{
 
297
        RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
 
298
        PyObject* result;
 
299
        int retval;
 
300
        PyThreadState* oldstate;
 
301
 
 
302
        if(!helper->seek || !helper->tell)
 
303
                return -1;
 
304
 
 
305
        PyEval_AcquireLock();
 
306
        oldstate = PyThreadState_Swap(helper->thread);
 
307
        
 
308
        if(!(offset == 0 && whence == SEEK_CUR)) /*being called only for 'tell'*/
 
309
        {
 
310
                result = PyObject_CallFunction(helper->seek, "ii", offset, whence);
 
311
                if(!result)
 
312
                        return -1;
 
313
                Py_DECREF(result);
 
314
        }
 
315
 
 
316
        result = PyObject_CallFunction(helper->tell, NULL);
 
317
        if(!result)
 
318
                return -1;
 
319
 
 
320
        retval = PyInt_AsLong(result);
 
321
        Py_DECREF(result);
 
322
 
 
323
        PyThreadState_Swap(oldstate);
 
324
        PyEval_ReleaseLock();
 
325
        
 
326
        return retval;
 
327
}
 
328
 
 
329
 
 
330
static int rw_read_th(SDL_RWops* context, void* ptr, int size, int maxnum)
 
331
{
 
332
        RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
 
333
        PyObject* result;
 
334
        int retval;
 
335
        PyThreadState* oldstate;
 
336
 
 
337
        if(!helper->read)
 
338
                return -1;
 
339
 
 
340
        PyEval_AcquireLock();
 
341
        oldstate = PyThreadState_Swap(helper->thread);
 
342
        
 
343
        result = PyObject_CallFunction(helper->read, "i", size * maxnum);
 
344
        if(!result)
 
345
                return -1;
 
346
                
 
347
        if(!PyString_Check(result))
 
348
        {
 
349
                Py_DECREF(result);
 
350
                return -1;
 
351
        }
 
352
                
 
353
        retval = PyString_GET_SIZE(result);
 
354
        memcpy(ptr, PyString_AsString(result), retval);
 
355
        retval /= size;
 
356
 
 
357
        Py_DECREF(result);
 
358
 
 
359
        PyThreadState_Swap(oldstate);
 
360
        PyEval_ReleaseLock();
 
361
        
 
362
        return retval;
 
363
}
 
364
 
 
365
 
 
366
static int rw_write_th(SDL_RWops* context, const void* ptr, int size, int num)
 
367
{
 
368
        RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
 
369
        PyObject* result;
 
370
        PyThreadState* oldstate;
 
371
   
 
372
        if(!helper->write)
 
373
                return -1;
 
374
 
 
375
        PyEval_AcquireLock();
 
376
        oldstate = PyThreadState_Swap(helper->thread);
 
377
        
 
378
        result = PyObject_CallFunction(helper->write, "s#", ptr, size * num);
 
379
        if(!result)
 
380
                return -1;
 
381
 
 
382
        Py_DECREF(result);
 
383
 
 
384
        PyThreadState_Swap(oldstate);
 
385
        PyEval_ReleaseLock();
 
386
        
 
387
        return num;
 
388
}
 
389
 
 
390
 
 
391
static int rw_close_th(SDL_RWops* context)
 
392
{
 
393
        RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
 
394
        PyObject* result;
 
395
        int retval = 0;
 
396
        PyThreadState* oldstate;
 
397
    
 
398
        PyEval_AcquireLock();
 
399
        oldstate = PyThreadState_Swap(helper->thread);
 
400
        
 
401
        if(helper->close)
 
402
        {
 
403
                result = PyObject_CallFunction(helper->close, NULL);
 
404
                if(result)
 
405
                        retval = -1;
 
406
                Py_XDECREF(result);
 
407
        }
 
408
 
 
409
        Py_XDECREF(helper->seek);
 
410
        Py_XDECREF(helper->tell);
 
411
        Py_XDECREF(helper->write);
 
412
        Py_XDECREF(helper->read);
 
413
        Py_XDECREF(helper->close);
 
414
        PyMem_Del(helper);
 
415
 
 
416
        PyThreadState_Swap(oldstate);
 
417
        PyThreadState_Clear(helper->thread);
 
418
        PyThreadState_Delete(helper->thread);
 
419
        PyEval_ReleaseLock();
 
420
        
 
421
        SDL_FreeRW(context);
 
422
        return retval;
 
423
}
 
424
#endif
 
425
 
 
426
 
 
427
 
 
428
static PyMethodDef rwobject__builtins__[] =
 
429
{
 
430
        {NULL, NULL}
 
431
};
 
432
 
 
433
 
 
434
 
 
435
PYGAME_EXPORT
 
436
void initrwobject(void)
 
437
{
 
438
        PyObject *module, *dict, *apiobj;
 
439
        static void* c_api[PYGAMEAPI_RWOBJECT_NUMSLOTS];
 
440
 
 
441
        PyGAME_C_API[0] = PyGAME_C_API[0]; /*this cleans a compiler warning*/
 
442
 
 
443
        /* Create the module and add the functions */
 
444
        module = Py_InitModule3("rwobject", rwobject__builtins__, "SDL_RWops support");
 
445
        dict = PyModule_GetDict(module);
 
446
 
 
447
        /* export the c api */
 
448
        c_api[0] = RWopsFromPython;
 
449
        c_api[1] = RWopsCheckPython;
 
450
        c_api[2] = RWopsFromPythonThreaded;
 
451
        c_api[3] = RWopsCheckPythonThreaded;
 
452
        apiobj = PyCObject_FromVoidPtr(c_api, NULL);
 
453
        PyDict_SetItemString(dict, PYGAMEAPI_LOCAL_ENTRY, apiobj);
 
454
        Py_DECREF(apiobj);
 
455
}