Mercurial > pygame
annotate src/bufferproxy.c @ 1137:ec3ced33488f
Reworked locking code to be more strict about locking.
Added Surface.get_locks() method.
| author | marcus |
|---|---|
| date | Mon, 16 Jun 2008 18:46:56 +0000 |
| parents | 3cc4c037f5ef |
| children | c0d170c1e636 134f8fe8d639 |
| rev | line source |
|---|---|
| 860 | 1 /* |
| 2 pygame - Python Game Library | |
| 3 Copyright (C) 2007 Marcus von Appen | |
| 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 */ | |
| 20 | |
| 21 #define PYGAMEAPI_BUFFERPROXY_INTERNAL | |
| 22 | |
| 23 #include "pygame.h" | |
| 24 #include "pygamedocs.h" | |
| 25 | |
| 26 static PyObject* _bufferproxy_new (PyTypeObject *type, PyObject *args, | |
| 27 PyObject *kwds); | |
| 28 static void _bufferproxy_dealloc (PyBufferProxy *self); | |
| 29 static PyObject* _bufferproxy_get_dict (PyBufferProxy *self, void *closure); | |
|
898
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
30 static PyObject* _bufferproxy_get_raw (PyBufferProxy *self, void *closure); |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
31 static PyObject* _bufferproxy_get_length (PyBufferProxy *self, void *closure); |
| 860 | 32 static PyObject* _bufferproxy_repr (PyBufferProxy *self); |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
33 static PyObject* _bufferproxy_write (PyBufferProxy *buffer, PyObject *args); |
| 860 | 34 |
| 35 /* Buffer methods */ | |
| 36 static Py_ssize_t _bufferproxy_getreadbuf (PyBufferProxy *buffer, | |
| 37 Py_ssize_t _index, | |
| 38 const void **ptr); | |
| 39 static Py_ssize_t _bufferproxy_getwritebuf (PyBufferProxy *buffer, | |
| 40 Py_ssize_t _index, | |
| 41 const void **ptr); | |
| 42 static Py_ssize_t _bufferproxy_getsegcount (PyBufferProxy *buffer, | |
| 43 Py_ssize_t *lenp); | |
| 44 | |
| 45 /* C API interfaces */ | |
| 46 static PyObject* PyBufferProxy_New (PyObject *parent, void *buffer, | |
| 47 Py_ssize_t length, PyObject *lock); | |
| 48 | |
| 49 /** | |
| 50 * Methods, which are bound to the PyBufferProxy type. | |
| 51 */ | |
| 52 static PyMethodDef _bufferproxy_methods[] = | |
| 53 { | |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
54 { "write", (PyCFunction) _bufferproxy_write, METH_VARARGS, |
| 906 | 55 "B.write (bufferproxy, buffer, offset) -> None\n\n" \ |
| 56 "Writes raw data to the bufferproxy.\n\n" \ | |
| 57 "Writes the raw data from buffer to the BufferProxy object, starting\n" \ | |
| 58 "at the specified offset within the BufferProxy.\n" \ | |
| 59 "If the length of the passed buffer exceeds the length of the\n" \ | |
| 60 "BufferProxy (reduced by the offset), an IndexError will be raised." }, | |
| 860 | 61 { NULL, NULL, 0, NULL } |
| 62 }; | |
| 63 | |
| 64 /** | |
| 65 * Getters and setters for the PyBufferProxy. | |
| 66 */ | |
| 67 static PyGetSetDef _bufferproxy_getsets[] = | |
| 68 { | |
| 69 { "__dict__", (getter) _bufferproxy_get_dict, NULL, NULL, NULL }, | |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
70 { "raw", (getter) _bufferproxy_get_raw, NULL, |
| 906 | 71 "The raw buffer data as string. The string may contain NUL bytes.", |
| 72 NULL }, | |
|
898
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
73 { "length", (getter) _bufferproxy_get_length, NULL, |
| 906 | 74 "The size of the buffer data in bytes.", NULL }, |
| 860 | 75 { NULL, NULL, NULL, NULL, NULL } |
| 76 }; | |
| 77 | |
| 78 | |
| 79 /** | |
| 80 * Buffer interface support for the PyBufferProxy. | |
| 81 */ | |
| 82 static PyBufferProcs _bufferproxy_as_buffer = | |
| 83 { | |
| 84 (readbufferproc) _bufferproxy_getreadbuf, | |
| 85 (writebufferproc) _bufferproxy_getwritebuf, | |
| 86 (segcountproc) _bufferproxy_getsegcount, | |
| 87 NULL, | |
| 88 }; | |
| 89 | |
| 90 static PyTypeObject PyBufferProxy_Type = | |
| 91 { | |
| 92 PyObject_HEAD_INIT(NULL) | |
| 93 0, | |
| 906 | 94 "pygame.bufferproxy.BufferProxy", /* tp_name */ |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
95 sizeof (PyBufferProxy), /* tp_basicsize */ |
| 860 | 96 0, /* tp_itemsize */ |
| 97 (destructor) _bufferproxy_dealloc, /* tp_dealloc */ | |
| 98 0, /* tp_print */ | |
| 99 0, /* tp_getattr */ | |
| 100 0, /* tp_setattr */ | |
| 101 0, /* tp_compare */ | |
|
867
a249a10980f0
Fixed bufferproxy stringifcation method. Fixed PixelArray's contains() method.
marcus
parents:
860
diff
changeset
|
102 (reprfunc) &_bufferproxy_repr, /* tp_repr */ |
| 860 | 103 0, /* tp_as_number */ |
| 104 0, /* tp_as_sequence */ | |
| 105 0, /* tp_as_mapping */ | |
| 106 0, /* tp_hash */ | |
| 107 0, /* tp_call */ | |
| 108 0, /* tp_str */ | |
| 109 0, /* tp_getattro */ | |
| 110 0, /* tp_setattro */ | |
| 111 &_bufferproxy_as_buffer, /* tp_as_buffer */ | |
| 112 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, | |
| 906 | 113 "BufferProxy () -> BufferProxy\n\n" \ |
| 114 "Creates a new, empty BufferProxy.\n\n" \ | |
| 115 "A BufferProxy usually should be constructed from C code, not Python.", | |
| 860 | 116 0, /* tp_traverse */ |
| 117 0, /* tp_clear */ | |
| 118 0, /* tp_richcompare */ | |
| 119 offsetof (PyBufferProxy, weakrefs), /* tp_weaklistoffset */ | |
| 120 0, /* tp_iter */ | |
| 121 0, /* tp_iternext */ | |
| 122 _bufferproxy_methods, /* tp_methods */ | |
| 123 0, /* tp_members */ | |
| 124 _bufferproxy_getsets, /* tp_getset */ | |
| 125 0, /* tp_base */ | |
| 126 0, /* tp_dict */ | |
| 127 0, /* tp_descr_get */ | |
| 128 0, /* tp_descr_set */ | |
| 129 offsetof (PyBufferProxy, dict), /* tp_dictoffset */ | |
| 130 0, /* tp_init */ | |
| 131 0, /* tp_alloc */ | |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
132 _bufferproxy_new, /* tp_new */ |
| 860 | 133 0, /* tp_free */ |
| 134 0, /* tp_is_gc */ | |
| 135 0, /* tp_bases */ | |
| 136 0, /* tp_mro */ | |
| 137 0, /* tp_cache */ | |
| 138 0, /* tp_subclasses */ | |
| 139 0, /* tp_weaklist */ | |
| 140 0 /* tp_del */ | |
| 141 }; | |
| 142 | |
| 143 /** | |
| 144 * Creates a new PyBufferProxy. | |
| 145 */ | |
| 146 static PyObject* | |
| 147 _bufferproxy_new (PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 148 { | |
| 149 PyBufferProxy *self = (PyBufferProxy *) type->tp_alloc (type, 0); | |
| 150 if (!self) | |
| 151 return NULL; | |
| 152 | |
| 153 self->weakrefs = NULL; | |
| 154 self->dict = NULL; | |
| 155 self->parent = NULL; | |
| 156 self->buffer = NULL; | |
| 157 self->lock = NULL; | |
| 158 return (PyObject *) self; | |
| 159 } | |
| 160 | |
| 161 /** | |
| 162 * Deallocates the PyBufferProxy and its members. | |
| 163 */ | |
| 164 static void | |
| 165 _bufferproxy_dealloc (PyBufferProxy *self) | |
| 166 { | |
| 167 if (self->weakrefs) | |
| 168 PyObject_ClearWeakRefs ((PyObject *) self); | |
|
1137
ec3ced33488f
Reworked locking code to be more strict about locking.
marcus
parents:
914
diff
changeset
|
169 |
|
ec3ced33488f
Reworked locking code to be more strict about locking.
marcus
parents:
914
diff
changeset
|
170 Py_XDECREF (self->lock); |
| 860 | 171 Py_XDECREF (self->dict); |
| 172 self->ob_type->tp_free ((PyObject *) self); | |
| 173 } | |
| 174 | |
| 175 /**** Getter and setter access ****/ | |
| 176 | |
| 177 /** | |
| 178 * Getter for PyBufferProxy.__dict__. | |
| 179 */ | |
| 180 static PyObject* | |
| 181 _bufferproxy_get_dict (PyBufferProxy *self, void *closure) | |
| 182 { | |
| 183 if (!self->dict) | |
| 184 { | |
| 185 self->dict = PyDict_New (); | |
| 186 if (!self->dict) | |
| 187 return NULL; | |
| 188 } | |
| 189 | |
| 190 Py_INCREF (self->dict); | |
| 191 return self->dict; | |
| 192 } | |
| 193 | |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
194 /** |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
195 * Getter for PyBufferProxy.raw. |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
196 */ |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
197 static PyObject* |
|
898
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
198 _bufferproxy_get_raw (PyBufferProxy *self, void *closure) |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
199 { |
|
898
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
200 return PyString_FromStringAndSize (self->buffer, self->length); |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
201 } |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
202 |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
203 /** |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
204 * Getter for PyBufferProxy.length |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
205 */ |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
206 static PyObject* |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
207 _bufferproxy_get_length (PyBufferProxy *self, void *closure) |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
208 { |
|
424ef30fa1ea
Added numpy support for the sndarray module. BufferProxy now contains a length property, which indicates the length of the buffer in bytes.
marcus
parents:
876
diff
changeset
|
209 return PyInt_FromLong (self->length); |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
210 } |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
211 |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
212 /**** Methods ****/ |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
213 |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
214 /** |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
215 * Representation method. |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
216 */ |
| 860 | 217 static PyObject* |
| 218 _bufferproxy_repr (PyBufferProxy *self) | |
| 219 { | |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
220 /* zd is for Py_size_t which python < 2.5 doesn't have. */ |
| 860 | 221 #if PY_VERSION_HEX < 0x02050000 |
| 222 return PyString_FromFormat("<BufferProxy(%d)>", self->length); | |
| 223 #else | |
| 224 return PyString_FromFormat("<BufferProxy(%zd)>", self->length); | |
| 225 #endif | |
| 226 } | |
| 227 | |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
228 /** |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
229 * Writes raw data to the buffer. |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
230 */ |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
231 static PyObject* |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
232 _bufferproxy_write (PyBufferProxy *buffer, PyObject *args) |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
233 { |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
234 Py_ssize_t offset; |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
235 Py_ssize_t length; |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
236 char *buf; |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
237 |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
238 if (!PyArg_ParseTuple (args, "s#i", &buf, &length, &offset)) |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
239 return NULL; |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
240 |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
241 if (offset + length > buffer->length) |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
242 { |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
243 return RAISE (PyExc_IndexError, "bytes to write exceed buffer size"); |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
244 } |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
245 |
| 914 | 246 memcpy (((Uint8 *)buffer->buffer) + offset, buf, (size_t) length); |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
247 |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
248 Py_RETURN_NONE; |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
249 } |
|
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
250 |
| 860 | 251 /**** Buffer interfaces ****/ |
| 252 | |
| 253 static Py_ssize_t | |
| 254 _bufferproxy_getreadbuf (PyBufferProxy *buffer, Py_ssize_t _index, | |
| 255 const void **ptr) | |
| 256 { | |
| 257 if (_index != 0) | |
| 258 { | |
| 259 PyErr_SetString (PyExc_SystemError, | |
| 260 "Accessing non-existent buffer segment"); | |
| 261 return -1; | |
| 262 } | |
| 263 | |
| 264 if (!buffer->parent) | |
| 265 { | |
| 266 *ptr = NULL; | |
| 267 return 0; | |
| 268 } | |
| 269 | |
| 270 *ptr = buffer->buffer; | |
| 271 return buffer->length; | |
| 272 } | |
| 273 | |
| 274 static Py_ssize_t | |
| 275 _bufferproxy_getwritebuf (PyBufferProxy *buffer, Py_ssize_t _index, | |
| 276 const void **ptr) | |
| 277 { | |
| 278 if (_index != 0) | |
| 279 { | |
| 280 PyErr_SetString (PyExc_SystemError, | |
| 281 "Accessing non-existent array segment"); | |
| 282 return -1; | |
| 283 } | |
| 284 | |
| 285 if (!buffer->parent) | |
| 286 { | |
| 287 *ptr = NULL; | |
| 288 return 0; | |
| 289 } | |
| 290 | |
| 291 *ptr = buffer->buffer; | |
| 292 return buffer->length; | |
| 293 } | |
| 294 | |
| 295 static Py_ssize_t | |
| 296 _bufferproxy_getsegcount (PyBufferProxy *buffer, Py_ssize_t *lenp) | |
| 297 { | |
| 298 if (!buffer->parent) | |
| 299 { | |
| 300 *lenp = 0; | |
| 301 return 0; | |
| 302 } | |
| 303 | |
| 304 if (lenp) | |
| 305 *lenp = buffer->length; | |
| 306 return 1; | |
| 307 } | |
| 308 | |
| 309 static PyObject* | |
| 310 PyBufferProxy_New (PyObject *parent, void *buffer, Py_ssize_t length, | |
| 311 PyObject *lock) | |
| 312 { | |
| 313 PyBufferProxy *buf; | |
| 314 | |
| 315 buf = (PyBufferProxy *) _bufferproxy_new (&PyBufferProxy_Type, NULL, NULL); | |
| 316 | |
| 317 if (!buf) | |
| 318 return NULL; | |
| 319 buf->buffer = buffer; | |
| 320 buf->length = length; | |
| 321 buf->lock = lock; | |
| 322 buf->parent = parent; | |
| 323 return (PyObject *) buf; | |
| 324 } | |
| 325 | |
| 326 PYGAME_EXPORT | |
| 327 void initbufferproxy (void) | |
| 328 { | |
| 329 PyObject *module; | |
| 330 PyObject *dict; | |
| 331 PyObject *apiobj; | |
| 332 static void* c_api[PYGAMEAPI_BUFFERPROXY_NUMSLOTS]; | |
| 333 | |
| 334 if (PyType_Ready (&PyBufferProxy_Type) < 0) | |
| 335 return; | |
| 336 | |
| 337 /* create the module */ | |
|
870
31fa129efd0f
Fixed Mask documentation. Added write() method to BufferProxy.
marcus
parents:
867
diff
changeset
|
338 module = Py_InitModule3 ("bufferproxy", NULL, |
| 906 | 339 "A generic proxy module that can spend arbitrary " \ |
| 340 "objects a buffer interface"); | |
| 860 | 341 PyBufferProxy_Type.tp_getattro = PyObject_GenericGetAttr; |
| 342 Py_INCREF (&PyBufferProxy_Type); | |
| 343 PyModule_AddObject (module, "BufferProxy", (PyObject *)&PyBufferProxy_Type); | |
| 344 dict = PyModule_GetDict (module); | |
| 345 | |
| 346 c_api[0] = &PyBufferProxy_Type; | |
| 347 c_api[1] = PyBufferProxy_New; | |
| 348 apiobj = PyCObject_FromVoidPtr (c_api, NULL); | |
| 349 PyDict_SetItemString (dict, PYGAMEAPI_LOCAL_ENTRY, apiobj); | |
| 350 Py_DECREF (apiobj); | |
| 351 } |
