home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Objects / bufferobject.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  11.1 KB  |  558 lines

  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.     int b_size;
  12.     int b_readonly;
  13. #ifdef CACHE_HASH
  14.     long b_hash;
  15. #endif
  16. } PyBufferObject;
  17.  
  18.  
  19. static PyObject *
  20. _PyBuffer_FromMemory(PyObject *base, void *ptr, int size, int readonly)
  21. {
  22.     PyBufferObject * b;
  23.  
  24.     if ( size < 0 ) {
  25.         PyErr_SetString(PyExc_ValueError,
  26.                 "size must be zero or positive");
  27.         return NULL;
  28.     }
  29.  
  30.     b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
  31.     if ( b == NULL )
  32.         return NULL;
  33.  
  34.     Py_XINCREF(base);
  35.     b->b_base = base;
  36.     b->b_ptr = ptr;
  37.     b->b_size = size;
  38.     b->b_readonly = readonly;
  39. #ifdef CACHE_HASH
  40.     b->b_hash = -1;
  41. #endif
  42.  
  43.     return (PyObject *) b;
  44. }
  45.  
  46. static PyObject *
  47. _PyBuffer_FromObject(PyObject *base, int offset, int size,
  48.                      getreadbufferproc proc, int readonly)
  49. {
  50.     PyBufferProcs *pb = base->ob_type->tp_as_buffer;
  51.     void *p;
  52.     int count;
  53.  
  54.     if ( offset < 0 ) {
  55.         PyErr_SetString(PyExc_ValueError,
  56.                 "offset must be zero or positive");
  57.         return NULL;
  58.     }
  59.  
  60.     if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
  61.     {
  62.         PyErr_SetString(PyExc_TypeError,
  63.                 "single-segment buffer object expected");
  64.         return NULL;
  65.     }
  66.     if ( (count = (*proc)(base, 0, &p)) < 0 )
  67.         return NULL;
  68.  
  69.     /* apply constraints to the start/end */
  70.     if ( size == Py_END_OF_BUFFER || size < 0 )
  71.         size = count;
  72.     if ( offset > count )
  73.         offset = count;
  74.     if ( offset + size > count )
  75.         size = count - offset;
  76.  
  77.     /* if the base object is another buffer, then "deref" it */
  78.     if ( PyBuffer_Check(base) )
  79.         base = ((PyBufferObject *)base)->b_base;
  80.  
  81.     return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
  82. }
  83.  
  84.  
  85. PyObject *
  86. PyBuffer_FromObject(PyObject *base, int offset, int size)
  87. {
  88.     PyBufferProcs *pb = base->ob_type->tp_as_buffer;
  89.  
  90.     if ( pb == NULL ||
  91.          pb->bf_getreadbuffer == NULL ||
  92.          pb->bf_getsegcount == NULL )
  93.     {
  94.         PyErr_SetString(PyExc_TypeError, "buffer object expected");
  95.         return NULL;
  96.     }
  97.  
  98.     return _PyBuffer_FromObject(base, offset, size,
  99.                     pb->bf_getreadbuffer, 1);
  100. }
  101.  
  102. PyObject *
  103. PyBuffer_FromReadWriteObject(PyObject *base, int offset, int size)
  104. {
  105.     PyBufferProcs *pb = base->ob_type->tp_as_buffer;
  106.  
  107.     if ( pb == NULL ||
  108.          pb->bf_getwritebuffer == NULL ||
  109.          pb->bf_getsegcount == NULL )
  110.     {
  111.         PyErr_SetString(PyExc_TypeError, "buffer object expected");
  112.         return NULL;
  113.     }
  114.  
  115.     return _PyBuffer_FromObject(base, offset, size,
  116.                     (getreadbufferproc)pb->bf_getwritebuffer,
  117.                     0);
  118. }
  119.  
  120. PyObject *
  121. PyBuffer_FromMemory(void *ptr, int size)
  122. {
  123.     return _PyBuffer_FromMemory(NULL, ptr, size, 1);
  124. }
  125.  
  126. PyObject *
  127. PyBuffer_FromReadWriteMemory(void *ptr, int size)
  128. {
  129.     return _PyBuffer_FromMemory(NULL, ptr, size, 0);
  130. }
  131.  
  132. PyObject *
  133. PyBuffer_New(int size)
  134. {
  135.     PyObject *o;
  136.     PyBufferObject * b;
  137.  
  138.     if (size < 0) {
  139.         PyErr_SetString(PyExc_ValueError,
  140.                 "size must be zero or positive");
  141.         return NULL;
  142.     }
  143.     /* PyObject_New is inlined */
  144.     o = PyObject_MALLOC(sizeof(*b) + size);
  145.     if ( o == NULL )
  146.         return PyErr_NoMemory();
  147.     b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
  148.  
  149.     b->b_base = NULL;
  150.     b->b_ptr = (void *)(b + 1);
  151.     b->b_size = size;
  152.     b->b_readonly = 0;
  153. #ifdef CACHE_HASH
  154.     b->b_hash = -1;
  155. #endif
  156.  
  157.     return o;
  158. }
  159.  
  160. /* Methods */
  161.  
  162. static void
  163. buffer_dealloc(PyBufferObject *self)
  164. {
  165.     Py_XDECREF(self->b_base);
  166.     PyObject_DEL(self);
  167. }
  168.  
  169. static int
  170. buffer_compare(PyBufferObject *self, PyBufferObject *other)
  171. {
  172.     int len_self = self->b_size;
  173.     int len_other = other->b_size;
  174.     int min_len = (len_self < len_other) ? len_self : len_other;
  175.     int cmp;
  176.     if (min_len > 0) {
  177.         cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
  178.         if (cmp != 0)
  179.             return cmp;
  180.     }
  181.     return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
  182. }
  183.  
  184. static PyObject *
  185. buffer_repr(PyBufferObject *self)
  186. {
  187.     char buf[300];
  188.     char *status = self->b_readonly ? "read-only" : "read-write";
  189.  
  190.     if ( self->b_base == NULL )
  191.     {
  192.         sprintf(buf, "<%s buffer ptr %p, size %d at %p>",
  193.             status,
  194.             self->b_ptr,
  195.             self->b_size,
  196.             self);
  197.     }
  198.     else
  199.     {
  200.         sprintf(buf, "<%s buffer for %p, ptr %p, size %d at %p>",
  201.             status,
  202.             self->b_base,
  203.             self->b_ptr,
  204.             self->b_size,
  205.             self);
  206.     }
  207.  
  208.     return PyString_FromString(buf);
  209. }
  210.  
  211. static long
  212. buffer_hash(PyBufferObject *self)
  213. {
  214.     register int len;
  215.     register unsigned char *p;
  216.     register long x;
  217.  
  218. #ifdef CACHE_HASH
  219.     if ( self->b_hash != -1 )
  220.         return self->b_hash;
  221. #endif
  222.  
  223.     if ( !self->b_readonly )
  224.     {
  225.         /* ### use different wording, since this is conditional? */
  226.         PyErr_SetString(PyExc_TypeError, "unhashable type");
  227.         return -1;
  228.     }
  229.  
  230.     len = self->b_size;
  231.     p = (unsigned char *) self->b_ptr;
  232.     x = *p << 7;
  233.     while (--len >= 0)
  234.         x = (1000003*x) ^ *p++;
  235.     x ^= self->b_size;
  236.     if (x == -1)
  237.         x = -2;
  238. #ifdef CACHE_HASH
  239.     self->b_hash = x;
  240. #endif
  241.     return x;
  242. }
  243.  
  244. static PyObject *
  245. buffer_str(PyBufferObject *self)
  246. {
  247.     return PyString_FromStringAndSize(self->b_ptr, self->b_size);
  248. }
  249.  
  250. /* Sequence methods */
  251.  
  252. static int
  253. buffer_length(PyBufferObject *self)
  254. {
  255.     return self->b_size;
  256. }
  257.  
  258. static PyObject *
  259. buffer_concat(PyBufferObject *self, PyObject *other)
  260. {
  261.     PyBufferProcs *pb = other->ob_type->tp_as_buffer;
  262.     char *p1;
  263.     void *p2;
  264.     PyObject *ob;
  265.     int count;
  266.  
  267.     if ( pb == NULL ||
  268.          pb->bf_getreadbuffer == NULL ||
  269.          pb->bf_getsegcount == NULL )
  270.     {
  271.         PyErr_BadArgument();
  272.         return NULL;
  273.     }
  274.     if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
  275.     {
  276.         /* ### use a different exception type/message? */
  277.         PyErr_SetString(PyExc_TypeError,
  278.                 "single-segment buffer object expected");
  279.         return NULL;
  280.     }
  281.  
  282.     /* optimize special case */
  283.     if ( self->b_size == 0 )
  284.     {
  285.         Py_INCREF(other);
  286.         return other;
  287.     }
  288.  
  289.     if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
  290.         return NULL;
  291.  
  292.     /* optimize special case */
  293.     if ( count == 0 )
  294.     {
  295.         Py_INCREF(self);
  296.         return (PyObject *)self;
  297.     }
  298.  
  299.     ob = PyString_FromStringAndSize(NULL, self->b_size + count);
  300.     p1 = PyString_AS_STRING(ob);
  301.     memcpy(p1, self->b_ptr, self->b_size);
  302.     memcpy(p1 + self->b_size, p2, count);
  303.  
  304.     /* there is an extra byte in the string object, so this is safe */
  305.     p1[self->b_size + count] = '\0';
  306.  
  307.     return ob;
  308. }
  309.  
  310. static PyObject *
  311. buffer_repeat(PyBufferObject *self, int count)
  312. {
  313.     PyObject *ob;
  314.     register char *p;
  315.     void *ptr = self->b_ptr;
  316.     int size = self->b_size;
  317.  
  318.     if ( count < 0 )
  319.         count = 0;
  320.     ob = PyString_FromStringAndSize(NULL, size * count);
  321.     if ( ob == NULL )
  322.         return NULL;
  323.  
  324.     p = PyString_AS_STRING(ob);
  325.     while ( count-- )
  326.     {
  327.         memcpy(p, ptr, size);
  328.         p += size;
  329.     }
  330.  
  331.     /* there is an extra byte in the string object, so this is safe */
  332.     *p = '\0';
  333.  
  334.     return ob;
  335. }
  336.  
  337. static PyObject *
  338. buffer_item(PyBufferObject *self, int idx)
  339. {
  340.     if ( idx < 0 || idx >= self->b_size )
  341.     {
  342.         PyErr_SetString(PyExc_IndexError, "buffer index out of range");
  343.         return NULL;
  344.     }
  345.     return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
  346. }
  347.  
  348. static PyObject *
  349. buffer_slice(PyBufferObject *self, int left, int right)
  350. {
  351.     if ( left < 0 )
  352.         left = 0;
  353.     if ( right < 0 )
  354.         right = 0;
  355.     if ( right > self->b_size )
  356.         right = self->b_size;
  357.     if ( left == 0 && right == self->b_size )
  358.     {
  359.         /* same as self */
  360.         Py_INCREF(self);
  361.         return (PyObject *)self;
  362.     }
  363.     if ( right < left )
  364.         right = left;
  365.     return PyString_FromStringAndSize((char *)self->b_ptr + left,
  366.                       right - left);
  367. }
  368.  
  369. static int
  370. buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
  371. {
  372.     PyBufferProcs *pb;
  373.     void *p;
  374.     int count;
  375.  
  376.     if ( self->b_readonly ) {
  377.         PyErr_SetString(PyExc_TypeError,
  378.                 "buffer is read-only");
  379.         return -1;
  380.     }
  381.  
  382.     if (idx < 0 || idx >= self->b_size) {
  383.         PyErr_SetString(PyExc_IndexError,
  384.                 "buffer assignment index out of range");
  385.         return -1;
  386.     }
  387.  
  388.     pb = other ? other->ob_type->tp_as_buffer : NULL;
  389.     if ( pb == NULL ||
  390.          pb->bf_getreadbuffer == NULL ||
  391.          pb->bf_getsegcount == NULL )
  392.     {
  393.         PyErr_BadArgument();
  394.         return -1;
  395.     }
  396.     if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
  397.     {
  398.         /* ### use a different exception type/message? */
  399.         PyErr_SetString(PyExc_TypeError,
  400.                 "single-segment buffer object expected");
  401.         return -1;
  402.     }
  403.  
  404.     if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
  405.         return -1;
  406.     if ( count != 1 ) {
  407.         PyErr_SetString(PyExc_TypeError,
  408.                 "right operand must be a single byte");
  409.         return -1;
  410.     }
  411.  
  412.     ((char *)self->b_ptr)[idx] = *(char *)p;
  413.     return 0;
  414. }
  415.  
  416. static int
  417. buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
  418. {
  419.     PyBufferProcs *pb;
  420.     void *p;
  421.     int slice_len;
  422.     int count;
  423.  
  424.     if ( self->b_readonly ) {
  425.         PyErr_SetString(PyExc_TypeError,
  426.                 "buffer is read-only");
  427.         return -1;
  428.     }
  429.  
  430.     pb = other ? other->ob_type->tp_as_buffer : NULL;
  431.     if ( pb == NULL ||
  432.          pb->bf_getreadbuffer == NULL ||
  433.          pb->bf_getsegcount == NULL )
  434.     {
  435.         PyErr_BadArgument();
  436.         return -1;
  437.     }
  438.     if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
  439.     {
  440.         /* ### use a different exception type/message? */
  441.         PyErr_SetString(PyExc_TypeError,
  442.                 "single-segment buffer object expected");
  443.         return -1;
  444.     }
  445.     if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
  446.         return -1;
  447.  
  448.     if ( left < 0 )
  449.         left = 0;
  450.     else if ( left > self->b_size )
  451.         left = self->b_size;
  452.     if ( right < left )
  453.         right = left;
  454.     else if ( right > self->b_size )
  455.         right = self->b_size;
  456.     slice_len = right - left;
  457.  
  458.     if ( count != slice_len ) {
  459.         PyErr_SetString(
  460.             PyExc_TypeError,
  461.             "right operand length must match slice length");
  462.         return -1;
  463.     }
  464.  
  465.     if ( slice_len )
  466.         memcpy((char *)self->b_ptr + left, p, slice_len);
  467.  
  468.     return 0;
  469. }
  470.  
  471. /* Buffer methods */
  472.  
  473. static int
  474. buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
  475. {
  476.     if ( idx != 0 ) {
  477.         PyErr_SetString(PyExc_SystemError,
  478.                 "accessing non-existent buffer segment");
  479.         return -1;
  480.     }
  481.     *pp = self->b_ptr;
  482.     return self->b_size;
  483. }
  484.  
  485. static int
  486. buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
  487. {
  488.     if ( self->b_readonly )
  489.     {
  490.         PyErr_SetString(PyExc_TypeError, "buffer is read-only");
  491.         return -1;
  492.     }
  493.     return buffer_getreadbuf(self, idx, pp);
  494. }
  495.  
  496. static int
  497. buffer_getsegcount(PyBufferObject *self, int *lenp)
  498. {
  499.     if ( lenp )
  500.         *lenp = self->b_size;
  501.     return 1;
  502. }
  503.  
  504. static int
  505. buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
  506. {
  507.     if ( idx != 0 ) {
  508.         PyErr_SetString(PyExc_SystemError,
  509.                 "accessing non-existent buffer segment");
  510.         return -1;
  511.     }
  512.     *pp = (const char *)self->b_ptr;
  513.     return self->b_size;
  514. }
  515.  
  516.  
  517. static PySequenceMethods buffer_as_sequence = {
  518.     (inquiry)buffer_length, /*sq_length*/
  519.     (binaryfunc)buffer_concat, /*sq_concat*/
  520.     (intargfunc)buffer_repeat, /*sq_repeat*/
  521.     (intargfunc)buffer_item, /*sq_item*/
  522.     (intintargfunc)buffer_slice, /*sq_slice*/
  523.     (intobjargproc)buffer_ass_item, /*sq_ass_item*/
  524.     (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
  525. };
  526.  
  527. static PyBufferProcs buffer_as_buffer = {
  528.     (getreadbufferproc)buffer_getreadbuf,
  529.     (getwritebufferproc)buffer_getwritebuf,
  530.     (getsegcountproc)buffer_getsegcount,
  531.     (getcharbufferproc)buffer_getcharbuf,
  532. };
  533.  
  534. PyTypeObject PyBuffer_Type = {
  535.     PyObject_HEAD_INIT(&PyType_Type)
  536.     0,
  537.     "buffer",
  538.     sizeof(PyBufferObject),
  539.     0,
  540.     (destructor)buffer_dealloc, /*tp_dealloc*/
  541.     0,        /*tp_print*/
  542.     0,        /*tp_getattr*/
  543.     0,        /*tp_setattr*/
  544.     (cmpfunc)buffer_compare, /*tp_compare*/
  545.     (reprfunc)buffer_repr, /*tp_repr*/
  546.     0,        /*tp_as_number*/
  547.     &buffer_as_sequence,    /*tp_as_sequence*/
  548.     0,        /*tp_as_mapping*/
  549.     (hashfunc)buffer_hash,    /*tp_hash*/
  550.     0,        /*tp_call*/
  551.     (reprfunc)buffer_str,        /*tp_str*/
  552.     0,        /*tp_getattro*/
  553.     0,        /*tp_setattro*/
  554.     &buffer_as_buffer,    /*tp_as_buffer*/
  555.     Py_TPFLAGS_DEFAULT,    /*tp_flags*/
  556.     0,        /*tp_doc*/
  557. };
  558.