History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Objects/bufferobject.c (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Objects/bufferobject.c+706−0
@@ -0,0 +1,706 @@
1+
2+/* Buffer object implementation */
3+
4+#include "Python.h"
5+
6+
7+typedef struct {
8+ PyObject_HEAD
9+ PyObject *b_base;
10+ void *b_ptr;
11+ Py_ssize_t b_size;
12+ Py_ssize_t b_offset;
13+ int b_readonly;
14+ long b_hash;
15+} PyBufferObject;
16+
17+
18+enum buffer_t {
19+ READ_BUFFER,
20+ WRITE_BUFFER,
21+ CHAR_BUFFER,
22+ ANY_BUFFER,
23+};
24+
25+static int
26+get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
27+ enum buffer_t buffer_type)
28+{
29+ if (self->b_base == NULL) {
30+ assert (ptr != NULL);
31+ *ptr = self->b_ptr;
32+ *size = self->b_size;
33+ }
34+ else {
35+ Py_ssize_t count, offset;
36+ readbufferproc proc = 0;
37+ PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
38+ if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
39+ PyErr_SetString(PyExc_TypeError,
40+ "single-segment buffer object expected");
41+ return 0;
42+ }
43+ if ((buffer_type == READ_BUFFER) ||
44+ ((buffer_type == ANY_BUFFER) && self->b_readonly))
45+ proc = bp->bf_getreadbuffer;
46+ else if ((buffer_type == WRITE_BUFFER) ||
47+ (buffer_type == ANY_BUFFER))
48+ proc = (readbufferproc)bp->bf_getwritebuffer;
49+ else if (buffer_type == CHAR_BUFFER) {
50+ if (!PyType_HasFeature(self->ob_type,
51+ Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
52+ PyErr_SetString(PyExc_TypeError,
53+ "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
54+ return 0;
55+ }
56+ proc = (readbufferproc)bp->bf_getcharbuffer;
57+ }
58+ if (!proc) {
59+ char *buffer_type_name;
60+ switch (buffer_type) {
61+ case READ_BUFFER:
62+ buffer_type_name = "read";
63+ break;
64+ case WRITE_BUFFER:
65+ buffer_type_name = "write";
66+ break;
67+ case CHAR_BUFFER:
68+ buffer_type_name = "char";
69+ break;
70+ default:
71+ buffer_type_name = "no";
72+ break;
73+ }
74+ PyErr_Format(PyExc_TypeError,
75+ "%s buffer type not available",
76+ buffer_type_name);
77+ return 0;
78+ }
79+ if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
80+ return 0;
81+ /* apply constraints to the start/end */
82+ if (self->b_offset > count)
83+ offset = count;
84+ else
85+ offset = self->b_offset;
86+ *(char **)ptr = *(char **)ptr + offset;
87+ if (self->b_size == Py_END_OF_BUFFER)
88+ *size = count;
89+ else
90+ *size = self->b_size;
91+ if (offset + *size > count)
92+ *size = count - offset;
93+ }
94+ return 1;
95+}
96+
97+
98+static PyObject *
99+buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
100+ int readonly)
101+{
102+ PyBufferObject * b;
103+
104+ if (size < 0 && size != Py_END_OF_BUFFER) {
105+ PyErr_SetString(PyExc_ValueError,
106+ "size must be zero or positive");
107+ return NULL;
108+ }
109+ if (offset < 0) {
110+ PyErr_SetString(PyExc_ValueError,
111+ "offset must be zero or positive");
112+ return NULL;
113+ }
114+
115+ b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
116+ if ( b == NULL )
117+ return NULL;
118+
119+ Py_XINCREF(base);
120+ b->b_base = base;
121+ b->b_ptr = ptr;
122+ b->b_size = size;
123+ b->b_offset = offset;
124+ b->b_readonly = readonly;
125+ b->b_hash = -1;
126+
127+ return (PyObject *) b;
128+}
129+
130+static PyObject *
131+buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
132+{
133+ if (offset < 0) {
134+ PyErr_SetString(PyExc_ValueError,
135+ "offset must be zero or positive");
136+ return NULL;
137+ }
138+ if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
139+ /* another buffer, refer to the base object */
140+ PyBufferObject *b = (PyBufferObject *)base;
141+ if (b->b_size != Py_END_OF_BUFFER) {
142+ Py_ssize_t base_size = b->b_size - offset;
143+ if (base_size < 0)
144+ base_size = 0;
145+ if (size == Py_END_OF_BUFFER || size > base_size)
146+ size = base_size;
147+ }
148+ offset += b->b_offset;
149+ base = b->b_base;
150+ }
151+ return buffer_from_memory(base, size, offset, NULL, readonly);
152+}
153+
154+
155+PyObject *
156+PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
157+{
158+ PyBufferProcs *pb = base->ob_type->tp_as_buffer;
159+
160+ if ( pb == NULL ||
161+ pb->bf_getreadbuffer == NULL ||
162+ pb->bf_getsegcount == NULL )
163+ {
164+ PyErr_SetString(PyExc_TypeError, "buffer object expected");
165+ return NULL;
166+ }
167+
168+ return buffer_from_object(base, size, offset, 1);
169+}
170+
171+PyObject *
172+PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
173+{
174+ PyBufferProcs *pb = base->ob_type->tp_as_buffer;
175+
176+ if ( pb == NULL ||
177+ pb->bf_getwritebuffer == NULL ||
178+ pb->bf_getsegcount == NULL )
179+ {
180+ PyErr_SetString(PyExc_TypeError, "buffer object expected");
181+ return NULL;
182+ }
183+
184+ return buffer_from_object(base, size, offset, 0);
185+}
186+
187+PyObject *
188+PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
189+{
190+ return buffer_from_memory(NULL, size, 0, ptr, 1);
191+}
192+
193+PyObject *
194+PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
195+{
196+ return buffer_from_memory(NULL, size, 0, ptr, 0);
197+}
198+
199+PyObject *
200+PyBuffer_New(Py_ssize_t size)
201+{
202+ PyObject *o;
203+ PyBufferObject * b;
204+
205+ if (size < 0) {
206+ PyErr_SetString(PyExc_ValueError,
207+ "size must be zero or positive");
208+ return NULL;
209+ }
210+ /* XXX: check for overflow in multiply */
211+ /* Inline PyObject_New */
212+ o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
213+ if ( o == NULL )
214+ return PyErr_NoMemory();
215+ b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
216+
217+ b->b_base = NULL;
218+ b->b_ptr = (void *)(b + 1);
219+ b->b_size = size;
220+ b->b_offset = 0;
221+ b->b_readonly = 0;
222+ b->b_hash = -1;
223+
224+ return o;
225+}
226+
227+/* Methods */
228+
229+static PyObject *
230+buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
231+{
232+ PyObject *ob;
233+ Py_ssize_t offset = 0;
234+ Py_ssize_t size = Py_END_OF_BUFFER;
235+
236+ if (!_PyArg_NoKeywords("buffer()", kw))
237+ return NULL;
238+
239+ if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
240+ return NULL;
241+ return PyBuffer_FromObject(ob, offset, size);
242+}
243+
244+PyDoc_STRVAR(buffer_doc,
245+"buffer(object [, offset[, size]])\n\
246+\n\
247+Create a new buffer object which references the given object.\n\
248+The buffer will reference a slice of the target object from the\n\
249+start of the object (or at the specified offset). The slice will\n\
250+extend to the end of the target object (or with the specified size).");
251+
252+
253+static void
254+buffer_dealloc(PyBufferObject *self)
255+{
256+ Py_XDECREF(self->b_base);
257+ PyObject_DEL(self);
258+}
259+
260+static int
261+buffer_compare(PyBufferObject *self, PyBufferObject *other)
262+{
263+ void *p1, *p2;
264+ Py_ssize_t len_self, len_other, min_len;
265+ int cmp;
266+
267+ if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
268+ return -1;
269+ if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
270+ return -1;
271+ min_len = (len_self < len_other) ? len_self : len_other;
272+ if (min_len > 0) {
273+ cmp = memcmp(p1, p2, min_len);
274+ if (cmp != 0)
275+ return cmp < 0 ? -1 : 1;
276+ }
277+ return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
278+}
279+
280+static PyObject *
281+buffer_repr(PyBufferObject *self)
282+{
283+ const char *status = self->b_readonly ? "read-only" : "read-write";
284+
285+ if ( self->b_base == NULL )
286+ return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
287+ status,
288+ self->b_ptr,
289+ self->b_size,
290+ self);
291+ else
292+ return PyString_FromFormat(
293+ "<%s buffer for %p, size %zd, offset %zd at %p>",
294+ status,
295+ self->b_base,
296+ self->b_size,
297+ self->b_offset,
298+ self);
299+}
300+
301+static long
302+buffer_hash(PyBufferObject *self)
303+{
304+ void *ptr;
305+ Py_ssize_t size;
306+ register Py_ssize_t len;
307+ register unsigned char *p;
308+ register long x;
309+
310+ if ( self->b_hash != -1 )
311+ return self->b_hash;
312+
313+ /* XXX potential bugs here, a readonly buffer does not imply that the
314+ * underlying memory is immutable. b_readonly is a necessary but not
315+ * sufficient condition for a buffer to be hashable. Perhaps it would
316+ * be better to only allow hashing if the underlying object is known to
317+ * be immutable (e.g. PyString_Check() is true). Another idea would
318+ * be to call tp_hash on the underlying object and see if it raises
319+ * an error. */
320+ if ( !self->b_readonly )
321+ {
322+ PyErr_SetString(PyExc_TypeError,
323+ "writable buffers are not hashable");
324+ return -1;
325+ }
326+
327+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))
328+ return -1;
329+ p = (unsigned char *) ptr;
330+ len = size;
331+ x = *p << 7;
332+ while (--len >= 0)
333+ x = (1000003*x) ^ *p++;
334+ x ^= size;
335+ if (x == -1)
336+ x = -2;
337+ self->b_hash = x;
338+ return x;
339+}
340+
341+static PyObject *
342+buffer_str(PyBufferObject *self)
343+{
344+ void *ptr;
345+ Py_ssize_t size;
346+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))
347+ return NULL;
348+ return PyString_FromStringAndSize((const char *)ptr, size);
349+}
350+
351+/* Sequence methods */
352+
353+static Py_ssize_t
354+buffer_length(PyBufferObject *self)
355+{
356+ void *ptr;
357+ Py_ssize_t size;
358+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))
359+ return -1;
360+ return size;
361+}
362+
363+static PyObject *
364+buffer_concat(PyBufferObject *self, PyObject *other)
365+{
366+ PyBufferProcs *pb = other->ob_type->tp_as_buffer;
367+ void *ptr1, *ptr2;
368+ char *p;
369+ PyObject *ob;
370+ Py_ssize_t size, count;
371+
372+ if ( pb == NULL ||
373+ pb->bf_getreadbuffer == NULL ||
374+ pb->bf_getsegcount == NULL )
375+ {
376+ PyErr_BadArgument();
377+ return NULL;
378+ }
379+ if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
380+ {
381+ /* ### use a different exception type/message? */
382+ PyErr_SetString(PyExc_TypeError,
383+ "single-segment buffer object expected");
384+ return NULL;
385+ }
386+
387+ if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
388+ return NULL;
389+
390+ /* optimize special case */
391+ if ( size == 0 )
392+ {
393+ Py_INCREF(other);
394+ return other;
395+ }
396+
397+ if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
398+ return NULL;
399+
400+ ob = PyString_FromStringAndSize(NULL, size + count);
401+ if ( ob == NULL )
402+ return NULL;
403+ p = PyString_AS_STRING(ob);
404+ memcpy(p, ptr1, size);
405+ memcpy(p + size, ptr2, count);
406+
407+ /* there is an extra byte in the string object, so this is safe */
408+ p[size + count] = '\0';
409+
410+ return ob;
411+}
412+
413+static PyObject *
414+buffer_repeat(PyBufferObject *self, Py_ssize_t count)
415+{
416+ PyObject *ob;
417+ register char *p;
418+ void *ptr;
419+ Py_ssize_t size;
420+
421+ if ( count < 0 )
422+ count = 0;
423+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))
424+ return NULL;
425+ ob = PyString_FromStringAndSize(NULL, size * count);
426+ if ( ob == NULL )
427+ return NULL;
428+
429+ p = PyString_AS_STRING(ob);
430+ while ( count-- )
431+ {
432+ memcpy(p, ptr, size);
433+ p += size;
434+ }
435+
436+ /* there is an extra byte in the string object, so this is safe */
437+ *p = '\0';
438+
439+ return ob;
440+}
441+
442+static PyObject *
443+buffer_item(PyBufferObject *self, Py_ssize_t idx)
444+{
445+ void *ptr;
446+ Py_ssize_t size;
447+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))
448+ return NULL;
449+ if ( idx < 0 || idx >= size ) {
450+ PyErr_SetString(PyExc_IndexError, "buffer index out of range");
451+ return NULL;
452+ }
453+ return PyString_FromStringAndSize((char *)ptr + idx, 1);
454+}
455+
456+static PyObject *
457+buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
458+{
459+ void *ptr;
460+ Py_ssize_t size;
461+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))
462+ return NULL;
463+ if ( left < 0 )
464+ left = 0;
465+ if ( right < 0 )
466+ right = 0;
467+ if ( right > size )
468+ right = size;
469+ if ( right < left )
470+ right = left;
471+ return PyString_FromStringAndSize((char *)ptr + left,
472+ right - left);
473+}
474+
475+static int
476+buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
477+{
478+ PyBufferProcs *pb;
479+ void *ptr1, *ptr2;
480+ Py_ssize_t size;
481+ Py_ssize_t count;
482+
483+ if ( self->b_readonly ) {
484+ PyErr_SetString(PyExc_TypeError,
485+ "buffer is read-only");
486+ return -1;
487+ }
488+
489+ if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
490+ return -1;
491+
492+ if (idx < 0 || idx >= size) {
493+ PyErr_SetString(PyExc_IndexError,
494+ "buffer assignment index out of range");
495+ return -1;
496+ }
497+
498+ pb = other ? other->ob_type->tp_as_buffer : NULL;
499+ if ( pb == NULL ||
500+ pb->bf_getreadbuffer == NULL ||
501+ pb->bf_getsegcount == NULL )
502+ {
503+ PyErr_BadArgument();
504+ return -1;
505+ }
506+ if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
507+ {
508+ /* ### use a different exception type/message? */
509+ PyErr_SetString(PyExc_TypeError,
510+ "single-segment buffer object expected");
511+ return -1;
512+ }
513+
514+ if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
515+ return -1;
516+ if ( count != 1 ) {
517+ PyErr_SetString(PyExc_TypeError,
518+ "right operand must be a single byte");
519+ return -1;
520+ }
521+
522+ ((char *)ptr1)[idx] = *(char *)ptr2;
523+ return 0;
524+}
525+
526+static int
527+buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
528+{
529+ PyBufferProcs *pb;
530+ void *ptr1, *ptr2;
531+ Py_ssize_t size;
532+ Py_ssize_t slice_len;
533+ Py_ssize_t count;
534+
535+ if ( self->b_readonly ) {
536+ PyErr_SetString(PyExc_TypeError,
537+ "buffer is read-only");
538+ return -1;
539+ }
540+
541+ pb = other ? other->ob_type->tp_as_buffer : NULL;
542+ if ( pb == NULL ||
543+ pb->bf_getreadbuffer == NULL ||
544+ pb->bf_getsegcount == NULL )
545+ {
546+ PyErr_BadArgument();
547+ return -1;
548+ }
549+ if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
550+ {
551+ /* ### use a different exception type/message? */
552+ PyErr_SetString(PyExc_TypeError,
553+ "single-segment buffer object expected");
554+ return -1;
555+ }
556+ if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
557+ return -1;
558+ if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
559+ return -1;
560+
561+ if ( left < 0 )
562+ left = 0;
563+ else if ( left > size )
564+ left = size;
565+ if ( right < left )
566+ right = left;
567+ else if ( right > size )
568+ right = size;
569+ slice_len = right - left;
570+
571+ if ( count != slice_len ) {
572+ PyErr_SetString(
573+ PyExc_TypeError,
574+ "right operand length must match slice length");
575+ return -1;
576+ }
577+
578+ if ( slice_len )
579+ memcpy((char *)ptr1 + left, ptr2, slice_len);
580+
581+ return 0;
582+}
583+
584+/* Buffer methods */
585+
586+static Py_ssize_t
587+buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
588+{
589+ Py_ssize_t size;
590+ if ( idx != 0 ) {
591+ PyErr_SetString(PyExc_SystemError,
592+ "accessing non-existent buffer segment");
593+ return -1;
594+ }
595+ if (!get_buf(self, pp, &size, READ_BUFFER))
596+ return -1;
597+ return size;
598+}
599+
600+static Py_ssize_t
601+buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
602+{
603+ Py_ssize_t size;
604+
605+ if ( self->b_readonly )
606+ {
607+ PyErr_SetString(PyExc_TypeError, "buffer is read-only");
608+ return -1;
609+ }
610+
611+ if ( idx != 0 ) {
612+ PyErr_SetString(PyExc_SystemError,
613+ "accessing non-existent buffer segment");
614+ return -1;
615+ }
616+ if (!get_buf(self, pp, &size, WRITE_BUFFER))
617+ return -1;
618+ return size;
619+}
620+
621+static Py_ssize_t
622+buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
623+{
624+ void *ptr;
625+ Py_ssize_t size;
626+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))
627+ return -1;
628+ if (lenp)
629+ *lenp = size;
630+ return 1;
631+}
632+
633+static Py_ssize_t
634+buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
635+{
636+ void *ptr;
637+ Py_ssize_t size;
638+ if ( idx != 0 ) {
639+ PyErr_SetString(PyExc_SystemError,
640+ "accessing non-existent buffer segment");
641+ return -1;
642+ }
643+ if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
644+ return -1;
645+ *pp = (const char *)ptr;
646+ return size;
647+}
648+
649+static PySequenceMethods buffer_as_sequence = {
650+ (lenfunc)buffer_length, /*sq_length*/
651+ (binaryfunc)buffer_concat, /*sq_concat*/
652+ (ssizeargfunc)buffer_repeat, /*sq_repeat*/
653+ (ssizeargfunc)buffer_item, /*sq_item*/
654+ (ssizessizeargfunc)buffer_slice, /*sq_slice*/
655+ (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
656+ (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
657+};
658+
659+static PyBufferProcs buffer_as_buffer = {
660+ (readbufferproc)buffer_getreadbuf,
661+ (writebufferproc)buffer_getwritebuf,
662+ (segcountproc)buffer_getsegcount,
663+ (charbufferproc)buffer_getcharbuf,
664+};
665+
666+PyTypeObject PyBuffer_Type = {
667+ PyObject_HEAD_INIT(&PyType_Type)
668+ 0,
669+ "buffer",
670+ sizeof(PyBufferObject),
671+ 0,
672+ (destructor)buffer_dealloc, /* tp_dealloc */
673+ 0, /* tp_print */
674+ 0, /* tp_getattr */
675+ 0, /* tp_setattr */
676+ (cmpfunc)buffer_compare, /* tp_compare */
677+ (reprfunc)buffer_repr, /* tp_repr */
678+ 0, /* tp_as_number */
679+ &buffer_as_sequence, /* tp_as_sequence */
680+ 0, /* tp_as_mapping */
681+ (hashfunc)buffer_hash, /* tp_hash */
682+ 0, /* tp_call */
683+ (reprfunc)buffer_str, /* tp_str */
684+ PyObject_GenericGetAttr, /* tp_getattro */
685+ 0, /* tp_setattro */
686+ &buffer_as_buffer, /* tp_as_buffer */
687+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
688+ buffer_doc, /* tp_doc */
689+ 0, /* tp_traverse */
690+ 0, /* tp_clear */
691+ 0, /* tp_richcompare */
692+ 0, /* tp_weaklistoffset */
693+ 0, /* tp_iter */
694+ 0, /* tp_iternext */
695+ 0, /* tp_methods */
696+ 0, /* tp_members */
697+ 0, /* tp_getset */
698+ 0, /* tp_base */
699+ 0, /* tp_dict */
700+ 0, /* tp_descr_get */
701+ 0, /* tp_descr_set */
702+ 0, /* tp_dictoffset */
703+ 0, /* tp_init */
704+ 0, /* tp_alloc */
705+ buffer_new, /* tp_new */
706+};