symbian-qemu-0.9.1-12/python-2.6.1/Objects/bufferobject.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 	if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
       
   211 		/* unlikely */
       
   212 		return PyErr_NoMemory();
       
   213 	}
       
   214 	/* Inline PyObject_New */
       
   215 	o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
       
   216 	if ( o == NULL )
       
   217 		return PyErr_NoMemory();
       
   218 	b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
       
   219 
       
   220 	b->b_base = NULL;
       
   221 	b->b_ptr = (void *)(b + 1);
       
   222 	b->b_size = size;
       
   223 	b->b_offset = 0;
       
   224 	b->b_readonly = 0;
       
   225 	b->b_hash = -1;
       
   226 
       
   227 	return o;
       
   228 }
       
   229 
       
   230 /* Methods */
       
   231 
       
   232 static PyObject *
       
   233 buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
       
   234 {
       
   235 	PyObject *ob;
       
   236 	Py_ssize_t offset = 0;
       
   237 	Py_ssize_t size = Py_END_OF_BUFFER;
       
   238 
       
   239 	if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
       
   240 		return NULL;
       
   241 	
       
   242 	if (!_PyArg_NoKeywords("buffer()", kw))
       
   243 		return NULL;
       
   244 
       
   245 	if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
       
   246 	    return NULL;
       
   247 	return PyBuffer_FromObject(ob, offset, size);
       
   248 }
       
   249 
       
   250 PyDoc_STRVAR(buffer_doc,
       
   251 "buffer(object [, offset[, size]])\n\
       
   252 \n\
       
   253 Create a new buffer object which references the given object.\n\
       
   254 The buffer will reference a slice of the target object from the\n\
       
   255 start of the object (or at the specified offset). The slice will\n\
       
   256 extend to the end of the target object (or with the specified size).");
       
   257 
       
   258 
       
   259 static void
       
   260 buffer_dealloc(PyBufferObject *self)
       
   261 {
       
   262 	Py_XDECREF(self->b_base);
       
   263 	PyObject_DEL(self);
       
   264 }
       
   265 
       
   266 static int
       
   267 buffer_compare(PyBufferObject *self, PyBufferObject *other)
       
   268 {
       
   269 	void *p1, *p2;
       
   270 	Py_ssize_t len_self, len_other, min_len;
       
   271 	int cmp;
       
   272 
       
   273 	if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
       
   274 		return -1;
       
   275 	if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
       
   276 		return -1;
       
   277 	min_len = (len_self < len_other) ? len_self : len_other;
       
   278 	if (min_len > 0) {
       
   279 		cmp = memcmp(p1, p2, min_len);
       
   280 		if (cmp != 0)
       
   281 			return cmp < 0 ? -1 : 1;
       
   282 	}
       
   283 	return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
       
   284 }
       
   285 
       
   286 static PyObject *
       
   287 buffer_repr(PyBufferObject *self)
       
   288 {
       
   289 	const char *status = self->b_readonly ? "read-only" : "read-write";
       
   290 
       
   291 	if ( self->b_base == NULL )
       
   292 		return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
       
   293 					   status,
       
   294 					   self->b_ptr,
       
   295 					   self->b_size,
       
   296 					   self);
       
   297 	else
       
   298 		return PyString_FromFormat(
       
   299 			"<%s buffer for %p, size %zd, offset %zd at %p>",
       
   300 			status,
       
   301 			self->b_base,
       
   302 			self->b_size,
       
   303 			self->b_offset,
       
   304 			self);
       
   305 }
       
   306 
       
   307 static long
       
   308 buffer_hash(PyBufferObject *self)
       
   309 {
       
   310 	void *ptr;
       
   311 	Py_ssize_t size;
       
   312 	register Py_ssize_t len;
       
   313 	register unsigned char *p;
       
   314 	register long x;
       
   315 
       
   316 	if ( self->b_hash != -1 )
       
   317 		return self->b_hash;
       
   318 
       
   319 	/* XXX potential bugs here, a readonly buffer does not imply that the
       
   320 	 * underlying memory is immutable.  b_readonly is a necessary but not
       
   321 	 * sufficient condition for a buffer to be hashable.  Perhaps it would
       
   322 	 * be better to only allow hashing if the underlying object is known to
       
   323 	 * be immutable (e.g. PyString_Check() is true).  Another idea would
       
   324 	 * be to call tp_hash on the underlying object and see if it raises
       
   325 	 * an error. */
       
   326 	if ( !self->b_readonly )
       
   327 	{
       
   328 		PyErr_SetString(PyExc_TypeError,
       
   329 				"writable buffers are not hashable");
       
   330 		return -1;
       
   331 	}
       
   332 
       
   333 	if (!get_buf(self, &ptr, &size, ANY_BUFFER))
       
   334 		return -1;
       
   335 	p = (unsigned char *) ptr;
       
   336 	len = size;
       
   337 	x = *p << 7;
       
   338 	while (--len >= 0)
       
   339 		x = (1000003*x) ^ *p++;
       
   340 	x ^= size;
       
   341 	if (x == -1)
       
   342 		x = -2;
       
   343 	self->b_hash = x;
       
   344 	return x;
       
   345 }
       
   346 
       
   347 static PyObject *
       
   348 buffer_str(PyBufferObject *self)
       
   349 {
       
   350 	void *ptr;
       
   351 	Py_ssize_t size;
       
   352 	if (!get_buf(self, &ptr, &size, ANY_BUFFER))
       
   353 		return NULL;
       
   354 	return PyString_FromStringAndSize((const char *)ptr, size);
       
   355 }
       
   356 
       
   357 /* Sequence methods */
       
   358 
       
   359 static Py_ssize_t
       
   360 buffer_length(PyBufferObject *self)
       
   361 {
       
   362 	void *ptr;
       
   363 	Py_ssize_t size;
       
   364 	if (!get_buf(self, &ptr, &size, ANY_BUFFER))
       
   365 		return -1;
       
   366 	return size;
       
   367 }
       
   368 
       
   369 static PyObject *
       
   370 buffer_concat(PyBufferObject *self, PyObject *other)
       
   371 {
       
   372 	PyBufferProcs *pb = other->ob_type->tp_as_buffer;
       
   373 	void *ptr1, *ptr2;
       
   374 	char *p;
       
   375 	PyObject *ob;
       
   376 	Py_ssize_t size, count;
       
   377 
       
   378 	if ( pb == NULL ||
       
   379 	     pb->bf_getreadbuffer == NULL ||
       
   380 	     pb->bf_getsegcount == NULL )
       
   381 	{
       
   382 		PyErr_BadArgument();
       
   383 		return NULL;
       
   384 	}
       
   385 	if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
       
   386 	{
       
   387 		/* ### use a different exception type/message? */
       
   388 		PyErr_SetString(PyExc_TypeError,
       
   389 				"single-segment buffer object expected");
       
   390 		return NULL;
       
   391 	}
       
   392 
       
   393  	if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
       
   394  		return NULL;
       
   395  
       
   396 	/* optimize special case */
       
   397 	if ( size == 0 )
       
   398 	{
       
   399 	    Py_INCREF(other);
       
   400 	    return other;
       
   401 	}
       
   402 
       
   403 	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
       
   404 		return NULL;
       
   405 
       
   406 	assert(count <= PY_SIZE_MAX - size);
       
   407 
       
   408  	ob = PyString_FromStringAndSize(NULL, size + count);
       
   409 	if ( ob == NULL )
       
   410 		return NULL;
       
   411  	p = PyString_AS_STRING(ob);
       
   412  	memcpy(p, ptr1, size);
       
   413  	memcpy(p + size, ptr2, count);
       
   414 
       
   415 	/* there is an extra byte in the string object, so this is safe */
       
   416 	p[size + count] = '\0';
       
   417 
       
   418 	return ob;
       
   419 }
       
   420 
       
   421 static PyObject *
       
   422 buffer_repeat(PyBufferObject *self, Py_ssize_t count)
       
   423 {
       
   424 	PyObject *ob;
       
   425 	register char *p;
       
   426 	void *ptr;
       
   427 	Py_ssize_t size;
       
   428 
       
   429 	if ( count < 0 )
       
   430 		count = 0;
       
   431 	if (!get_buf(self, &ptr, &size, ANY_BUFFER))
       
   432 		return NULL;
       
   433 	if (count > PY_SSIZE_T_MAX / size) {
       
   434 		PyErr_SetString(PyExc_MemoryError, "result too large");
       
   435 		return NULL;
       
   436 	}
       
   437 	ob = PyString_FromStringAndSize(NULL, size * count);
       
   438 	if ( ob == NULL )
       
   439 		return NULL;
       
   440 
       
   441 	p = PyString_AS_STRING(ob);
       
   442 	while ( count-- )
       
   443 	{
       
   444 	    memcpy(p, ptr, size);
       
   445 	    p += size;
       
   446 	}
       
   447 
       
   448 	/* there is an extra byte in the string object, so this is safe */
       
   449 	*p = '\0';
       
   450 
       
   451 	return ob;
       
   452 }
       
   453 
       
   454 static PyObject *
       
   455 buffer_item(PyBufferObject *self, Py_ssize_t idx)
       
   456 {
       
   457 	void *ptr;
       
   458 	Py_ssize_t size;
       
   459 	if (!get_buf(self, &ptr, &size, ANY_BUFFER))
       
   460 		return NULL;
       
   461 	if ( idx < 0 || idx >= size ) {
       
   462 		PyErr_SetString(PyExc_IndexError, "buffer index out of range");
       
   463 		return NULL;
       
   464 	}
       
   465 	return PyString_FromStringAndSize((char *)ptr + idx, 1);
       
   466 }
       
   467 
       
   468 static PyObject *
       
   469 buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
       
   470 {
       
   471 	void *ptr;
       
   472 	Py_ssize_t size;
       
   473 	if (!get_buf(self, &ptr, &size, ANY_BUFFER))
       
   474 		return NULL;
       
   475 	if ( left < 0 )
       
   476 		left = 0;
       
   477 	if ( right < 0 )
       
   478 		right = 0;
       
   479 	if ( right > size )
       
   480 		right = size;
       
   481 	if ( right < left )
       
   482 		right = left;
       
   483 	return PyString_FromStringAndSize((char *)ptr + left,
       
   484 					  right - left);
       
   485 }
       
   486 
       
   487 static PyObject *
       
   488 buffer_subscript(PyBufferObject *self, PyObject *item)
       
   489 {
       
   490 	void *p;
       
   491 	Py_ssize_t size;
       
   492 	
       
   493 	if (!get_buf(self, &p, &size, ANY_BUFFER))
       
   494 		return NULL;
       
   495 	if (PyIndex_Check(item)) {
       
   496 		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
       
   497 		if (i == -1 && PyErr_Occurred())
       
   498 			return NULL;
       
   499 		if (i < 0)
       
   500 			i += size;
       
   501 		return buffer_item(self, i);
       
   502 	}
       
   503 	else if (PySlice_Check(item)) {
       
   504 		Py_ssize_t start, stop, step, slicelength, cur, i;
       
   505 
       
   506 		if (PySlice_GetIndicesEx((PySliceObject*)item, size,
       
   507 				 &start, &stop, &step, &slicelength) < 0) {
       
   508 			return NULL;
       
   509 		}
       
   510 
       
   511 		if (slicelength <= 0)
       
   512 			return PyString_FromStringAndSize("", 0);
       
   513 		else if (step == 1)
       
   514 			return PyString_FromStringAndSize((char *)p + start,
       
   515 							  stop - start);
       
   516 		else {
       
   517 			PyObject *result;
       
   518 			char *source_buf = (char *)p;
       
   519 			char *result_buf = (char *)PyMem_Malloc(slicelength);
       
   520 
       
   521 			if (result_buf == NULL)
       
   522 				return PyErr_NoMemory();
       
   523 
       
   524 			for (cur = start, i = 0; i < slicelength;
       
   525 			     cur += step, i++) {
       
   526 				result_buf[i] = source_buf[cur];
       
   527 			}
       
   528 
       
   529 			result = PyString_FromStringAndSize(result_buf,
       
   530 							    slicelength);
       
   531 			PyMem_Free(result_buf);
       
   532 			return result;
       
   533 		}
       
   534 	}
       
   535 	else {
       
   536 		PyErr_SetString(PyExc_TypeError,
       
   537 				"sequence index must be integer");
       
   538 		return NULL;
       
   539 	}
       
   540 }
       
   541 
       
   542 static int
       
   543 buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
       
   544 {
       
   545 	PyBufferProcs *pb;
       
   546 	void *ptr1, *ptr2;
       
   547 	Py_ssize_t size;
       
   548 	Py_ssize_t count;
       
   549 
       
   550 	if ( self->b_readonly ) {
       
   551 		PyErr_SetString(PyExc_TypeError,
       
   552 				"buffer is read-only");
       
   553 		return -1;
       
   554 	}
       
   555 
       
   556 	if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
       
   557 		return -1;
       
   558 
       
   559 	if (idx < 0 || idx >= size) {
       
   560 		PyErr_SetString(PyExc_IndexError,
       
   561 				"buffer assignment index out of range");
       
   562 		return -1;
       
   563 	}
       
   564 
       
   565 	pb = other ? other->ob_type->tp_as_buffer : NULL;
       
   566 	if ( pb == NULL ||
       
   567 	     pb->bf_getreadbuffer == NULL ||
       
   568 	     pb->bf_getsegcount == NULL )
       
   569 	{
       
   570 		PyErr_BadArgument();
       
   571 		return -1;
       
   572 	}
       
   573 	if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
       
   574 	{
       
   575 		/* ### use a different exception type/message? */
       
   576 		PyErr_SetString(PyExc_TypeError,
       
   577 				"single-segment buffer object expected");
       
   578 		return -1;
       
   579 	}
       
   580 
       
   581 	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
       
   582 		return -1;
       
   583 	if ( count != 1 ) {
       
   584 		PyErr_SetString(PyExc_TypeError,
       
   585 				"right operand must be a single byte");
       
   586 		return -1;
       
   587 	}
       
   588 
       
   589 	((char *)ptr1)[idx] = *(char *)ptr2;
       
   590 	return 0;
       
   591 }
       
   592 
       
   593 static int
       
   594 buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
       
   595 {
       
   596 	PyBufferProcs *pb;
       
   597 	void *ptr1, *ptr2;
       
   598 	Py_ssize_t size;
       
   599 	Py_ssize_t slice_len;
       
   600 	Py_ssize_t count;
       
   601 
       
   602 	if ( self->b_readonly ) {
       
   603 		PyErr_SetString(PyExc_TypeError,
       
   604 				"buffer is read-only");
       
   605 		return -1;
       
   606 	}
       
   607 
       
   608 	pb = other ? other->ob_type->tp_as_buffer : NULL;
       
   609 	if ( pb == NULL ||
       
   610 	     pb->bf_getreadbuffer == NULL ||
       
   611 	     pb->bf_getsegcount == NULL )
       
   612 	{
       
   613 		PyErr_BadArgument();
       
   614 		return -1;
       
   615 	}
       
   616 	if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
       
   617 	{
       
   618 		/* ### use a different exception type/message? */
       
   619 		PyErr_SetString(PyExc_TypeError,
       
   620 				"single-segment buffer object expected");
       
   621 		return -1;
       
   622 	}
       
   623 	if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
       
   624 		return -1;
       
   625 	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
       
   626 		return -1;
       
   627 
       
   628 	if ( left < 0 )
       
   629 		left = 0;
       
   630 	else if ( left > size )
       
   631 		left = size;
       
   632 	if ( right < left )
       
   633 		right = left;
       
   634 	else if ( right > size )
       
   635 		right = size;
       
   636 	slice_len = right - left;
       
   637 
       
   638 	if ( count != slice_len ) {
       
   639 		PyErr_SetString(
       
   640 			PyExc_TypeError,
       
   641 			"right operand length must match slice length");
       
   642 		return -1;
       
   643 	}
       
   644 
       
   645 	if ( slice_len )
       
   646 	    memcpy((char *)ptr1 + left, ptr2, slice_len);
       
   647 
       
   648 	return 0;
       
   649 }
       
   650 
       
   651 static int
       
   652 buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
       
   653 {
       
   654 	PyBufferProcs *pb;
       
   655 	void *ptr1, *ptr2;
       
   656 	Py_ssize_t selfsize;
       
   657 	Py_ssize_t othersize;
       
   658 
       
   659 	if ( self->b_readonly ) {
       
   660 		PyErr_SetString(PyExc_TypeError,
       
   661 				"buffer is read-only");
       
   662 		return -1;
       
   663 	}
       
   664 
       
   665 	pb = value ? value->ob_type->tp_as_buffer : NULL;
       
   666 	if ( pb == NULL ||
       
   667 	     pb->bf_getreadbuffer == NULL ||
       
   668 	     pb->bf_getsegcount == NULL )
       
   669 	{
       
   670 		PyErr_BadArgument();
       
   671 		return -1;
       
   672 	}
       
   673 	if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
       
   674 	{
       
   675 		/* ### use a different exception type/message? */
       
   676 		PyErr_SetString(PyExc_TypeError,
       
   677 				"single-segment buffer object expected");
       
   678 		return -1;
       
   679 	}
       
   680 	if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
       
   681 		return -1;
       
   682 	if (PyIndex_Check(item)) {
       
   683 		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
       
   684 		if (i == -1 && PyErr_Occurred())
       
   685 			return -1;
       
   686 		if (i < 0)
       
   687 			i += selfsize;
       
   688 		return buffer_ass_item(self, i, value);
       
   689 	}
       
   690 	else if (PySlice_Check(item)) {
       
   691 		Py_ssize_t start, stop, step, slicelength;
       
   692 		
       
   693 		if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
       
   694 				&start, &stop, &step, &slicelength) < 0)
       
   695 			return -1;
       
   696 
       
   697 		if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
       
   698 			return -1;
       
   699 
       
   700 		if (othersize != slicelength) {
       
   701 			PyErr_SetString(
       
   702 				PyExc_TypeError,
       
   703 				"right operand length must match slice length");
       
   704 			return -1;
       
   705 		}
       
   706 
       
   707 		if (slicelength == 0)
       
   708 			return 0;
       
   709 		else if (step == 1) {
       
   710 			memcpy((char *)ptr1 + start, ptr2, slicelength);
       
   711 			return 0;
       
   712 		}
       
   713 		else {
       
   714 			Py_ssize_t cur, i;
       
   715 			
       
   716 			for (cur = start, i = 0; i < slicelength;
       
   717 			     cur += step, i++) {
       
   718 				((char *)ptr1)[cur] = ((char *)ptr2)[i];
       
   719 			}
       
   720 
       
   721 			return 0;
       
   722 		}
       
   723 	} else {
       
   724 		PyErr_SetString(PyExc_TypeError,
       
   725 				"buffer indices must be integers");
       
   726 		return -1;
       
   727 	}
       
   728 }
       
   729 
       
   730 /* Buffer methods */
       
   731 
       
   732 static Py_ssize_t
       
   733 buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
       
   734 {
       
   735 	Py_ssize_t size;
       
   736 	if ( idx != 0 ) {
       
   737 		PyErr_SetString(PyExc_SystemError,
       
   738 				"accessing non-existent buffer segment");
       
   739 		return -1;
       
   740 	}
       
   741 	if (!get_buf(self, pp, &size, READ_BUFFER))
       
   742 		return -1;
       
   743 	return size;
       
   744 }
       
   745 
       
   746 static Py_ssize_t
       
   747 buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
       
   748 {
       
   749 	Py_ssize_t size;
       
   750 
       
   751 	if ( self->b_readonly )
       
   752 	{
       
   753 		PyErr_SetString(PyExc_TypeError, "buffer is read-only");
       
   754 		return -1;
       
   755 	}
       
   756 
       
   757 	if ( idx != 0 ) {
       
   758 		PyErr_SetString(PyExc_SystemError,
       
   759 				"accessing non-existent buffer segment");
       
   760 		return -1;
       
   761 	}
       
   762 	if (!get_buf(self, pp, &size, WRITE_BUFFER))
       
   763 		return -1;
       
   764 	return size;
       
   765 }
       
   766 
       
   767 static Py_ssize_t
       
   768 buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
       
   769 {
       
   770 	void *ptr;
       
   771 	Py_ssize_t size;
       
   772 	if (!get_buf(self, &ptr, &size, ANY_BUFFER))
       
   773 		return -1;
       
   774 	if (lenp)
       
   775 		*lenp = size;
       
   776 	return 1;
       
   777 }
       
   778 
       
   779 static Py_ssize_t
       
   780 buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
       
   781 {
       
   782 	void *ptr;
       
   783 	Py_ssize_t size;
       
   784 	if ( idx != 0 ) {
       
   785 		PyErr_SetString(PyExc_SystemError,
       
   786 				"accessing non-existent buffer segment");
       
   787 		return -1;
       
   788 	}
       
   789 	if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
       
   790 		return -1;
       
   791 	*pp = (const char *)ptr;
       
   792 	return size;
       
   793 }
       
   794 
       
   795 static PySequenceMethods buffer_as_sequence = {
       
   796 	(lenfunc)buffer_length, /*sq_length*/
       
   797 	(binaryfunc)buffer_concat, /*sq_concat*/
       
   798 	(ssizeargfunc)buffer_repeat, /*sq_repeat*/
       
   799 	(ssizeargfunc)buffer_item, /*sq_item*/
       
   800 	(ssizessizeargfunc)buffer_slice, /*sq_slice*/
       
   801 	(ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
       
   802 	(ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
       
   803 };
       
   804 
       
   805 static PyMappingMethods buffer_as_mapping = {
       
   806 	(lenfunc)buffer_length,
       
   807 	(binaryfunc)buffer_subscript,
       
   808 	(objobjargproc)buffer_ass_subscript,
       
   809 };
       
   810 
       
   811 static PyBufferProcs buffer_as_buffer = {
       
   812 	(readbufferproc)buffer_getreadbuf,
       
   813 	(writebufferproc)buffer_getwritebuf,
       
   814 	(segcountproc)buffer_getsegcount,
       
   815 	(charbufferproc)buffer_getcharbuf,
       
   816 };
       
   817 
       
   818 PyTypeObject PyBuffer_Type = {
       
   819 	PyVarObject_HEAD_INIT(&PyType_Type, 0)
       
   820 	"buffer",
       
   821 	sizeof(PyBufferObject),
       
   822 	0,
       
   823 	(destructor)buffer_dealloc, 		/* tp_dealloc */
       
   824 	0,					/* tp_print */
       
   825 	0,					/* tp_getattr */
       
   826 	0,					/* tp_setattr */
       
   827 	(cmpfunc)buffer_compare,		/* tp_compare */
       
   828 	(reprfunc)buffer_repr,			/* tp_repr */
       
   829 	0,					/* tp_as_number */
       
   830 	&buffer_as_sequence,			/* tp_as_sequence */
       
   831 	&buffer_as_mapping,			/* tp_as_mapping */
       
   832 	(hashfunc)buffer_hash,			/* tp_hash */
       
   833 	0,					/* tp_call */
       
   834 	(reprfunc)buffer_str,			/* tp_str */
       
   835 	PyObject_GenericGetAttr,		/* tp_getattro */
       
   836 	0,					/* tp_setattro */
       
   837 	&buffer_as_buffer,			/* tp_as_buffer */
       
   838 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
       
   839 	buffer_doc,				/* tp_doc */
       
   840 	0,					/* tp_traverse */
       
   841 	0,					/* tp_clear */
       
   842 	0,					/* tp_richcompare */
       
   843 	0,					/* tp_weaklistoffset */
       
   844 	0,					/* tp_iter */
       
   845 	0,					/* tp_iternext */
       
   846 	0,					/* tp_methods */	
       
   847 	0,					/* tp_members */
       
   848 	0,					/* tp_getset */
       
   849 	0,					/* tp_base */
       
   850 	0,					/* tp_dict */
       
   851 	0,					/* tp_descr_get */
       
   852 	0,					/* tp_descr_set */
       
   853 	0,					/* tp_dictoffset */
       
   854 	0,					/* tp_init */
       
   855 	0,					/* tp_alloc */
       
   856 	buffer_new,				/* tp_new */
       
   857 };