2007-11-21 15:29:53 -04:00
|
|
|
/* PyBytes (bytearray) implementation */
|
2006-04-22 20:28:04 -03:00
|
|
|
|
|
|
|
#define PY_SSIZE_T_CLEAN
|
|
|
|
#include "Python.h"
|
2006-05-05 01:34:18 -03:00
|
|
|
#include "structmember.h"
|
2007-10-16 03:31:30 -03:00
|
|
|
#include "bytes_methods.h"
|
2006-04-22 20:28:04 -03:00
|
|
|
|
2007-02-27 15:02:19 -04:00
|
|
|
static PyBytesObject *nullbytes = NULL;
|
|
|
|
|
|
|
|
void
|
|
|
|
PyBytes_Fini(void)
|
|
|
|
{
|
|
|
|
Py_CLEAR(nullbytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
PyBytes_Init(void)
|
|
|
|
{
|
|
|
|
nullbytes = PyObject_New(PyBytesObject, &PyBytes_Type);
|
|
|
|
if (nullbytes == NULL)
|
|
|
|
return 0;
|
|
|
|
nullbytes->ob_bytes = NULL;
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(nullbytes) = nullbytes->ob_alloc = 0;
|
2007-08-18 08:21:56 -03:00
|
|
|
nullbytes->ob_exports = 0;
|
2007-02-27 15:02:19 -04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* end nullbytes support */
|
|
|
|
|
2007-04-12 22:39:34 -03:00
|
|
|
/* Helpers */
|
|
|
|
|
|
|
|
static int
|
|
|
|
_getbytevalue(PyObject* arg, int *value)
|
2007-02-27 15:02:19 -04:00
|
|
|
{
|
2007-10-16 03:31:30 -03:00
|
|
|
long face_value;
|
|
|
|
|
2007-12-02 10:31:20 -04:00
|
|
|
if (PyLong_Check(arg)) {
|
|
|
|
face_value = PyLong_AsLong(arg);
|
2007-10-16 03:31:30 -03:00
|
|
|
if (face_value < 0 || face_value >= 256) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PyErr_Format(PyExc_TypeError, "an integer is required");
|
2007-02-27 15:02:19 -04:00
|
|
|
return 0;
|
|
|
|
}
|
2007-10-16 03:31:30 -03:00
|
|
|
|
|
|
|
*value = face_value;
|
2007-02-27 15:02:19 -04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
static int
|
2007-09-22 23:00:13 -03:00
|
|
|
bytes_getbuffer(PyBytesObject *obj, Py_buffer *view, int flags)
|
2007-08-24 14:33:11 -03:00
|
|
|
{
|
2008-04-14 17:53:13 -03:00
|
|
|
int ret;
|
|
|
|
void *ptr;
|
|
|
|
if (view == NULL) {
|
|
|
|
obj->ob_exports++;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (obj->ob_bytes == NULL)
|
|
|
|
ptr = "";
|
|
|
|
else
|
|
|
|
ptr = obj->ob_bytes;
|
|
|
|
ret = PyBuffer_FillInfo(view, ptr, Py_SIZE(obj), 0, flags);
|
|
|
|
if (ret >= 0) {
|
|
|
|
obj->ob_exports++;
|
|
|
|
}
|
|
|
|
return ret;
|
2007-08-18 08:21:56 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-09-22 23:00:13 -03:00
|
|
|
bytes_releasebuffer(PyBytesObject *obj, Py_buffer *view)
|
2007-08-18 08:21:56 -03:00
|
|
|
{
|
2008-04-14 17:53:13 -03:00
|
|
|
obj->ob_exports--;
|
2007-08-18 08:21:56 -03:00
|
|
|
}
|
|
|
|
|
2007-08-27 03:19:22 -03:00
|
|
|
static Py_ssize_t
|
2007-09-22 23:00:13 -03:00
|
|
|
_getbuffer(PyObject *obj, Py_buffer *view)
|
2007-04-12 22:39:34 -03:00
|
|
|
{
|
2007-12-18 22:45:37 -04:00
|
|
|
PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer;
|
2007-04-12 22:39:34 -03:00
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
if (buffer == NULL || buffer->bf_getbuffer == NULL)
|
2007-08-29 01:05:57 -03:00
|
|
|
{
|
|
|
|
PyErr_Format(PyExc_TypeError,
|
|
|
|
"Type %.100s doesn't support the buffer API",
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_TYPE(obj)->tp_name);
|
2007-08-29 01:05:57 -03:00
|
|
|
return -1;
|
|
|
|
}
|
2007-04-12 22:39:34 -03:00
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
|
|
|
|
return -1;
|
|
|
|
return view->len;
|
2007-04-12 22:39:34 -03:00
|
|
|
}
|
|
|
|
|
2006-04-22 20:28:04 -03:00
|
|
|
/* Direct API functions */
|
|
|
|
|
|
|
|
PyObject *
|
2006-04-24 10:47:05 -03:00
|
|
|
PyBytes_FromObject(PyObject *input)
|
|
|
|
{
|
|
|
|
return PyObject_CallFunctionObjArgs((PyObject *)&PyBytes_Type,
|
|
|
|
input, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *
|
|
|
|
PyBytes_FromStringAndSize(const char *bytes, Py_ssize_t size)
|
2006-04-22 20:28:04 -03:00
|
|
|
{
|
|
|
|
PyBytesObject *new;
|
2007-10-26 03:44:10 -03:00
|
|
|
Py_ssize_t alloc;
|
2006-04-22 20:28:04 -03:00
|
|
|
|
Merged revisions 62260-62261,62266,62271,62277-62279,62289-62290,62293-62298,62302-62306,62308,62311,62313-62315,62319-62321 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r62260 | gregory.p.smith | 2008-04-10 01:11:56 +0200 (Thu, 10 Apr 2008) | 2 lines
better diagnostics
........
r62261 | gregory.p.smith | 2008-04-10 01:16:37 +0200 (Thu, 10 Apr 2008) | 3 lines
Raise SystemError when size < 0 is passed into PyString_FromStringAndSize,
PyBytes_FromStringAndSize or PyUnicode_FromStringAndSize. [issue2587]
........
r62266 | neal.norwitz | 2008-04-10 07:46:39 +0200 (Thu, 10 Apr 2008) | 5 lines
Remove the test file before writing it in case there is no write permission.
This might help fix some of the failures on Windows box(es). It doesn't hurt
either way and ensure the tests are a little more self contained (ie have
less assumptions).
........
r62271 | gregory.p.smith | 2008-04-10 21:50:36 +0200 (Thu, 10 Apr 2008) | 2 lines
get rid of assert (size >= 0) now that an explicit if (size < 0) is in the code.
........
r62277 | andrew.kuchling | 2008-04-10 23:27:10 +0200 (Thu, 10 Apr 2008) | 1 line
Remove forward-looking statement
........
r62278 | andrew.kuchling | 2008-04-10 23:28:51 +0200 (Thu, 10 Apr 2008) | 1 line
Add punctuation
........
r62279 | andrew.kuchling | 2008-04-10 23:29:01 +0200 (Thu, 10 Apr 2008) | 1 line
Use issue directive
........
r62289 | thomas.heller | 2008-04-11 15:05:38 +0200 (Fri, 11 Apr 2008) | 3 lines
Move backwards compatibility macro to the correct place;
PyIndex_Check() was introduced in Python 2.5.
........
r62290 | thomas.heller | 2008-04-11 16:20:26 +0200 (Fri, 11 Apr 2008) | 2 lines
Performance improvements.
........
r62293 | christian.heimes | 2008-04-12 15:03:03 +0200 (Sat, 12 Apr 2008) | 2 lines
Applied patch #2617 from Frank Wierzbicki wit some extras from me
-J and -X are now reserved for Jython and non-standard arguments (e.g. IronPython). I've added some extra comments to make sure the reservation don't get missed in the future.
........
r62294 | georg.brandl | 2008-04-12 20:11:18 +0200 (Sat, 12 Apr 2008) | 2 lines
Use absolute path in sys.path.
........
r62295 | georg.brandl | 2008-04-12 20:36:09 +0200 (Sat, 12 Apr 2008) | 2 lines
#2615: small consistency update by Jeroen Ruigrok van der Werven.
........
r62296 | georg.brandl | 2008-04-12 21:00:20 +0200 (Sat, 12 Apr 2008) | 2 lines
Add Jeroen.
........
r62297 | georg.brandl | 2008-04-12 21:05:37 +0200 (Sat, 12 Apr 2008) | 2 lines
Don't offend snake lovers.
........
r62298 | gregory.p.smith | 2008-04-12 22:37:48 +0200 (Sat, 12 Apr 2008) | 2 lines
fix compiler warnings
........
r62302 | gregory.p.smith | 2008-04-13 00:24:04 +0200 (Sun, 13 Apr 2008) | 3 lines
socket.error inherits from IOError, it no longer needs listing in
the all_errors tuple.
........
r62303 | brett.cannon | 2008-04-13 01:44:07 +0200 (Sun, 13 Apr 2008) | 8 lines
Re-implement the 'warnings' module in C. This allows for usage of the
'warnings' code in places where it was previously not possible (e.g., the
parser). It could also potentially lead to a speed-up in interpreter start-up
if the C version of the code (_warnings) is imported over the use of the
Python version in key places.
Closes issue #1631171.
........
r62304 | gregory.p.smith | 2008-04-13 02:03:25 +0200 (Sun, 13 Apr 2008) | 3 lines
Adds a profile-opt target for easy compilation of a python binary using
gcc's profile guided optimization.
........
r62305 | brett.cannon | 2008-04-13 02:18:44 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix a bug in PySys_HasWarnOption() where it was not properly checking the
length of the list storing the warning options.
........
r62306 | brett.cannon | 2008-04-13 02:25:15 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix an accidental bug of an non-existent init function.
........
r62308 | andrew.kuchling | 2008-04-13 03:05:59 +0200 (Sun, 13 Apr 2008) | 1 line
Mention -J, -X
........
r62311 | benjamin.peterson | 2008-04-13 04:20:05 +0200 (Sun, 13 Apr 2008) | 2 lines
Give the "Interactive Interpreter Changes" section in 2.6 whatsnew a unique link name
........
r62313 | brett.cannon | 2008-04-13 04:42:36 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix test_warnings by making the state of things more consistent for each test
when it is run.
........
r62314 | skip.montanaro | 2008-04-13 05:17:30 +0200 (Sun, 13 Apr 2008) | 2 lines
spelling
........
r62315 | georg.brandl | 2008-04-13 09:07:44 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix markup.
........
r62319 | christian.heimes | 2008-04-13 11:30:17 +0200 (Sun, 13 Apr 2008) | 1 line
Fix compiler warning Include/warnings.h:19:28: warning: no newline at end of file
........
r62320 | christian.heimes | 2008-04-13 11:33:24 +0200 (Sun, 13 Apr 2008) | 1 line
Use PyString_InternFromString instead of PyString_FromString for static vars
........
r62321 | christian.heimes | 2008-04-13 11:37:05 +0200 (Sun, 13 Apr 2008) | 1 line
Added new files to the pcbuild files
........
2008-04-13 10:53:33 -03:00
|
|
|
if (size < 0) {
|
|
|
|
PyErr_SetString(PyExc_SystemError,
|
|
|
|
"Negative size passed to PyBytes_FromStringAndSize");
|
|
|
|
return NULL;
|
|
|
|
}
|
2006-04-22 20:28:04 -03:00
|
|
|
|
|
|
|
new = PyObject_New(PyBytesObject, &PyBytes_Type);
|
|
|
|
if (new == NULL)
|
2006-04-24 10:47:05 -03:00
|
|
|
return NULL;
|
|
|
|
|
2007-05-03 21:41:39 -03:00
|
|
|
if (size == 0) {
|
2006-04-24 10:47:05 -03:00
|
|
|
new->ob_bytes = NULL;
|
2007-05-03 21:41:39 -03:00
|
|
|
alloc = 0;
|
|
|
|
}
|
2006-04-24 10:47:05 -03:00
|
|
|
else {
|
2007-05-03 21:41:39 -03:00
|
|
|
alloc = size + 1;
|
|
|
|
new->ob_bytes = PyMem_Malloc(alloc);
|
2006-04-24 10:47:05 -03:00
|
|
|
if (new->ob_bytes == NULL) {
|
|
|
|
Py_DECREF(new);
|
2007-08-30 02:44:54 -03:00
|
|
|
return PyErr_NoMemory();
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
|
|
|
if (bytes != NULL)
|
|
|
|
memcpy(new->ob_bytes, bytes, size);
|
2007-05-03 21:41:39 -03:00
|
|
|
new->ob_bytes[size] = '\0'; /* Trailing null byte */
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(new) = size;
|
2007-05-03 21:41:39 -03:00
|
|
|
new->ob_alloc = alloc;
|
2007-08-18 08:21:56 -03:00
|
|
|
new->ob_exports = 0;
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-04-22 20:28:04 -03:00
|
|
|
return (PyObject *)new;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_ssize_t
|
|
|
|
PyBytes_Size(PyObject *self)
|
|
|
|
{
|
|
|
|
assert(self != NULL);
|
|
|
|
assert(PyBytes_Check(self));
|
|
|
|
|
2006-05-05 12:15:40 -03:00
|
|
|
return PyBytes_GET_SIZE(self);
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
PyBytes_AsString(PyObject *self)
|
|
|
|
{
|
|
|
|
assert(self != NULL);
|
|
|
|
assert(PyBytes_Check(self));
|
|
|
|
|
2006-05-05 12:15:40 -03:00
|
|
|
return PyBytes_AS_STRING(self);
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
PyBytes_Resize(PyObject *self, Py_ssize_t size)
|
|
|
|
{
|
|
|
|
void *sval;
|
2006-05-05 01:34:18 -03:00
|
|
|
Py_ssize_t alloc = ((PyBytesObject *)self)->ob_alloc;
|
2006-04-22 20:28:04 -03:00
|
|
|
|
|
|
|
assert(self != NULL);
|
|
|
|
assert(PyBytes_Check(self));
|
|
|
|
assert(size >= 0);
|
|
|
|
|
2006-05-05 01:34:18 -03:00
|
|
|
if (size < alloc / 2) {
|
|
|
|
/* Major downsize; resize down to exact size */
|
2007-05-04 01:27:16 -03:00
|
|
|
alloc = size + 1;
|
2006-05-05 01:34:18 -03:00
|
|
|
}
|
2007-05-03 21:41:39 -03:00
|
|
|
else if (size < alloc) {
|
2006-05-05 01:34:18 -03:00
|
|
|
/* Within allocated size; quick exit */
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) = size;
|
2007-08-29 01:05:57 -03:00
|
|
|
((PyBytesObject *)self)->ob_bytes[size] = '\0'; /* Trailing null */
|
2006-05-05 01:34:18 -03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (size <= alloc * 1.125) {
|
|
|
|
/* Moderate upsize; overallocate similar to list_resize() */
|
|
|
|
alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Major upsize; resize up to exact size */
|
2007-05-03 21:41:39 -03:00
|
|
|
alloc = size + 1;
|
2007-05-04 01:27:16 -03:00
|
|
|
}
|
2006-05-05 01:34:18 -03:00
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
if (((PyBytesObject *)self)->ob_exports > 0) {
|
|
|
|
/*
|
2007-08-29 01:05:57 -03:00
|
|
|
fprintf(stderr, "%d: %s", ((PyBytesObject *)self)->ob_exports,
|
|
|
|
((PyBytesObject *)self)->ob_bytes);
|
2007-08-18 08:21:56 -03:00
|
|
|
*/
|
|
|
|
PyErr_SetString(PyExc_BufferError,
|
2007-08-29 01:05:57 -03:00
|
|
|
"Existing exports of data: object cannot be re-sized");
|
2007-08-18 08:21:56 -03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2006-05-05 01:34:18 -03:00
|
|
|
sval = PyMem_Realloc(((PyBytesObject *)self)->ob_bytes, alloc);
|
2006-04-22 20:28:04 -03:00
|
|
|
if (sval == NULL) {
|
2006-04-24 10:47:05 -03:00
|
|
|
PyErr_NoMemory();
|
|
|
|
return -1;
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
((PyBytesObject *)self)->ob_bytes = sval;
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) = size;
|
2006-05-05 01:34:18 -03:00
|
|
|
((PyBytesObject *)self)->ob_alloc = alloc;
|
2007-05-03 21:41:39 -03:00
|
|
|
((PyBytesObject *)self)->ob_bytes[size] = '\0'; /* Trailing null byte */
|
|
|
|
|
2006-04-22 20:28:04 -03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-04-12 22:39:34 -03:00
|
|
|
PyObject *
|
|
|
|
PyBytes_Concat(PyObject *a, PyObject *b)
|
2006-04-24 10:47:05 -03:00
|
|
|
{
|
2007-08-18 08:21:56 -03:00
|
|
|
Py_ssize_t size;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer va, vb;
|
2007-11-06 17:34:58 -04:00
|
|
|
PyBytesObject *result = NULL;
|
2006-04-24 10:47:05 -03:00
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
va.len = -1;
|
|
|
|
vb.len = -1;
|
|
|
|
if (_getbuffer(a, &va) < 0 ||
|
|
|
|
_getbuffer(b, &vb) < 0) {
|
|
|
|
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
|
2007-11-06 17:34:58 -04:00
|
|
|
goto done;
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
size = va.len + vb.len;
|
|
|
|
if (size < 0) {
|
|
|
|
return PyErr_NoMemory();
|
2007-11-06 17:34:58 -04:00
|
|
|
goto done;
|
2007-08-18 08:21:56 -03:00
|
|
|
}
|
2007-04-12 22:39:34 -03:00
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, size);
|
|
|
|
if (result != NULL) {
|
2007-08-18 08:21:56 -03:00
|
|
|
memcpy(result->ob_bytes, va.buf, va.len);
|
|
|
|
memcpy(result->ob_bytes + va.len, vb.buf, vb.len);
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
2007-08-24 14:33:11 -03:00
|
|
|
|
2007-11-06 17:34:58 -04:00
|
|
|
done:
|
|
|
|
if (va.len != -1)
|
|
|
|
PyObject_ReleaseBuffer(a, &va);
|
|
|
|
if (vb.len != -1)
|
|
|
|
PyObject_ReleaseBuffer(b, &vb);
|
2006-04-24 10:47:05 -03:00
|
|
|
return (PyObject *)result;
|
|
|
|
}
|
|
|
|
|
2007-04-12 22:39:34 -03:00
|
|
|
/* Functions stuffed into the type object */
|
|
|
|
|
|
|
|
static Py_ssize_t
|
|
|
|
bytes_length(PyBytesObject *self)
|
|
|
|
{
|
2007-12-18 22:45:37 -04:00
|
|
|
return Py_SIZE(self);
|
2007-04-12 22:39:34 -03:00
|
|
|
}
|
|
|
|
|
2006-04-27 19:54:26 -03:00
|
|
|
static PyObject *
|
|
|
|
bytes_iconcat(PyBytesObject *self, PyObject *other)
|
|
|
|
{
|
2007-04-12 22:39:34 -03:00
|
|
|
Py_ssize_t mysize;
|
2006-04-27 19:54:26 -03:00
|
|
|
Py_ssize_t size;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer vo;
|
2006-04-27 19:54:26 -03:00
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
if (_getbuffer(other, &vo) < 0) {
|
2007-08-29 01:05:57 -03:00
|
|
|
PyErr_Format(PyExc_TypeError, "can't concat bytes to %.100s",
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_TYPE(self)->tp_name);
|
2007-08-29 01:05:57 -03:00
|
|
|
return NULL;
|
2006-04-27 19:54:26 -03:00
|
|
|
}
|
|
|
|
|
2007-12-18 22:45:37 -04:00
|
|
|
mysize = Py_SIZE(self);
|
2007-08-18 08:21:56 -03:00
|
|
|
size = mysize + vo.len;
|
|
|
|
if (size < 0) {
|
2007-08-29 01:05:57 -03:00
|
|
|
PyObject_ReleaseBuffer(other, &vo);
|
|
|
|
return PyErr_NoMemory();
|
2007-08-18 08:21:56 -03:00
|
|
|
}
|
2007-05-04 01:27:16 -03:00
|
|
|
if (size < self->ob_alloc) {
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) = size;
|
|
|
|
self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */
|
2007-05-04 01:27:16 -03:00
|
|
|
}
|
2007-08-18 08:21:56 -03:00
|
|
|
else if (PyBytes_Resize((PyObject *)self, size) < 0) {
|
2007-08-29 01:05:57 -03:00
|
|
|
PyObject_ReleaseBuffer(other, &vo);
|
|
|
|
return NULL;
|
2007-08-18 08:21:56 -03:00
|
|
|
}
|
|
|
|
memcpy(self->ob_bytes + mysize, vo.buf, vo.len);
|
|
|
|
PyObject_ReleaseBuffer(other, &vo);
|
2006-04-27 19:54:26 -03:00
|
|
|
Py_INCREF(self);
|
|
|
|
return (PyObject *)self;
|
|
|
|
}
|
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
static PyObject *
|
|
|
|
bytes_repeat(PyBytesObject *self, Py_ssize_t count)
|
|
|
|
{
|
|
|
|
PyBytesObject *result;
|
|
|
|
Py_ssize_t mysize;
|
|
|
|
Py_ssize_t size;
|
|
|
|
|
|
|
|
if (count < 0)
|
|
|
|
count = 0;
|
2007-12-18 22:45:37 -04:00
|
|
|
mysize = Py_SIZE(self);
|
2006-04-24 10:47:05 -03:00
|
|
|
size = mysize * count;
|
|
|
|
if (count != 0 && size / count != mysize)
|
|
|
|
return PyErr_NoMemory();
|
2007-05-03 21:41:39 -03:00
|
|
|
result = (PyBytesObject *)PyBytes_FromStringAndSize(NULL, size);
|
2006-04-24 10:47:05 -03:00
|
|
|
if (result != NULL && size != 0) {
|
|
|
|
if (mysize == 1)
|
|
|
|
memset(result->ob_bytes, self->ob_bytes[0], size);
|
|
|
|
else {
|
2006-04-27 19:54:26 -03:00
|
|
|
Py_ssize_t i;
|
2006-04-24 10:47:05 -03:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
memcpy(result->ob_bytes + i*mysize, self->ob_bytes, mysize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (PyObject *)result;
|
|
|
|
}
|
|
|
|
|
2006-04-27 19:54:26 -03:00
|
|
|
static PyObject *
|
|
|
|
bytes_irepeat(PyBytesObject *self, Py_ssize_t count)
|
|
|
|
{
|
|
|
|
Py_ssize_t mysize;
|
|
|
|
Py_ssize_t size;
|
|
|
|
|
|
|
|
if (count < 0)
|
|
|
|
count = 0;
|
2007-12-18 22:45:37 -04:00
|
|
|
mysize = Py_SIZE(self);
|
2006-04-27 19:54:26 -03:00
|
|
|
size = mysize * count;
|
|
|
|
if (count != 0 && size / count != mysize)
|
|
|
|
return PyErr_NoMemory();
|
2007-05-04 01:27:16 -03:00
|
|
|
if (size < self->ob_alloc) {
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) = size;
|
|
|
|
self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */
|
2007-05-04 01:27:16 -03:00
|
|
|
}
|
2006-05-05 01:34:18 -03:00
|
|
|
else if (PyBytes_Resize((PyObject *)self, size) < 0)
|
2006-04-27 19:54:26 -03:00
|
|
|
return NULL;
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-04-27 19:54:26 -03:00
|
|
|
if (mysize == 1)
|
|
|
|
memset(self->ob_bytes, self->ob_bytes[0], size);
|
|
|
|
else {
|
|
|
|
Py_ssize_t i;
|
|
|
|
for (i = 1; i < count; i++)
|
|
|
|
memcpy(self->ob_bytes + i*mysize, self->ob_bytes, mysize);
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_INCREF(self);
|
|
|
|
return (PyObject *)self;
|
|
|
|
}
|
|
|
|
|
2006-04-22 20:28:04 -03:00
|
|
|
static PyObject *
|
|
|
|
bytes_getitem(PyBytesObject *self, Py_ssize_t i)
|
|
|
|
{
|
|
|
|
if (i < 0)
|
2007-12-18 22:45:37 -04:00
|
|
|
i += Py_SIZE(self);
|
|
|
|
if (i < 0 || i >= Py_SIZE(self)) {
|
2007-11-21 15:29:53 -04:00
|
|
|
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
|
2006-04-24 10:47:05 -03:00
|
|
|
return NULL;
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
2007-12-02 10:31:20 -04:00
|
|
|
return PyLong_FromLong((unsigned char)(self->ob_bytes[i]));
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
2006-12-19 04:30:14 -04:00
|
|
|
bytes_subscript(PyBytesObject *self, PyObject *item)
|
2006-04-24 10:47:05 -03:00
|
|
|
{
|
2006-12-19 04:30:14 -04:00
|
|
|
if (PyIndex_Check(item)) {
|
|
|
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
2006-04-24 10:47:05 -03:00
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
if (i == -1 && PyErr_Occurred())
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (i < 0)
|
|
|
|
i += PyBytes_GET_SIZE(self);
|
|
|
|
|
2007-12-18 22:45:37 -04:00
|
|
|
if (i < 0 || i >= Py_SIZE(self)) {
|
2007-11-21 15:29:53 -04:00
|
|
|
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
|
2006-12-19 04:30:14 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-12-02 10:31:20 -04:00
|
|
|
return PyLong_FromLong((unsigned char)(self->ob_bytes[i]));
|
2006-12-19 04:30:14 -04:00
|
|
|
}
|
|
|
|
else if (PySlice_Check(item)) {
|
|
|
|
Py_ssize_t start, stop, step, slicelength, cur, i;
|
|
|
|
if (PySlice_GetIndicesEx((PySliceObject *)item,
|
|
|
|
PyBytes_GET_SIZE(self),
|
|
|
|
&start, &stop, &step, &slicelength) < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
if (slicelength <= 0)
|
|
|
|
return PyBytes_FromStringAndSize("", 0);
|
|
|
|
else if (step == 1) {
|
|
|
|
return PyBytes_FromStringAndSize(self->ob_bytes + start,
|
|
|
|
slicelength);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char *source_buf = PyBytes_AS_STRING(self);
|
|
|
|
char *result_buf = (char *)PyMem_Malloc(slicelength);
|
|
|
|
PyObject *result;
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
if (result_buf == NULL)
|
|
|
|
return PyErr_NoMemory();
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
for (cur = start, i = 0; i < slicelength;
|
|
|
|
cur += step, i++) {
|
|
|
|
result_buf[i] = source_buf[cur];
|
|
|
|
}
|
|
|
|
result = PyBytes_FromStringAndSize(result_buf, slicelength);
|
|
|
|
PyMem_Free(result_buf);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2007-11-21 15:29:53 -04:00
|
|
|
PyErr_SetString(PyExc_TypeError, "bytearray indices must be integers");
|
2006-12-19 04:30:14 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
static int
|
2006-12-19 04:30:14 -04:00
|
|
|
bytes_setslice(PyBytesObject *self, Py_ssize_t lo, Py_ssize_t hi,
|
2006-04-24 10:47:05 -03:00
|
|
|
PyObject *values)
|
|
|
|
{
|
2007-04-12 22:39:34 -03:00
|
|
|
Py_ssize_t avail, needed;
|
|
|
|
void *bytes;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer vbytes;
|
2007-08-18 08:21:56 -03:00
|
|
|
int res = 0;
|
2006-04-24 10:47:05 -03:00
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
vbytes.len = -1;
|
2007-04-12 22:39:34 -03:00
|
|
|
if (values == (PyObject *)self) {
|
2007-08-18 08:21:56 -03:00
|
|
|
/* Make a copy and call this function recursively */
|
2006-04-24 10:47:05 -03:00
|
|
|
int err;
|
|
|
|
values = PyBytes_FromObject(values);
|
|
|
|
if (values == NULL)
|
|
|
|
return -1;
|
|
|
|
err = bytes_setslice(self, lo, hi, values);
|
|
|
|
Py_DECREF(values);
|
|
|
|
return err;
|
|
|
|
}
|
2007-04-12 22:39:34 -03:00
|
|
|
if (values == NULL) {
|
|
|
|
/* del b[lo:hi] */
|
|
|
|
bytes = NULL;
|
|
|
|
needed = 0;
|
|
|
|
}
|
2006-04-24 10:47:05 -03:00
|
|
|
else {
|
2007-08-18 08:21:56 -03:00
|
|
|
if (_getbuffer(values, &vbytes) < 0) {
|
|
|
|
PyErr_Format(PyExc_TypeError,
|
|
|
|
"can't set bytes slice from %.100s",
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_TYPE(values)->tp_name);
|
2007-08-18 08:21:56 -03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
needed = vbytes.len;
|
|
|
|
bytes = vbytes.buf;
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (lo < 0)
|
|
|
|
lo = 0;
|
2006-08-23 20:20:29 -03:00
|
|
|
if (hi < lo)
|
|
|
|
hi = lo;
|
2007-12-18 22:45:37 -04:00
|
|
|
if (hi > Py_SIZE(self))
|
|
|
|
hi = Py_SIZE(self);
|
2006-04-24 10:47:05 -03:00
|
|
|
|
|
|
|
avail = hi - lo;
|
|
|
|
if (avail < 0)
|
|
|
|
lo = hi = avail = 0;
|
|
|
|
|
|
|
|
if (avail != needed) {
|
|
|
|
if (avail > needed) {
|
|
|
|
/*
|
|
|
|
0 lo hi old_size
|
|
|
|
| |<----avail----->|<-----tomove------>|
|
|
|
|
| |<-needed->|<-----tomove------>|
|
|
|
|
0 lo new_hi new_size
|
|
|
|
*/
|
|
|
|
memmove(self->ob_bytes + lo + needed, self->ob_bytes + hi,
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) - hi);
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
2007-08-29 01:05:57 -03:00
|
|
|
/* XXX(nnorwitz): need to verify this can't overflow! */
|
2006-12-19 04:30:14 -04:00
|
|
|
if (PyBytes_Resize((PyObject *)self,
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) + needed - avail) < 0) {
|
2007-08-18 08:21:56 -03:00
|
|
|
res = -1;
|
|
|
|
goto finish;
|
|
|
|
}
|
2006-04-24 10:47:05 -03:00
|
|
|
if (avail < needed) {
|
|
|
|
/*
|
|
|
|
0 lo hi old_size
|
|
|
|
| |<-avail->|<-----tomove------>|
|
|
|
|
| |<----needed---->|<-----tomove------>|
|
|
|
|
0 lo new_hi new_size
|
|
|
|
*/
|
|
|
|
memmove(self->ob_bytes + lo + needed, self->ob_bytes + hi,
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) - lo - needed);
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needed > 0)
|
|
|
|
memcpy(self->ob_bytes + lo, bytes, needed);
|
|
|
|
|
2007-08-24 14:33:11 -03:00
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
finish:
|
2007-08-24 14:33:11 -03:00
|
|
|
if (vbytes.len != -1)
|
2007-08-18 08:21:56 -03:00
|
|
|
PyObject_ReleaseBuffer(values, &vbytes);
|
|
|
|
return res;
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
bytes_setitem(PyBytesObject *self, Py_ssize_t i, PyObject *value)
|
|
|
|
{
|
|
|
|
Py_ssize_t ival;
|
|
|
|
|
|
|
|
if (i < 0)
|
2007-12-18 22:45:37 -04:00
|
|
|
i += Py_SIZE(self);
|
2006-04-24 10:47:05 -03:00
|
|
|
|
2007-12-18 22:45:37 -04:00
|
|
|
if (i < 0 || i >= Py_SIZE(self)) {
|
2007-11-21 15:29:53 -04:00
|
|
|
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
|
2006-04-24 10:47:05 -03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value == NULL)
|
|
|
|
return bytes_setslice(self, i, i+1, NULL);
|
|
|
|
|
2006-08-22 10:41:17 -03:00
|
|
|
ival = PyNumber_AsSsize_t(value, PyExc_ValueError);
|
2006-04-24 10:47:05 -03:00
|
|
|
if (ival == -1 && PyErr_Occurred())
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (ival < 0 || ival >= 256) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
self->ob_bytes[i] = ival;
|
|
|
|
return 0;
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
static int
|
|
|
|
bytes_ass_subscript(PyBytesObject *self, PyObject *item, PyObject *values)
|
|
|
|
{
|
|
|
|
Py_ssize_t start, stop, step, slicelen, needed;
|
|
|
|
char *bytes;
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
if (PyIndex_Check(item)) {
|
|
|
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
|
|
|
|
|
|
|
if (i == -1 && PyErr_Occurred())
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (i < 0)
|
|
|
|
i += PyBytes_GET_SIZE(self);
|
|
|
|
|
2007-12-18 22:45:37 -04:00
|
|
|
if (i < 0 || i >= Py_SIZE(self)) {
|
2007-11-21 15:29:53 -04:00
|
|
|
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
|
2006-12-19 04:30:14 -04:00
|
|
|
return -1;
|
|
|
|
}
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
if (values == NULL) {
|
|
|
|
/* Fall through to slice assignment */
|
|
|
|
start = i;
|
|
|
|
stop = i + 1;
|
|
|
|
step = 1;
|
|
|
|
slicelen = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Py_ssize_t ival = PyNumber_AsSsize_t(values, PyExc_ValueError);
|
|
|
|
if (ival == -1 && PyErr_Occurred())
|
|
|
|
return -1;
|
|
|
|
if (ival < 0 || ival >= 256) {
|
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"byte must be in range(0, 256)");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
self->ob_bytes[i] = (char)ival;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (PySlice_Check(item)) {
|
|
|
|
if (PySlice_GetIndicesEx((PySliceObject *)item,
|
|
|
|
PyBytes_GET_SIZE(self),
|
|
|
|
&start, &stop, &step, &slicelen) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2007-11-21 15:29:53 -04:00
|
|
|
PyErr_SetString(PyExc_TypeError, "bytearray indices must be integer");
|
2006-12-19 04:30:14 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (values == NULL) {
|
|
|
|
bytes = NULL;
|
|
|
|
needed = 0;
|
|
|
|
}
|
|
|
|
else if (values == (PyObject *)self || !PyBytes_Check(values)) {
|
|
|
|
/* Make a copy an call this function recursively */
|
|
|
|
int err;
|
|
|
|
values = PyBytes_FromObject(values);
|
|
|
|
if (values == NULL)
|
|
|
|
return -1;
|
|
|
|
err = bytes_ass_subscript(self, item, values);
|
|
|
|
Py_DECREF(values);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
assert(PyBytes_Check(values));
|
|
|
|
bytes = ((PyBytesObject *)values)->ob_bytes;
|
2007-12-18 22:45:37 -04:00
|
|
|
needed = Py_SIZE(values);
|
2006-12-19 04:30:14 -04:00
|
|
|
}
|
|
|
|
/* Make sure b[5:2] = ... inserts before 5, not before 2. */
|
|
|
|
if ((step < 0 && start < stop) ||
|
|
|
|
(step > 0 && start > stop))
|
|
|
|
stop = start;
|
|
|
|
if (step == 1) {
|
|
|
|
if (slicelen != needed) {
|
|
|
|
if (slicelen > needed) {
|
|
|
|
/*
|
|
|
|
0 start stop old_size
|
|
|
|
| |<---slicelen--->|<-----tomove------>|
|
|
|
|
| |<-needed->|<-----tomove------>|
|
|
|
|
0 lo new_hi new_size
|
|
|
|
*/
|
|
|
|
memmove(self->ob_bytes + start + needed, self->ob_bytes + stop,
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) - stop);
|
2006-12-19 04:30:14 -04:00
|
|
|
}
|
|
|
|
if (PyBytes_Resize((PyObject *)self,
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) + needed - slicelen) < 0)
|
2006-12-19 04:30:14 -04:00
|
|
|
return -1;
|
|
|
|
if (slicelen < needed) {
|
|
|
|
/*
|
|
|
|
0 lo hi old_size
|
|
|
|
| |<-avail->|<-----tomove------>|
|
|
|
|
| |<----needed---->|<-----tomove------>|
|
|
|
|
0 lo new_hi new_size
|
|
|
|
*/
|
|
|
|
memmove(self->ob_bytes + start + needed, self->ob_bytes + stop,
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self) - start - needed);
|
2006-12-19 04:30:14 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needed > 0)
|
|
|
|
memcpy(self->ob_bytes + start, bytes, needed);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (needed == 0) {
|
|
|
|
/* Delete slice */
|
|
|
|
Py_ssize_t cur, i;
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
if (step < 0) {
|
|
|
|
stop = start + 1;
|
|
|
|
start = stop + step * (slicelen - 1) - 1;
|
|
|
|
step = -step;
|
|
|
|
}
|
|
|
|
for (cur = start, i = 0;
|
|
|
|
i < slicelen; cur += step, i++) {
|
|
|
|
Py_ssize_t lim = step - 1;
|
|
|
|
|
|
|
|
if (cur + step >= PyBytes_GET_SIZE(self))
|
|
|
|
lim = PyBytes_GET_SIZE(self) - cur - 1;
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
memmove(self->ob_bytes + cur - i,
|
|
|
|
self->ob_bytes + cur + 1, lim);
|
|
|
|
}
|
|
|
|
/* Move the tail of the bytes, in one chunk */
|
|
|
|
cur = start + slicelen*step;
|
|
|
|
if (cur < PyBytes_GET_SIZE(self)) {
|
|
|
|
memmove(self->ob_bytes + cur - slicelen,
|
|
|
|
self->ob_bytes + cur,
|
|
|
|
PyBytes_GET_SIZE(self) - cur);
|
|
|
|
}
|
|
|
|
if (PyBytes_Resize((PyObject *)self,
|
|
|
|
PyBytes_GET_SIZE(self) - slicelen) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Assign slice */
|
|
|
|
Py_ssize_t cur, i;
|
2007-04-12 19:49:52 -03:00
|
|
|
|
2006-12-19 04:30:14 -04:00
|
|
|
if (needed != slicelen) {
|
|
|
|
PyErr_Format(PyExc_ValueError,
|
|
|
|
"attempt to assign bytes of size %zd "
|
|
|
|
"to extended slice of size %zd",
|
|
|
|
needed, slicelen);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
for (cur = start, i = 0; i < slicelen; cur += step, i++)
|
|
|
|
self->ob_bytes[cur] = bytes[i];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-22 20:28:04 -03:00
|
|
|
static int
|
|
|
|
bytes_init(PyBytesObject *self, PyObject *args, PyObject *kwds)
|
|
|
|
{
|
2006-04-24 10:47:05 -03:00
|
|
|
static char *kwlist[] = {"source", "encoding", "errors", 0};
|
2006-04-22 20:28:04 -03:00
|
|
|
PyObject *arg = NULL;
|
2006-04-24 10:47:05 -03:00
|
|
|
const char *encoding = NULL;
|
|
|
|
const char *errors = NULL;
|
|
|
|
Py_ssize_t count;
|
|
|
|
PyObject *it;
|
2006-04-22 20:28:04 -03:00
|
|
|
PyObject *(*iternext)(PyObject *);
|
|
|
|
|
2007-12-18 22:45:37 -04:00
|
|
|
if (Py_SIZE(self) != 0) {
|
2006-05-05 01:34:18 -03:00
|
|
|
/* Empty previous contents (yes, do this first of all!) */
|
|
|
|
if (PyBytes_Resize((PyObject *)self, 0) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
2006-04-24 10:47:05 -03:00
|
|
|
|
|
|
|
/* Parse arguments */
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:bytes", kwlist,
|
|
|
|
&arg, &encoding, &errors))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Make a quick exit if no first argument */
|
|
|
|
if (arg == NULL) {
|
|
|
|
if (encoding != NULL || errors != NULL) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"encoding or errors without sequence argument");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2006-04-22 20:28:04 -03:00
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
if (PyUnicode_Check(arg)) {
|
|
|
|
/* Encode via the codec registry */
|
2007-05-04 02:00:04 -03:00
|
|
|
PyObject *encoded, *new;
|
2007-08-29 01:05:57 -03:00
|
|
|
if (encoding == NULL) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"string argument without an encoding");
|
|
|
|
return -1;
|
|
|
|
}
|
2006-04-24 10:47:05 -03:00
|
|
|
encoded = PyCodec_Encode(arg, encoding, errors);
|
|
|
|
if (encoded == NULL)
|
|
|
|
return -1;
|
2007-11-06 17:34:58 -04:00
|
|
|
assert(PyString_Check(encoded));
|
2007-08-29 01:05:57 -03:00
|
|
|
new = bytes_iconcat(self, encoded);
|
|
|
|
Py_DECREF(encoded);
|
|
|
|
if (new == NULL)
|
|
|
|
return -1;
|
|
|
|
Py_DECREF(new);
|
|
|
|
return 0;
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
/* If it's not unicode, there can't be encoding or errors */
|
|
|
|
if (encoding != NULL || errors != NULL) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"encoding or errors without a string argument");
|
|
|
|
return -1;
|
|
|
|
}
|
2006-04-22 20:28:04 -03:00
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
/* Is it an int? */
|
2006-08-22 10:41:17 -03:00
|
|
|
count = PyNumber_AsSsize_t(arg, PyExc_ValueError);
|
2006-04-24 10:47:05 -03:00
|
|
|
if (count == -1 && PyErr_Occurred())
|
|
|
|
PyErr_Clear();
|
|
|
|
else {
|
|
|
|
if (count < 0) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "negative count");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (count > 0) {
|
|
|
|
if (PyBytes_Resize((PyObject *)self, count))
|
|
|
|
return -1;
|
|
|
|
memset(self->ob_bytes, 0, count);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2007-08-24 14:33:11 -03:00
|
|
|
|
2007-11-21 15:29:53 -04:00
|
|
|
/* Use the buffer API */
|
2007-08-18 08:21:56 -03:00
|
|
|
if (PyObject_CheckBuffer(arg)) {
|
2006-04-24 10:47:05 -03:00
|
|
|
Py_ssize_t size;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer view;
|
2007-08-18 08:21:56 -03:00
|
|
|
if (PyObject_GetBuffer(arg, &view, PyBUF_FULL_RO) < 0)
|
2006-04-24 10:47:05 -03:00
|
|
|
return -1;
|
2007-08-18 08:21:56 -03:00
|
|
|
size = view.len;
|
|
|
|
if (PyBytes_Resize((PyObject *)self, size) < 0) goto fail;
|
|
|
|
if (PyBuffer_ToContiguous(self->ob_bytes, &view, size, 'C') < 0)
|
|
|
|
goto fail;
|
|
|
|
PyObject_ReleaseBuffer(arg, &view);
|
2006-04-24 10:47:05 -03:00
|
|
|
return 0;
|
2007-08-18 08:21:56 -03:00
|
|
|
fail:
|
|
|
|
PyObject_ReleaseBuffer(arg, &view);
|
|
|
|
return -1;
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
2006-04-22 20:28:04 -03:00
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
/* XXX Optimize this if the arguments is a list, tuple */
|
2006-04-22 20:28:04 -03:00
|
|
|
|
|
|
|
/* Get the iterator */
|
|
|
|
it = PyObject_GetIter(arg);
|
|
|
|
if (it == NULL)
|
2006-04-24 10:47:05 -03:00
|
|
|
return -1;
|
2007-12-18 22:45:37 -04:00
|
|
|
iternext = *Py_TYPE(it)->tp_iternext;
|
2006-04-22 20:28:04 -03:00
|
|
|
|
|
|
|
/* Run the iterator to exhaustion */
|
|
|
|
for (;;) {
|
2006-04-24 10:47:05 -03:00
|
|
|
PyObject *item;
|
|
|
|
Py_ssize_t value;
|
|
|
|
|
|
|
|
/* Get the next item */
|
|
|
|
item = iternext(it);
|
|
|
|
if (item == NULL) {
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
if (!PyErr_ExceptionMatches(PyExc_StopIteration))
|
|
|
|
goto error;
|
|
|
|
PyErr_Clear();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Interpret it as an int (__index__) */
|
2006-08-22 10:41:17 -03:00
|
|
|
value = PyNumber_AsSsize_t(item, PyExc_ValueError);
|
2006-04-24 10:47:05 -03:00
|
|
|
Py_DECREF(item);
|
|
|
|
if (value == -1 && PyErr_Occurred())
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* Range check */
|
|
|
|
if (value < 0 || value >= 256) {
|
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"bytes must be in range(0, 256)");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append the byte */
|
2007-12-18 22:45:37 -04:00
|
|
|
if (Py_SIZE(self) < self->ob_alloc)
|
|
|
|
Py_SIZE(self)++;
|
|
|
|
else if (PyBytes_Resize((PyObject *)self, Py_SIZE(self)+1) < 0)
|
2006-04-24 10:47:05 -03:00
|
|
|
goto error;
|
2007-12-18 22:45:37 -04:00
|
|
|
self->ob_bytes[Py_SIZE(self)-1] = value;
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean up and return success */
|
|
|
|
Py_DECREF(it);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
/* Error handling when it != NULL */
|
|
|
|
Py_DECREF(it);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-02-24 15:41:35 -04:00
|
|
|
/* Mostly copied from string_repr, but without the
|
|
|
|
"smart quote" functionality. */
|
2006-04-22 20:28:04 -03:00
|
|
|
static PyObject *
|
|
|
|
bytes_repr(PyBytesObject *self)
|
|
|
|
{
|
2007-05-18 14:15:44 -03:00
|
|
|
static const char *hexdigits = "0123456789abcdef";
|
2007-11-21 15:29:53 -04:00
|
|
|
const char *quote_prefix = "bytearray(b";
|
2007-11-06 17:34:58 -04:00
|
|
|
const char *quote_postfix = ")";
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_ssize_t length = Py_SIZE(self);
|
2007-11-21 15:29:53 -04:00
|
|
|
/* 14 == strlen(quote_prefix) + 2 + strlen(quote_postfix) */
|
|
|
|
size_t newsize = 14 + 4 * length;
|
2007-02-24 15:41:35 -04:00
|
|
|
PyObject *v;
|
2007-11-21 15:29:53 -04:00
|
|
|
if (newsize > PY_SSIZE_T_MAX || newsize / 4 - 3 != length) {
|
2007-02-24 15:41:35 -04:00
|
|
|
PyErr_SetString(PyExc_OverflowError,
|
2007-11-21 15:29:53 -04:00
|
|
|
"bytearray object is too large to make repr");
|
2006-04-24 10:47:05 -03:00
|
|
|
return NULL;
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
2007-05-18 14:15:44 -03:00
|
|
|
v = PyUnicode_FromUnicode(NULL, newsize);
|
2007-02-24 15:41:35 -04:00
|
|
|
if (v == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
register Py_ssize_t i;
|
2007-05-18 14:15:44 -03:00
|
|
|
register Py_UNICODE c;
|
|
|
|
register Py_UNICODE *p;
|
2007-11-06 17:34:58 -04:00
|
|
|
int quote;
|
|
|
|
|
|
|
|
/* Figure out which quote to use; single is preferred */
|
|
|
|
quote = '\'';
|
|
|
|
{
|
|
|
|
char *test, *start;
|
|
|
|
start = PyBytes_AS_STRING(self);
|
|
|
|
for (test = start; test < start+length; ++test) {
|
|
|
|
if (*test == '"') {
|
|
|
|
quote = '\''; /* back to single */
|
|
|
|
goto decided;
|
|
|
|
}
|
|
|
|
else if (*test == '\'')
|
|
|
|
quote = '"';
|
|
|
|
}
|
|
|
|
decided:
|
|
|
|
;
|
|
|
|
}
|
2007-02-24 15:41:35 -04:00
|
|
|
|
2007-05-18 14:15:44 -03:00
|
|
|
p = PyUnicode_AS_UNICODE(v);
|
2007-11-06 17:34:58 -04:00
|
|
|
while (*quote_prefix)
|
|
|
|
*p++ = *quote_prefix++;
|
2007-02-24 15:41:35 -04:00
|
|
|
*p++ = quote;
|
2007-11-06 17:34:58 -04:00
|
|
|
|
|
|
|
for (i = 0; i < length; i++) {
|
2007-02-24 15:41:35 -04:00
|
|
|
/* There's at least enough room for a hex escape
|
|
|
|
and a closing quote. */
|
2007-05-18 14:15:44 -03:00
|
|
|
assert(newsize - (p - PyUnicode_AS_UNICODE(v)) >= 5);
|
2007-02-24 15:41:35 -04:00
|
|
|
c = self->ob_bytes[i];
|
2007-11-06 17:34:58 -04:00
|
|
|
if (c == '\'' || c == '\\')
|
2007-02-24 15:41:35 -04:00
|
|
|
*p++ = '\\', *p++ = c;
|
|
|
|
else if (c == '\t')
|
|
|
|
*p++ = '\\', *p++ = 't';
|
|
|
|
else if (c == '\n')
|
|
|
|
*p++ = '\\', *p++ = 'n';
|
|
|
|
else if (c == '\r')
|
|
|
|
*p++ = '\\', *p++ = 'r';
|
|
|
|
else if (c == 0)
|
2007-05-08 16:09:34 -03:00
|
|
|
*p++ = '\\', *p++ = 'x', *p++ = '0', *p++ = '0';
|
2007-02-24 15:41:35 -04:00
|
|
|
else if (c < ' ' || c >= 0x7f) {
|
2007-05-18 14:15:44 -03:00
|
|
|
*p++ = '\\';
|
|
|
|
*p++ = 'x';
|
|
|
|
*p++ = hexdigits[(c & 0xf0) >> 4];
|
|
|
|
*p++ = hexdigits[c & 0xf];
|
2007-02-24 15:41:35 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
*p++ = c;
|
|
|
|
}
|
2007-05-18 14:15:44 -03:00
|
|
|
assert(newsize - (p - PyUnicode_AS_UNICODE(v)) >= 1);
|
2007-02-24 15:41:35 -04:00
|
|
|
*p++ = quote;
|
2007-11-06 17:34:58 -04:00
|
|
|
while (*quote_postfix) {
|
|
|
|
*p++ = *quote_postfix++;
|
|
|
|
}
|
2007-02-24 15:41:35 -04:00
|
|
|
*p = '\0';
|
2007-05-18 14:15:44 -03:00
|
|
|
if (PyUnicode_Resize(&v, (p - PyUnicode_AS_UNICODE(v)))) {
|
|
|
|
Py_DECREF(v);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-02-24 15:41:35 -04:00
|
|
|
return v;
|
|
|
|
}
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
static PyObject *
|
2007-11-06 17:34:58 -04:00
|
|
|
bytes_str(PyObject *op)
|
2006-04-24 10:47:05 -03:00
|
|
|
{
|
2007-11-06 17:34:58 -04:00
|
|
|
if (Py_BytesWarningFlag) {
|
|
|
|
if (PyErr_WarnEx(PyExc_BytesWarning,
|
2007-11-21 15:29:53 -04:00
|
|
|
"str() on a bytearray instance", 1))
|
2007-11-06 17:34:58 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return bytes_repr((PyBytesObject*)op);
|
2006-04-24 10:47:05 -03:00
|
|
|
}
|
|
|
|
|
2006-04-22 20:28:04 -03:00
|
|
|
static PyObject *
|
2007-04-08 21:43:24 -03:00
|
|
|
bytes_richcompare(PyObject *self, PyObject *other, int op)
|
2006-04-22 20:28:04 -03:00
|
|
|
{
|
2007-04-08 21:43:24 -03:00
|
|
|
Py_ssize_t self_size, other_size;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer self_bytes, other_bytes;
|
2006-04-22 20:28:04 -03:00
|
|
|
PyObject *res;
|
2007-04-08 21:43:24 -03:00
|
|
|
Py_ssize_t minsize;
|
2006-04-22 20:28:04 -03:00
|
|
|
int cmp;
|
|
|
|
|
2007-08-29 15:47:16 -03:00
|
|
|
/* Bytes can be compared to anything that supports the (binary)
|
|
|
|
buffer API. Except that a comparison with Unicode is always an
|
|
|
|
error, even if the comparison is for equality. */
|
|
|
|
if (PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type) ||
|
|
|
|
PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type)) {
|
2007-11-06 17:34:58 -04:00
|
|
|
if (Py_BytesWarningFlag && op == Py_EQ) {
|
|
|
|
if (PyErr_WarnEx(PyExc_BytesWarning,
|
2007-11-21 15:29:53 -04:00
|
|
|
"Comparsion between bytearray and string", 1))
|
2007-11-06 17:34:58 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-10-09 14:21:10 -03:00
|
|
|
Py_INCREF(Py_NotImplemented);
|
|
|
|
return Py_NotImplemented;
|
2007-08-29 15:47:16 -03:00
|
|
|
}
|
2007-04-08 21:43:24 -03:00
|
|
|
|
2007-04-12 22:39:34 -03:00
|
|
|
self_size = _getbuffer(self, &self_bytes);
|
|
|
|
if (self_size < 0) {
|
2007-08-29 01:05:57 -03:00
|
|
|
PyErr_Clear();
|
2007-04-08 21:43:24 -03:00
|
|
|
Py_INCREF(Py_NotImplemented);
|
|
|
|
return Py_NotImplemented;
|
|
|
|
}
|
|
|
|
|
2007-04-12 22:39:34 -03:00
|
|
|
other_size = _getbuffer(other, &other_bytes);
|
|
|
|
if (other_size < 0) {
|
2007-08-29 01:05:57 -03:00
|
|
|
PyErr_Clear();
|
2007-08-18 08:21:56 -03:00
|
|
|
PyObject_ReleaseBuffer(self, &self_bytes);
|
2006-04-24 10:47:05 -03:00
|
|
|
Py_INCREF(Py_NotImplemented);
|
|
|
|
return Py_NotImplemented;
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
2007-04-08 21:43:24 -03:00
|
|
|
if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
|
2006-04-24 10:47:05 -03:00
|
|
|
/* Shortcut: if the lengths differ, the objects differ */
|
|
|
|
cmp = (op == Py_NE);
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
else {
|
2007-04-08 21:43:24 -03:00
|
|
|
minsize = self_size;
|
|
|
|
if (other_size < minsize)
|
|
|
|
minsize = other_size;
|
2006-04-24 10:47:05 -03:00
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
cmp = memcmp(self_bytes.buf, other_bytes.buf, minsize);
|
2006-04-24 10:47:05 -03:00
|
|
|
/* In ISO C, memcmp() guarantees to use unsigned bytes! */
|
|
|
|
|
|
|
|
if (cmp == 0) {
|
2007-04-08 21:43:24 -03:00
|
|
|
if (self_size < other_size)
|
2006-04-24 10:47:05 -03:00
|
|
|
cmp = -1;
|
2007-04-08 21:43:24 -03:00
|
|
|
else if (self_size > other_size)
|
2006-04-24 10:47:05 -03:00
|
|
|
cmp = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (op) {
|
|
|
|
case Py_LT: cmp = cmp < 0; break;
|
|
|
|
case Py_LE: cmp = cmp <= 0; break;
|
|
|
|
case Py_EQ: cmp = cmp == 0; break;
|
|
|
|
case Py_NE: cmp = cmp != 0; break;
|
|
|
|
case Py_GT: cmp = cmp > 0; break;
|
|
|
|
case Py_GE: cmp = cmp >= 0; break;
|
|
|
|
}
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
res = cmp ? Py_True : Py_False;
|
2007-08-18 08:21:56 -03:00
|
|
|
PyObject_ReleaseBuffer(self, &self_bytes);
|
2007-08-24 14:33:11 -03:00
|
|
|
PyObject_ReleaseBuffer(other, &other_bytes);
|
2006-04-22 20:28:04 -03:00
|
|
|
Py_INCREF(res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bytes_dealloc(PyBytesObject *self)
|
|
|
|
{
|
2006-04-24 10:47:05 -03:00
|
|
|
if (self->ob_bytes != 0) {
|
|
|
|
PyMem_Free(self->ob_bytes);
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_TYPE(self)->tp_free((PyObject *)self);
|
2006-04-22 20:28:04 -03:00
|
|
|
}
|
|
|
|
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Methods */
|
|
|
|
|
|
|
|
#define STRINGLIB_CHAR char
|
|
|
|
#define STRINGLIB_CMP memcmp
|
|
|
|
#define STRINGLIB_LEN PyBytes_GET_SIZE
|
2007-10-16 03:31:30 -03:00
|
|
|
#define STRINGLIB_STR PyBytes_AS_STRING
|
2007-02-27 15:02:19 -04:00
|
|
|
#define STRINGLIB_NEW PyBytes_FromStringAndSize
|
|
|
|
#define STRINGLIB_EMPTY nullbytes
|
2007-10-16 03:31:30 -03:00
|
|
|
#define STRINGLIB_CHECK_EXACT PyBytes_CheckExact
|
|
|
|
#define STRINGLIB_MUTABLE 1
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
#include "stringlib/fastsearch.h"
|
|
|
|
#include "stringlib/count.h"
|
|
|
|
#include "stringlib/find.h"
|
|
|
|
#include "stringlib/partition.h"
|
2007-10-16 03:31:30 -03:00
|
|
|
#include "stringlib/ctype.h"
|
|
|
|
#include "stringlib/transmogrify.h"
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
/* The following Py_LOCAL_INLINE and Py_LOCAL functions
|
|
|
|
were copied from the old char* style string object. */
|
|
|
|
|
|
|
|
Py_LOCAL_INLINE(void)
|
|
|
|
_adjust_indices(Py_ssize_t *start, Py_ssize_t *end, Py_ssize_t len)
|
|
|
|
{
|
|
|
|
if (*end > len)
|
|
|
|
*end = len;
|
|
|
|
else if (*end < 0)
|
|
|
|
*end += len;
|
|
|
|
if (*end < 0)
|
|
|
|
*end = 0;
|
|
|
|
if (*start < 0)
|
|
|
|
*start += len;
|
|
|
|
if (*start < 0)
|
|
|
|
*start = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Py_LOCAL_INLINE(Py_ssize_t)
|
|
|
|
bytes_find_internal(PyBytesObject *self, PyObject *args, int dir)
|
|
|
|
{
|
|
|
|
PyObject *subobj;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer subbuf;
|
2007-02-27 15:02:19 -04:00
|
|
|
Py_ssize_t start=0, end=PY_SSIZE_T_MAX;
|
2007-08-31 10:48:41 -03:00
|
|
|
Py_ssize_t res;
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex", &subobj,
|
|
|
|
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
|
|
|
|
return -2;
|
2007-08-31 10:48:41 -03:00
|
|
|
if (_getbuffer(subobj, &subbuf) < 0)
|
2007-02-27 15:02:19 -04:00
|
|
|
return -2;
|
|
|
|
if (dir > 0)
|
2007-08-31 10:48:41 -03:00
|
|
|
res = stringlib_find_slice(
|
2007-02-27 15:02:19 -04:00
|
|
|
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
|
2007-08-31 10:48:41 -03:00
|
|
|
subbuf.buf, subbuf.len, start, end);
|
2007-02-27 15:02:19 -04:00
|
|
|
else
|
2007-08-31 10:48:41 -03:00
|
|
|
res = stringlib_rfind_slice(
|
2007-02-27 15:02:19 -04:00
|
|
|
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
|
2007-08-31 10:48:41 -03:00
|
|
|
subbuf.buf, subbuf.len, start, end);
|
|
|
|
PyObject_ReleaseBuffer(subobj, &subbuf);
|
|
|
|
return res;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(find__doc__,
|
|
|
|
"B.find(sub [,start [,end]]) -> int\n\
|
|
|
|
\n\
|
|
|
|
Return the lowest index in B where subsection sub is found,\n\
|
|
|
|
such that sub is contained within s[start,end]. Optional\n\
|
|
|
|
arguments start and end are interpreted as in slice notation.\n\
|
|
|
|
\n\
|
|
|
|
Return -1 on failure.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_find(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Py_ssize_t result = bytes_find_internal(self, args, +1);
|
|
|
|
if (result == -2)
|
|
|
|
return NULL;
|
2007-12-02 10:31:20 -04:00
|
|
|
return PyLong_FromSsize_t(result);
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(count__doc__,
|
2007-11-06 17:34:58 -04:00
|
|
|
"B.count(sub [,start [,end]]) -> int\n\
|
2007-02-27 15:02:19 -04:00
|
|
|
\n\
|
|
|
|
Return the number of non-overlapping occurrences of subsection sub in\n\
|
|
|
|
bytes B[start:end]. Optional arguments start and end are interpreted\n\
|
|
|
|
as in slice notation.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_count(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
PyObject *sub_obj;
|
2007-10-16 03:31:30 -03:00
|
|
|
const char *str = PyBytes_AS_STRING(self);
|
2007-02-27 15:02:19 -04:00
|
|
|
Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
|
2007-10-16 03:31:30 -03:00
|
|
|
Py_buffer vsub;
|
|
|
|
PyObject *count_obj;
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "O|O&O&:count", &sub_obj,
|
|
|
|
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
|
|
|
|
return NULL;
|
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
if (_getbuffer(sub_obj, &vsub) < 0)
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
|
|
|
|
2007-06-10 06:51:05 -03:00
|
|
|
_adjust_indices(&start, &end, PyBytes_GET_SIZE(self));
|
2007-02-27 15:02:19 -04:00
|
|
|
|
2007-12-02 10:31:20 -04:00
|
|
|
count_obj = PyLong_FromSsize_t(
|
2007-10-16 03:31:30 -03:00
|
|
|
stringlib_count(str + start, end - start, vsub.buf, vsub.len)
|
2007-02-27 15:02:19 -04:00
|
|
|
);
|
2007-10-16 03:31:30 -03:00
|
|
|
PyObject_ReleaseBuffer(sub_obj, &vsub);
|
|
|
|
return count_obj;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(index__doc__,
|
|
|
|
"B.index(sub [,start [,end]]) -> int\n\
|
|
|
|
\n\
|
|
|
|
Like B.find() but raise ValueError when the subsection is not found.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_index(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Py_ssize_t result = bytes_find_internal(self, args, +1);
|
|
|
|
if (result == -2)
|
|
|
|
return NULL;
|
|
|
|
if (result == -1) {
|
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"subsection not found");
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-12-02 10:31:20 -04:00
|
|
|
return PyLong_FromSsize_t(result);
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(rfind__doc__,
|
|
|
|
"B.rfind(sub [,start [,end]]) -> int\n\
|
|
|
|
\n\
|
|
|
|
Return the highest index in B where subsection sub is found,\n\
|
|
|
|
such that sub is contained within s[start,end]. Optional\n\
|
|
|
|
arguments start and end are interpreted as in slice notation.\n\
|
|
|
|
\n\
|
|
|
|
Return -1 on failure.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_rfind(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Py_ssize_t result = bytes_find_internal(self, args, -1);
|
|
|
|
if (result == -2)
|
|
|
|
return NULL;
|
2007-12-02 10:31:20 -04:00
|
|
|
return PyLong_FromSsize_t(result);
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(rindex__doc__,
|
|
|
|
"B.rindex(sub [,start [,end]]) -> int\n\
|
|
|
|
\n\
|
|
|
|
Like B.rfind() but raise ValueError when the subsection is not found.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_rindex(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Py_ssize_t result = bytes_find_internal(self, args, -1);
|
|
|
|
if (result == -2)
|
|
|
|
return NULL;
|
|
|
|
if (result == -1) {
|
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"subsection not found");
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-12-02 10:31:20 -04:00
|
|
|
return PyLong_FromSsize_t(result);
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-06 17:34:58 -04:00
|
|
|
static int
|
|
|
|
bytes_contains(PyObject *self, PyObject *arg)
|
|
|
|
{
|
|
|
|
Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError);
|
|
|
|
if (ival == -1 && PyErr_Occurred()) {
|
|
|
|
Py_buffer varg;
|
|
|
|
int pos;
|
|
|
|
PyErr_Clear();
|
|
|
|
if (_getbuffer(arg, &varg) < 0)
|
|
|
|
return -1;
|
2007-12-18 22:45:37 -04:00
|
|
|
pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self),
|
2007-11-06 17:34:58 -04:00
|
|
|
varg.buf, varg.len, 0);
|
|
|
|
PyObject_ReleaseBuffer(arg, &varg);
|
|
|
|
return pos >= 0;
|
|
|
|
}
|
|
|
|
if (ival < 0 || ival >= 256) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-12-18 22:45:37 -04:00
|
|
|
return memchr(PyBytes_AS_STRING(self), ival, Py_SIZE(self)) != NULL;
|
2007-11-06 17:34:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-02-27 15:02:19 -04:00
|
|
|
/* Matches the end (direction >= 0) or start (direction < 0) of self
|
|
|
|
* against substr, using the start and end arguments. Returns
|
|
|
|
* -1 on error, 0 if not found and 1 if found.
|
|
|
|
*/
|
|
|
|
Py_LOCAL(int)
|
|
|
|
_bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
|
|
|
|
Py_ssize_t end, int direction)
|
|
|
|
{
|
|
|
|
Py_ssize_t len = PyBytes_GET_SIZE(self);
|
|
|
|
const char* str;
|
2007-10-16 03:31:30 -03:00
|
|
|
Py_buffer vsubstr;
|
2007-10-21 21:09:51 -03:00
|
|
|
int rv = 0;
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
str = PyBytes_AS_STRING(self);
|
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
if (_getbuffer(substr, &vsubstr) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2007-02-27 15:02:19 -04:00
|
|
|
_adjust_indices(&start, &end, len);
|
|
|
|
|
|
|
|
if (direction < 0) {
|
|
|
|
/* startswith */
|
2007-10-16 03:31:30 -03:00
|
|
|
if (start+vsubstr.len > len) {
|
|
|
|
goto done;
|
|
|
|
}
|
2007-02-27 15:02:19 -04:00
|
|
|
} else {
|
|
|
|
/* endswith */
|
2007-10-16 03:31:30 -03:00
|
|
|
if (end-start < vsubstr.len || start > len) {
|
|
|
|
goto done;
|
|
|
|
}
|
2007-02-27 15:02:19 -04:00
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
if (end-vsubstr.len > start)
|
|
|
|
start = end - vsubstr.len;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
2007-10-16 03:31:30 -03:00
|
|
|
if (end-start >= vsubstr.len)
|
|
|
|
rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len);
|
|
|
|
|
|
|
|
done:
|
|
|
|
PyObject_ReleaseBuffer(substr, &vsubstr);
|
|
|
|
return rv;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(startswith__doc__,
|
2007-11-06 17:34:58 -04:00
|
|
|
"B.startswith(prefix [,start [,end]]) -> bool\n\
|
2007-02-27 15:02:19 -04:00
|
|
|
\n\
|
|
|
|
Return True if B starts with the specified prefix, False otherwise.\n\
|
|
|
|
With optional start, test B beginning at that position.\n\
|
|
|
|
With optional end, stop comparing B at that position.\n\
|
|
|
|
prefix can also be a tuple of strings to try.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_startswith(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Py_ssize_t start = 0;
|
|
|
|
Py_ssize_t end = PY_SSIZE_T_MAX;
|
|
|
|
PyObject *subobj;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "O|O&O&:startswith", &subobj,
|
|
|
|
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
|
|
|
|
return NULL;
|
|
|
|
if (PyTuple_Check(subobj)) {
|
|
|
|
Py_ssize_t i;
|
|
|
|
for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
|
|
|
|
result = _bytes_tailmatch(self,
|
|
|
|
PyTuple_GET_ITEM(subobj, i),
|
|
|
|
start, end, -1);
|
|
|
|
if (result == -1)
|
|
|
|
return NULL;
|
|
|
|
else if (result) {
|
|
|
|
Py_RETURN_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
result = _bytes_tailmatch(self, subobj, start, end, -1);
|
|
|
|
if (result == -1)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return PyBool_FromLong(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(endswith__doc__,
|
2007-11-06 17:34:58 -04:00
|
|
|
"B.endswith(suffix [,start [,end]]) -> bool\n\
|
2007-02-27 15:02:19 -04:00
|
|
|
\n\
|
|
|
|
Return True if B ends with the specified suffix, False otherwise.\n\
|
|
|
|
With optional start, test B beginning at that position.\n\
|
|
|
|
With optional end, stop comparing B at that position.\n\
|
|
|
|
suffix can also be a tuple of strings to try.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_endswith(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Py_ssize_t start = 0;
|
|
|
|
Py_ssize_t end = PY_SSIZE_T_MAX;
|
|
|
|
PyObject *subobj;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "O|O&O&:endswith", &subobj,
|
|
|
|
_PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
|
|
|
|
return NULL;
|
|
|
|
if (PyTuple_Check(subobj)) {
|
|
|
|
Py_ssize_t i;
|
|
|
|
for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
|
|
|
|
result = _bytes_tailmatch(self,
|
|
|
|
PyTuple_GET_ITEM(subobj, i),
|
|
|
|
start, end, +1);
|
|
|
|
if (result == -1)
|
|
|
|
return NULL;
|
|
|
|
else if (result) {
|
|
|
|
Py_RETURN_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
result = _bytes_tailmatch(self, subobj, start, end, +1);
|
|
|
|
if (result == -1)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return PyBool_FromLong(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(translate__doc__,
|
2007-11-21 15:29:53 -04:00
|
|
|
"B.translate(table[, deletechars]) -> bytearray\n\
|
2007-02-27 15:02:19 -04:00
|
|
|
\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Return a copy of B, where all characters occurring in the\n\
|
|
|
|
optional argument deletechars are removed, and the remaining\n\
|
|
|
|
characters have been mapped through the given translation\n\
|
|
|
|
table, which must be a bytes object of length 256.");
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_translate(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
register char *input, *output;
|
|
|
|
register const char *table;
|
|
|
|
register Py_ssize_t i, c, changed = 0;
|
|
|
|
PyObject *input_obj = (PyObject*)self;
|
2007-10-16 03:31:30 -03:00
|
|
|
const char *output_start;
|
|
|
|
Py_ssize_t inlen;
|
2007-02-27 15:02:19 -04:00
|
|
|
PyObject *result;
|
|
|
|
int trans_table[256];
|
|
|
|
PyObject *tableobj, *delobj = NULL;
|
2007-10-16 03:31:30 -03:00
|
|
|
Py_buffer vtable, vdel;
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (!PyArg_UnpackTuple(args, "translate", 1, 2,
|
|
|
|
&tableobj, &delobj))
|
|
|
|
return NULL;
|
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
if (_getbuffer(tableobj, &vtable) < 0)
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
if (vtable.len != 256) {
|
2007-02-27 15:02:19 -04:00
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"translation table must be 256 characters long");
|
2007-10-16 03:31:30 -03:00
|
|
|
result = NULL;
|
|
|
|
goto done;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (delobj != NULL) {
|
2007-10-16 03:31:30 -03:00
|
|
|
if (_getbuffer(delobj, &vdel) < 0) {
|
|
|
|
result = NULL;
|
|
|
|
goto done;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2007-10-16 03:31:30 -03:00
|
|
|
vdel.buf = NULL;
|
|
|
|
vdel.len = 0;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
table = (const char *)vtable.buf;
|
2007-02-27 15:02:19 -04:00
|
|
|
inlen = PyBytes_GET_SIZE(input_obj);
|
|
|
|
result = PyBytes_FromStringAndSize((char *)NULL, inlen);
|
|
|
|
if (result == NULL)
|
2007-10-16 03:31:30 -03:00
|
|
|
goto done;
|
2007-02-27 15:02:19 -04:00
|
|
|
output_start = output = PyBytes_AsString(result);
|
|
|
|
input = PyBytes_AS_STRING(input_obj);
|
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
if (vdel.len == 0) {
|
2007-02-27 15:02:19 -04:00
|
|
|
/* If no deletions are required, use faster code */
|
|
|
|
for (i = inlen; --i >= 0; ) {
|
|
|
|
c = Py_CHARMASK(*input++);
|
|
|
|
if (Py_CHARMASK((*output++ = table[c])) != c)
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
if (changed || !PyBytes_CheckExact(input_obj))
|
2007-10-16 03:31:30 -03:00
|
|
|
goto done;
|
2007-02-27 15:02:19 -04:00
|
|
|
Py_DECREF(result);
|
|
|
|
Py_INCREF(input_obj);
|
2007-10-16 03:31:30 -03:00
|
|
|
result = input_obj;
|
|
|
|
goto done;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++)
|
|
|
|
trans_table[i] = Py_CHARMASK(table[i]);
|
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
for (i = 0; i < vdel.len; i++)
|
|
|
|
trans_table[(int) Py_CHARMASK( ((unsigned char*)vdel.buf)[i] )] = -1;
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
for (i = inlen; --i >= 0; ) {
|
|
|
|
c = Py_CHARMASK(*input++);
|
|
|
|
if (trans_table[c] != -1)
|
|
|
|
if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c)
|
|
|
|
continue;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
if (!changed && PyBytes_CheckExact(input_obj)) {
|
|
|
|
Py_DECREF(result);
|
|
|
|
Py_INCREF(input_obj);
|
2007-10-16 03:31:30 -03:00
|
|
|
result = input_obj;
|
|
|
|
goto done;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
/* Fix the size of the resulting string */
|
|
|
|
if (inlen > 0)
|
|
|
|
PyBytes_Resize(result, output - output_start);
|
2007-10-16 03:31:30 -03:00
|
|
|
|
|
|
|
done:
|
|
|
|
PyObject_ReleaseBuffer(tableobj, &vtable);
|
|
|
|
if (delobj != NULL)
|
|
|
|
PyObject_ReleaseBuffer(delobj, &vdel);
|
2007-02-27 15:02:19 -04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define FORWARD 1
|
|
|
|
#define REVERSE -1
|
|
|
|
|
|
|
|
/* find and count characters and substrings */
|
|
|
|
|
|
|
|
#define findchar(target, target_len, c) \
|
|
|
|
((char *)memchr((const void *)(target), c, target_len))
|
|
|
|
|
|
|
|
/* Don't call if length < 2 */
|
|
|
|
#define Py_STRING_MATCH(target, offset, pattern, length) \
|
|
|
|
(target[offset] == pattern[0] && \
|
|
|
|
target[offset+length-1] == pattern[length-1] && \
|
|
|
|
!memcmp(target+offset+1, pattern+1, length-2) )
|
|
|
|
|
|
|
|
|
|
|
|
/* Bytes ops must return a string. */
|
|
|
|
/* If the object is subclass of bytes, create a copy */
|
|
|
|
Py_LOCAL(PyBytesObject *)
|
|
|
|
return_self(PyBytesObject *self)
|
|
|
|
{
|
|
|
|
if (PyBytes_CheckExact(self)) {
|
|
|
|
Py_INCREF(self);
|
|
|
|
return (PyBytesObject *)self;
|
|
|
|
}
|
|
|
|
return (PyBytesObject *)PyBytes_FromStringAndSize(
|
|
|
|
PyBytes_AS_STRING(self),
|
|
|
|
PyBytes_GET_SIZE(self));
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_LOCAL_INLINE(Py_ssize_t)
|
2007-10-26 03:44:10 -03:00
|
|
|
countchar(const char *target, Py_ssize_t target_len, char c, Py_ssize_t maxcount)
|
2007-02-27 15:02:19 -04:00
|
|
|
{
|
|
|
|
Py_ssize_t count=0;
|
|
|
|
const char *start=target;
|
|
|
|
const char *end=target+target_len;
|
|
|
|
|
|
|
|
while ( (start=findchar(start, end-start, c)) != NULL ) {
|
|
|
|
count++;
|
|
|
|
if (count >= maxcount)
|
|
|
|
break;
|
|
|
|
start += 1;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_LOCAL(Py_ssize_t)
|
|
|
|
findstring(const char *target, Py_ssize_t target_len,
|
|
|
|
const char *pattern, Py_ssize_t pattern_len,
|
|
|
|
Py_ssize_t start,
|
|
|
|
Py_ssize_t end,
|
|
|
|
int direction)
|
|
|
|
{
|
|
|
|
if (start < 0) {
|
|
|
|
start += target_len;
|
|
|
|
if (start < 0)
|
|
|
|
start = 0;
|
|
|
|
}
|
|
|
|
if (end > target_len) {
|
|
|
|
end = target_len;
|
|
|
|
} else if (end < 0) {
|
|
|
|
end += target_len;
|
|
|
|
if (end < 0)
|
|
|
|
end = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* zero-length substrings always match at the first attempt */
|
|
|
|
if (pattern_len == 0)
|
|
|
|
return (direction > 0) ? start : end;
|
|
|
|
|
|
|
|
end -= pattern_len;
|
|
|
|
|
|
|
|
if (direction < 0) {
|
|
|
|
for (; end >= start; end--)
|
|
|
|
if (Py_STRING_MATCH(target, end, pattern, pattern_len))
|
|
|
|
return end;
|
|
|
|
} else {
|
|
|
|
for (; start <= end; start++)
|
|
|
|
if (Py_STRING_MATCH(target, start, pattern, pattern_len))
|
|
|
|
return start;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_LOCAL_INLINE(Py_ssize_t)
|
|
|
|
countstring(const char *target, Py_ssize_t target_len,
|
|
|
|
const char *pattern, Py_ssize_t pattern_len,
|
|
|
|
Py_ssize_t start,
|
|
|
|
Py_ssize_t end,
|
|
|
|
int direction, Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
Py_ssize_t count=0;
|
|
|
|
|
|
|
|
if (start < 0) {
|
|
|
|
start += target_len;
|
|
|
|
if (start < 0)
|
|
|
|
start = 0;
|
|
|
|
}
|
|
|
|
if (end > target_len) {
|
|
|
|
end = target_len;
|
|
|
|
} else if (end < 0) {
|
|
|
|
end += target_len;
|
|
|
|
if (end < 0)
|
|
|
|
end = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* zero-length substrings match everywhere */
|
|
|
|
if (pattern_len == 0 || maxcount == 0) {
|
|
|
|
if (target_len+1 < maxcount)
|
|
|
|
return target_len+1;
|
|
|
|
return maxcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
end -= pattern_len;
|
|
|
|
if (direction < 0) {
|
|
|
|
for (; (end >= start); end--)
|
|
|
|
if (Py_STRING_MATCH(target, end, pattern, pattern_len)) {
|
|
|
|
count++;
|
|
|
|
if (--maxcount <= 0) break;
|
|
|
|
end -= pattern_len-1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (; (start <= end); start++)
|
|
|
|
if (Py_STRING_MATCH(target, start, pattern, pattern_len)) {
|
|
|
|
count++;
|
|
|
|
if (--maxcount <= 0)
|
|
|
|
break;
|
|
|
|
start += pattern_len-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Algorithms for different cases of string replacement */
|
|
|
|
|
|
|
|
/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */
|
|
|
|
Py_LOCAL(PyBytesObject *)
|
|
|
|
replace_interleave(PyBytesObject *self,
|
|
|
|
const char *to_s, Py_ssize_t to_len,
|
|
|
|
Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
char *self_s, *result_s;
|
|
|
|
Py_ssize_t self_len, result_len;
|
|
|
|
Py_ssize_t count, i, product;
|
|
|
|
PyBytesObject *result;
|
|
|
|
|
|
|
|
self_len = PyBytes_GET_SIZE(self);
|
|
|
|
|
|
|
|
/* 1 at the end plus 1 after every character */
|
|
|
|
count = self_len+1;
|
2007-04-12 19:49:52 -03:00
|
|
|
if (maxcount < count)
|
2007-02-27 15:02:19 -04:00
|
|
|
count = maxcount;
|
|
|
|
|
|
|
|
/* Check for overflow */
|
|
|
|
/* result_len = count * to_len + self_len; */
|
|
|
|
product = count * to_len;
|
|
|
|
if (product / to_len != count) {
|
|
|
|
PyErr_SetString(PyExc_OverflowError,
|
|
|
|
"replace string is too long");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
result_len = product + self_len;
|
|
|
|
if (result_len < 0) {
|
|
|
|
PyErr_SetString(PyExc_OverflowError,
|
|
|
|
"replace string is too long");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! (result = (PyBytesObject *)
|
|
|
|
PyBytes_FromStringAndSize(NULL, result_len)) )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
self_s = PyBytes_AS_STRING(self);
|
|
|
|
result_s = PyBytes_AS_STRING(result);
|
|
|
|
|
|
|
|
/* TODO: special case single character, which doesn't need memcpy */
|
|
|
|
|
|
|
|
/* Lay the first one down (guaranteed this will occur) */
|
|
|
|
Py_MEMCPY(result_s, to_s, to_len);
|
|
|
|
result_s += to_len;
|
|
|
|
count -= 1;
|
|
|
|
|
|
|
|
for (i=0; i<count; i++) {
|
|
|
|
*result_s++ = *self_s++;
|
|
|
|
Py_MEMCPY(result_s, to_s, to_len);
|
|
|
|
result_s += to_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy the rest of the original string */
|
|
|
|
Py_MEMCPY(result_s, self_s, self_len-i);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Special case for deleting a single character */
|
|
|
|
/* len(self)>=1, len(from)==1, to="", maxcount>=1 */
|
|
|
|
Py_LOCAL(PyBytesObject *)
|
|
|
|
replace_delete_single_character(PyBytesObject *self,
|
|
|
|
char from_c, Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
char *self_s, *result_s;
|
|
|
|
char *start, *next, *end;
|
|
|
|
Py_ssize_t self_len, result_len;
|
|
|
|
Py_ssize_t count;
|
|
|
|
PyBytesObject *result;
|
|
|
|
|
|
|
|
self_len = PyBytes_GET_SIZE(self);
|
|
|
|
self_s = PyBytes_AS_STRING(self);
|
|
|
|
|
|
|
|
count = countchar(self_s, self_len, from_c, maxcount);
|
|
|
|
if (count == 0) {
|
|
|
|
return return_self(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
result_len = self_len - count; /* from_len == 1 */
|
|
|
|
assert(result_len>=0);
|
|
|
|
|
|
|
|
if ( (result = (PyBytesObject *)
|
|
|
|
PyBytes_FromStringAndSize(NULL, result_len)) == NULL)
|
|
|
|
return NULL;
|
|
|
|
result_s = PyBytes_AS_STRING(result);
|
|
|
|
|
|
|
|
start = self_s;
|
|
|
|
end = self_s + self_len;
|
|
|
|
while (count-- > 0) {
|
|
|
|
next = findchar(start, end-start, from_c);
|
|
|
|
if (next == NULL)
|
|
|
|
break;
|
|
|
|
Py_MEMCPY(result_s, start, next-start);
|
|
|
|
result_s += (next-start);
|
|
|
|
start = next+1;
|
|
|
|
}
|
|
|
|
Py_MEMCPY(result_s, start, end-start);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */
|
|
|
|
|
|
|
|
Py_LOCAL(PyBytesObject *)
|
|
|
|
replace_delete_substring(PyBytesObject *self,
|
|
|
|
const char *from_s, Py_ssize_t from_len,
|
|
|
|
Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
char *self_s, *result_s;
|
|
|
|
char *start, *next, *end;
|
|
|
|
Py_ssize_t self_len, result_len;
|
|
|
|
Py_ssize_t count, offset;
|
|
|
|
PyBytesObject *result;
|
|
|
|
|
|
|
|
self_len = PyBytes_GET_SIZE(self);
|
|
|
|
self_s = PyBytes_AS_STRING(self);
|
|
|
|
|
|
|
|
count = countstring(self_s, self_len,
|
|
|
|
from_s, from_len,
|
|
|
|
0, self_len, 1,
|
|
|
|
maxcount);
|
|
|
|
|
|
|
|
if (count == 0) {
|
|
|
|
/* no matches */
|
|
|
|
return return_self(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
result_len = self_len - (count * from_len);
|
|
|
|
assert (result_len>=0);
|
|
|
|
|
|
|
|
if ( (result = (PyBytesObject *)
|
|
|
|
PyBytes_FromStringAndSize(NULL, result_len)) == NULL )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result_s = PyBytes_AS_STRING(result);
|
|
|
|
|
|
|
|
start = self_s;
|
|
|
|
end = self_s + self_len;
|
|
|
|
while (count-- > 0) {
|
|
|
|
offset = findstring(start, end-start,
|
|
|
|
from_s, from_len,
|
|
|
|
0, end-start, FORWARD);
|
|
|
|
if (offset == -1)
|
|
|
|
break;
|
|
|
|
next = start + offset;
|
|
|
|
|
|
|
|
Py_MEMCPY(result_s, start, next-start);
|
|
|
|
|
|
|
|
result_s += (next-start);
|
|
|
|
start = next+from_len;
|
|
|
|
}
|
|
|
|
Py_MEMCPY(result_s, start, end-start);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */
|
|
|
|
Py_LOCAL(PyBytesObject *)
|
|
|
|
replace_single_character_in_place(PyBytesObject *self,
|
|
|
|
char from_c, char to_c,
|
|
|
|
Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
char *self_s, *result_s, *start, *end, *next;
|
|
|
|
Py_ssize_t self_len;
|
|
|
|
PyBytesObject *result;
|
|
|
|
|
|
|
|
/* The result string will be the same size */
|
|
|
|
self_s = PyBytes_AS_STRING(self);
|
|
|
|
self_len = PyBytes_GET_SIZE(self);
|
|
|
|
|
|
|
|
next = findchar(self_s, self_len, from_c);
|
|
|
|
|
|
|
|
if (next == NULL) {
|
|
|
|
/* No matches; return the original bytes */
|
|
|
|
return return_self(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Need to make a new bytes */
|
|
|
|
result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, self_len);
|
|
|
|
if (result == NULL)
|
|
|
|
return NULL;
|
|
|
|
result_s = PyBytes_AS_STRING(result);
|
|
|
|
Py_MEMCPY(result_s, self_s, self_len);
|
|
|
|
|
|
|
|
/* change everything in-place, starting with this one */
|
|
|
|
start = result_s + (next-self_s);
|
|
|
|
*start = to_c;
|
|
|
|
start++;
|
|
|
|
end = result_s + self_len;
|
|
|
|
|
|
|
|
while (--maxcount > 0) {
|
|
|
|
next = findchar(start, end-start, from_c);
|
|
|
|
if (next == NULL)
|
|
|
|
break;
|
|
|
|
*next = to_c;
|
|
|
|
start = next+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */
|
|
|
|
Py_LOCAL(PyBytesObject *)
|
|
|
|
replace_substring_in_place(PyBytesObject *self,
|
|
|
|
const char *from_s, Py_ssize_t from_len,
|
|
|
|
const char *to_s, Py_ssize_t to_len,
|
|
|
|
Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
char *result_s, *start, *end;
|
|
|
|
char *self_s;
|
|
|
|
Py_ssize_t self_len, offset;
|
|
|
|
PyBytesObject *result;
|
|
|
|
|
|
|
|
/* The result bytes will be the same size */
|
|
|
|
|
|
|
|
self_s = PyBytes_AS_STRING(self);
|
|
|
|
self_len = PyBytes_GET_SIZE(self);
|
|
|
|
|
|
|
|
offset = findstring(self_s, self_len,
|
|
|
|
from_s, from_len,
|
|
|
|
0, self_len, FORWARD);
|
|
|
|
if (offset == -1) {
|
|
|
|
/* No matches; return the original bytes */
|
|
|
|
return return_self(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Need to make a new bytes */
|
|
|
|
result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, self_len);
|
|
|
|
if (result == NULL)
|
|
|
|
return NULL;
|
|
|
|
result_s = PyBytes_AS_STRING(result);
|
|
|
|
Py_MEMCPY(result_s, self_s, self_len);
|
|
|
|
|
|
|
|
/* change everything in-place, starting with this one */
|
|
|
|
start = result_s + offset;
|
|
|
|
Py_MEMCPY(start, to_s, from_len);
|
|
|
|
start += from_len;
|
|
|
|
end = result_s + self_len;
|
|
|
|
|
|
|
|
while ( --maxcount > 0) {
|
|
|
|
offset = findstring(start, end-start,
|
|
|
|
from_s, from_len,
|
|
|
|
0, end-start, FORWARD);
|
|
|
|
if (offset==-1)
|
|
|
|
break;
|
|
|
|
Py_MEMCPY(start+offset, to_s, from_len);
|
|
|
|
start += offset+from_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */
|
|
|
|
Py_LOCAL(PyBytesObject *)
|
|
|
|
replace_single_character(PyBytesObject *self,
|
|
|
|
char from_c,
|
|
|
|
const char *to_s, Py_ssize_t to_len,
|
|
|
|
Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
char *self_s, *result_s;
|
|
|
|
char *start, *next, *end;
|
|
|
|
Py_ssize_t self_len, result_len;
|
|
|
|
Py_ssize_t count, product;
|
|
|
|
PyBytesObject *result;
|
|
|
|
|
|
|
|
self_s = PyBytes_AS_STRING(self);
|
|
|
|
self_len = PyBytes_GET_SIZE(self);
|
|
|
|
|
|
|
|
count = countchar(self_s, self_len, from_c, maxcount);
|
|
|
|
if (count == 0) {
|
|
|
|
/* no matches, return unchanged */
|
|
|
|
return return_self(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* use the difference between current and new, hence the "-1" */
|
|
|
|
/* result_len = self_len + count * (to_len-1) */
|
|
|
|
product = count * (to_len-1);
|
|
|
|
if (product / (to_len-1) != count) {
|
|
|
|
PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
result_len = self_len + product;
|
|
|
|
if (result_len < 0) {
|
|
|
|
PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( (result = (PyBytesObject *)
|
|
|
|
PyBytes_FromStringAndSize(NULL, result_len)) == NULL)
|
|
|
|
return NULL;
|
|
|
|
result_s = PyBytes_AS_STRING(result);
|
|
|
|
|
|
|
|
start = self_s;
|
|
|
|
end = self_s + self_len;
|
|
|
|
while (count-- > 0) {
|
|
|
|
next = findchar(start, end-start, from_c);
|
2007-04-12 19:49:52 -03:00
|
|
|
if (next == NULL)
|
2007-02-27 15:02:19 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (next == start) {
|
|
|
|
/* replace with the 'to' */
|
|
|
|
Py_MEMCPY(result_s, to_s, to_len);
|
|
|
|
result_s += to_len;
|
|
|
|
start += 1;
|
|
|
|
} else {
|
|
|
|
/* copy the unchanged old then the 'to' */
|
|
|
|
Py_MEMCPY(result_s, start, next-start);
|
|
|
|
result_s += (next-start);
|
|
|
|
Py_MEMCPY(result_s, to_s, to_len);
|
|
|
|
result_s += to_len;
|
|
|
|
start = next+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Copy the remainder of the remaining bytes */
|
|
|
|
Py_MEMCPY(result_s, start, end-start);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */
|
|
|
|
Py_LOCAL(PyBytesObject *)
|
|
|
|
replace_substring(PyBytesObject *self,
|
|
|
|
const char *from_s, Py_ssize_t from_len,
|
|
|
|
const char *to_s, Py_ssize_t to_len,
|
|
|
|
Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
char *self_s, *result_s;
|
|
|
|
char *start, *next, *end;
|
|
|
|
Py_ssize_t self_len, result_len;
|
|
|
|
Py_ssize_t count, offset, product;
|
|
|
|
PyBytesObject *result;
|
|
|
|
|
|
|
|
self_s = PyBytes_AS_STRING(self);
|
|
|
|
self_len = PyBytes_GET_SIZE(self);
|
|
|
|
|
|
|
|
count = countstring(self_s, self_len,
|
|
|
|
from_s, from_len,
|
|
|
|
0, self_len, FORWARD, maxcount);
|
|
|
|
if (count == 0) {
|
|
|
|
/* no matches, return unchanged */
|
|
|
|
return return_self(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for overflow */
|
|
|
|
/* result_len = self_len + count * (to_len-from_len) */
|
|
|
|
product = count * (to_len-from_len);
|
|
|
|
if (product / (to_len-from_len) != count) {
|
|
|
|
PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
result_len = self_len + product;
|
|
|
|
if (result_len < 0) {
|
|
|
|
PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( (result = (PyBytesObject *)
|
|
|
|
PyBytes_FromStringAndSize(NULL, result_len)) == NULL)
|
|
|
|
return NULL;
|
|
|
|
result_s = PyBytes_AS_STRING(result);
|
|
|
|
|
|
|
|
start = self_s;
|
|
|
|
end = self_s + self_len;
|
|
|
|
while (count-- > 0) {
|
|
|
|
offset = findstring(start, end-start,
|
|
|
|
from_s, from_len,
|
|
|
|
0, end-start, FORWARD);
|
|
|
|
if (offset == -1)
|
|
|
|
break;
|
|
|
|
next = start+offset;
|
|
|
|
if (next == start) {
|
|
|
|
/* replace with the 'to' */
|
|
|
|
Py_MEMCPY(result_s, to_s, to_len);
|
|
|
|
result_s += to_len;
|
|
|
|
start += from_len;
|
|
|
|
} else {
|
|
|
|
/* copy the unchanged old then the 'to' */
|
|
|
|
Py_MEMCPY(result_s, start, next-start);
|
|
|
|
result_s += (next-start);
|
|
|
|
Py_MEMCPY(result_s, to_s, to_len);
|
|
|
|
result_s += to_len;
|
|
|
|
start = next+from_len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Copy the remainder of the remaining bytes */
|
|
|
|
Py_MEMCPY(result_s, start, end-start);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Py_LOCAL(PyBytesObject *)
|
|
|
|
replace(PyBytesObject *self,
|
|
|
|
const char *from_s, Py_ssize_t from_len,
|
|
|
|
const char *to_s, Py_ssize_t to_len,
|
|
|
|
Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
if (maxcount < 0) {
|
|
|
|
maxcount = PY_SSIZE_T_MAX;
|
|
|
|
} else if (maxcount == 0 || PyBytes_GET_SIZE(self) == 0) {
|
|
|
|
/* nothing to do; return the original bytes */
|
|
|
|
return return_self(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxcount == 0 ||
|
|
|
|
(from_len == 0 && to_len == 0)) {
|
|
|
|
/* nothing to do; return the original bytes */
|
|
|
|
return return_self(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle zero-length special cases */
|
|
|
|
|
|
|
|
if (from_len == 0) {
|
|
|
|
/* insert the 'to' bytes everywhere. */
|
|
|
|
/* >>> "Python".replace("", ".") */
|
|
|
|
/* '.P.y.t.h.o.n.' */
|
|
|
|
return replace_interleave(self, to_s, to_len, maxcount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Except for "".replace("", "A") == "A" there is no way beyond this */
|
|
|
|
/* point for an empty self bytes to generate a non-empty bytes */
|
|
|
|
/* Special case so the remaining code always gets a non-empty bytes */
|
|
|
|
if (PyBytes_GET_SIZE(self) == 0) {
|
|
|
|
return return_self(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (to_len == 0) {
|
|
|
|
/* delete all occurances of 'from' bytes */
|
|
|
|
if (from_len == 1) {
|
|
|
|
return replace_delete_single_character(
|
|
|
|
self, from_s[0], maxcount);
|
|
|
|
} else {
|
|
|
|
return replace_delete_substring(self, from_s, from_len, maxcount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle special case where both bytes have the same length */
|
|
|
|
|
|
|
|
if (from_len == to_len) {
|
|
|
|
if (from_len == 1) {
|
|
|
|
return replace_single_character_in_place(
|
|
|
|
self,
|
|
|
|
from_s[0],
|
|
|
|
to_s[0],
|
|
|
|
maxcount);
|
|
|
|
} else {
|
|
|
|
return replace_substring_in_place(
|
|
|
|
self, from_s, from_len, to_s, to_len, maxcount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise use the more generic algorithms */
|
|
|
|
if (from_len == 1) {
|
|
|
|
return replace_single_character(self, from_s[0],
|
|
|
|
to_s, to_len, maxcount);
|
|
|
|
} else {
|
|
|
|
/* len('from')>=2, len('to')>=1 */
|
|
|
|
return replace_substring(self, from_s, from_len, to_s, to_len, maxcount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-16 03:31:30 -03:00
|
|
|
|
2007-02-27 15:02:19 -04:00
|
|
|
PyDoc_STRVAR(replace__doc__,
|
2007-11-06 17:34:58 -04:00
|
|
|
"B.replace(old, new[, count]) -> bytes\n\
|
2007-02-27 15:02:19 -04:00
|
|
|
\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Return a copy of B with all occurrences of subsection\n\
|
2007-02-27 15:02:19 -04:00
|
|
|
old replaced by new. If the optional argument count is\n\
|
|
|
|
given, only the first count occurrences are replaced.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_replace(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Py_ssize_t count = -1;
|
2007-08-18 08:21:56 -03:00
|
|
|
PyObject *from, *to, *res;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer vfrom, vto;
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))
|
|
|
|
return NULL;
|
|
|
|
|
2007-08-29 01:05:57 -03:00
|
|
|
if (_getbuffer(from, &vfrom) < 0)
|
|
|
|
return NULL;
|
|
|
|
if (_getbuffer(to, &vto) < 0) {
|
|
|
|
PyObject_ReleaseBuffer(from, &vfrom);
|
|
|
|
return NULL;
|
2007-08-18 08:21:56 -03:00
|
|
|
}
|
2007-02-27 15:02:19 -04:00
|
|
|
|
2007-08-18 08:21:56 -03:00
|
|
|
res = (PyObject *)replace((PyBytesObject *) self,
|
2007-08-29 01:05:57 -03:00
|
|
|
vfrom.buf, vfrom.len,
|
|
|
|
vto.buf, vto.len, count);
|
2007-08-18 08:21:56 -03:00
|
|
|
|
2007-08-29 01:05:57 -03:00
|
|
|
PyObject_ReleaseBuffer(from, &vfrom);
|
|
|
|
PyObject_ReleaseBuffer(to, &vto);
|
2007-08-18 08:21:56 -03:00
|
|
|
return res;
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Overallocate the initial list to reduce the number of reallocs for small
|
|
|
|
split sizes. Eg, "A A A A A A A A A A".split() (10 elements) has three
|
|
|
|
resizes, to sizes 4, 8, then 16. Most observed string splits are for human
|
|
|
|
text (roughly 11 words per line) and field delimited data (usually 1-10
|
|
|
|
fields). For large strings the split algorithms are bandwidth limited
|
|
|
|
so increasing the preallocation likely will not improve things.*/
|
|
|
|
|
|
|
|
#define MAX_PREALLOC 12
|
|
|
|
|
|
|
|
/* 5 splits gives 6 elements */
|
|
|
|
#define PREALLOC_SIZE(maxsplit) \
|
|
|
|
(maxsplit >= MAX_PREALLOC ? MAX_PREALLOC : maxsplit+1)
|
|
|
|
|
|
|
|
#define SPLIT_APPEND(data, left, right) \
|
|
|
|
str = PyBytes_FromStringAndSize((data) + (left), \
|
|
|
|
(right) - (left)); \
|
|
|
|
if (str == NULL) \
|
|
|
|
goto onError; \
|
|
|
|
if (PyList_Append(list, str)) { \
|
|
|
|
Py_DECREF(str); \
|
|
|
|
goto onError; \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
Py_DECREF(str);
|
|
|
|
|
|
|
|
#define SPLIT_ADD(data, left, right) { \
|
|
|
|
str = PyBytes_FromStringAndSize((data) + (left), \
|
|
|
|
(right) - (left)); \
|
|
|
|
if (str == NULL) \
|
|
|
|
goto onError; \
|
|
|
|
if (count < MAX_PREALLOC) { \
|
|
|
|
PyList_SET_ITEM(list, count, str); \
|
|
|
|
} else { \
|
|
|
|
if (PyList_Append(list, str)) { \
|
|
|
|
Py_DECREF(str); \
|
|
|
|
goto onError; \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
Py_DECREF(str); \
|
|
|
|
} \
|
|
|
|
count++; }
|
|
|
|
|
|
|
|
/* Always force the list to the expected size. */
|
2007-12-18 22:45:37 -04:00
|
|
|
#define FIX_PREALLOC_SIZE(list) Py_SIZE(list) = count
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
Py_LOCAL_INLINE(PyObject *)
|
|
|
|
split_char(const char *s, Py_ssize_t len, char ch, Py_ssize_t maxcount)
|
|
|
|
{
|
2007-09-10 13:53:45 -03:00
|
|
|
register Py_ssize_t i, j, count = 0;
|
2007-02-27 15:02:19 -04:00
|
|
|
PyObject *str;
|
|
|
|
PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
|
|
|
|
|
|
|
|
if (list == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
i = j = 0;
|
|
|
|
while ((j < len) && (maxcount-- > 0)) {
|
2007-09-10 13:53:45 -03:00
|
|
|
for(; j < len; j++) {
|
2007-02-27 15:02:19 -04:00
|
|
|
/* I found that using memchr makes no difference */
|
|
|
|
if (s[j] == ch) {
|
|
|
|
SPLIT_ADD(s, i, j);
|
|
|
|
i = j = j + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i <= len) {
|
|
|
|
SPLIT_ADD(s, i, len);
|
|
|
|
}
|
|
|
|
FIX_PREALLOC_SIZE(list);
|
|
|
|
return list;
|
|
|
|
|
|
|
|
onError:
|
|
|
|
Py_DECREF(list);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-09-10 13:53:45 -03:00
|
|
|
|
|
|
|
Py_LOCAL_INLINE(PyObject *)
|
|
|
|
split_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
register Py_ssize_t i, j, count = 0;
|
|
|
|
PyObject *str;
|
|
|
|
PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
|
|
|
|
|
|
|
|
if (list == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = j = 0; i < len; ) {
|
2007-11-06 17:34:58 -04:00
|
|
|
/* find a token */
|
|
|
|
while (i < len && ISSPACE(s[i]))
|
|
|
|
i++;
|
|
|
|
j = i;
|
|
|
|
while (i < len && !ISSPACE(s[i]))
|
|
|
|
i++;
|
|
|
|
if (j < i) {
|
|
|
|
if (maxcount-- <= 0)
|
|
|
|
break;
|
|
|
|
SPLIT_ADD(s, j, i);
|
|
|
|
while (i < len && ISSPACE(s[i]))
|
|
|
|
i++;
|
|
|
|
j = i;
|
|
|
|
}
|
2007-09-10 13:53:45 -03:00
|
|
|
}
|
|
|
|
if (j < len) {
|
2007-11-06 17:34:58 -04:00
|
|
|
SPLIT_ADD(s, j, len);
|
2007-09-10 13:53:45 -03:00
|
|
|
}
|
|
|
|
FIX_PREALLOC_SIZE(list);
|
|
|
|
return list;
|
|
|
|
|
|
|
|
onError:
|
|
|
|
Py_DECREF(list);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-27 15:02:19 -04:00
|
|
|
PyDoc_STRVAR(split__doc__,
|
2007-11-21 15:29:53 -04:00
|
|
|
"B.split([sep[, maxsplit]]) -> list of bytearray\n\
|
2007-02-27 15:02:19 -04:00
|
|
|
\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Return a list of the sections in B, using sep as the delimiter.\n\
|
|
|
|
If sep is not given, B is split on ASCII whitespace characters\n\
|
2007-09-10 13:53:45 -03:00
|
|
|
(space, tab, return, newline, formfeed, vertical tab).\n\
|
|
|
|
If maxsplit is given, at most maxsplit splits are done.");
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_split(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Py_ssize_t len = PyBytes_GET_SIZE(self), n, i, j;
|
2007-09-10 13:53:45 -03:00
|
|
|
Py_ssize_t maxsplit = -1, count = 0;
|
2007-02-27 15:02:19 -04:00
|
|
|
const char *s = PyBytes_AS_STRING(self), *sub;
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject *list, *str, *subobj = Py_None;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer vsub;
|
2007-02-27 15:02:19 -04:00
|
|
|
#ifdef USE_FAST
|
|
|
|
Py_ssize_t pos;
|
|
|
|
#endif
|
|
|
|
|
2007-09-10 13:53:45 -03:00
|
|
|
if (!PyArg_ParseTuple(args, "|On:split", &subobj, &maxsplit))
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
|
|
|
if (maxsplit < 0)
|
|
|
|
maxsplit = PY_SSIZE_T_MAX;
|
2007-09-10 13:53:45 -03:00
|
|
|
|
|
|
|
if (subobj == Py_None)
|
|
|
|
return split_whitespace(s, len, maxsplit);
|
|
|
|
|
|
|
|
if (_getbuffer(subobj, &vsub) < 0)
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
2007-09-10 13:53:45 -03:00
|
|
|
sub = vsub.buf;
|
|
|
|
n = vsub.len;
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (n == 0) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "empty separator");
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject_ReleaseBuffer(subobj, &vsub);
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-09-10 13:53:45 -03:00
|
|
|
if (n == 1)
|
2007-02-27 15:02:19 -04:00
|
|
|
return split_char(s, len, sub[0], maxsplit);
|
|
|
|
|
|
|
|
list = PyList_New(PREALLOC_SIZE(maxsplit));
|
2007-09-10 13:53:45 -03:00
|
|
|
if (list == NULL) {
|
|
|
|
PyObject_ReleaseBuffer(subobj, &vsub);
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
2007-09-10 13:53:45 -03:00
|
|
|
}
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
#ifdef USE_FAST
|
|
|
|
i = j = 0;
|
|
|
|
while (maxsplit-- > 0) {
|
|
|
|
pos = fastsearch(s+i, len-i, sub, n, FAST_SEARCH);
|
|
|
|
if (pos < 0)
|
|
|
|
break;
|
|
|
|
j = i+pos;
|
|
|
|
SPLIT_ADD(s, i, j);
|
|
|
|
i = j + n;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
i = j = 0;
|
|
|
|
while ((j+n <= len) && (maxsplit-- > 0)) {
|
|
|
|
for (; j+n <= len; j++) {
|
|
|
|
if (Py_STRING_MATCH(s, j, sub, n)) {
|
|
|
|
SPLIT_ADD(s, i, j);
|
|
|
|
i = j = j + n;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
SPLIT_ADD(s, i, len);
|
|
|
|
FIX_PREALLOC_SIZE(list);
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject_ReleaseBuffer(subobj, &vsub);
|
2007-02-27 15:02:19 -04:00
|
|
|
return list;
|
|
|
|
|
|
|
|
onError:
|
|
|
|
Py_DECREF(list);
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject_ReleaseBuffer(subobj, &vsub);
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-11-06 17:34:58 -04:00
|
|
|
/* stringlib's partition shares nullbytes in some cases.
|
|
|
|
undo this, we don't want the nullbytes to be shared. */
|
|
|
|
static PyObject *
|
|
|
|
make_nullbytes_unique(PyObject *result)
|
|
|
|
{
|
|
|
|
if (result != NULL) {
|
|
|
|
int i;
|
|
|
|
assert(PyTuple_Check(result));
|
|
|
|
assert(PyTuple_GET_SIZE(result) == 3);
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
if (PyTuple_GET_ITEM(result, i) == (PyObject *)nullbytes) {
|
|
|
|
PyObject *new = PyBytes_FromStringAndSize(NULL, 0);
|
|
|
|
if (new == NULL) {
|
|
|
|
Py_DECREF(result);
|
|
|
|
result = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Py_DECREF(nullbytes);
|
|
|
|
PyTuple_SET_ITEM(result, i, new);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2007-02-27 15:02:19 -04:00
|
|
|
PyDoc_STRVAR(partition__doc__,
|
|
|
|
"B.partition(sep) -> (head, sep, tail)\n\
|
|
|
|
\n\
|
|
|
|
Searches for the separator sep in B, and returns the part before it,\n\
|
|
|
|
the separator itself, and the part after it. If the separator is not\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
found, returns B and two empty bytearray objects.");
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_partition(PyBytesObject *self, PyObject *sep_obj)
|
|
|
|
{
|
|
|
|
PyObject *bytesep, *result;
|
|
|
|
|
|
|
|
bytesep = PyBytes_FromObject(sep_obj);
|
|
|
|
if (! bytesep)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result = stringlib_partition(
|
|
|
|
(PyObject*) self,
|
|
|
|
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
|
2007-04-12 19:49:52 -03:00
|
|
|
bytesep,
|
2007-02-27 15:02:19 -04:00
|
|
|
PyBytes_AS_STRING(bytesep), PyBytes_GET_SIZE(bytesep)
|
|
|
|
);
|
|
|
|
|
|
|
|
Py_DECREF(bytesep);
|
2007-11-06 17:34:58 -04:00
|
|
|
return make_nullbytes_unique(result);
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(rpartition__doc__,
|
|
|
|
"B.rpartition(sep) -> (tail, sep, head)\n\
|
|
|
|
\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Searches for the separator sep in B, starting at the end of B,\n\
|
|
|
|
and returns the part before it, the separator itself, and the\n\
|
|
|
|
part after it. If the separator is not found, returns two empty\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
bytearray objects and B.");
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_rpartition(PyBytesObject *self, PyObject *sep_obj)
|
|
|
|
{
|
|
|
|
PyObject *bytesep, *result;
|
|
|
|
|
|
|
|
bytesep = PyBytes_FromObject(sep_obj);
|
|
|
|
if (! bytesep)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result = stringlib_rpartition(
|
|
|
|
(PyObject*) self,
|
|
|
|
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
|
2007-04-12 19:49:52 -03:00
|
|
|
bytesep,
|
2007-02-27 15:02:19 -04:00
|
|
|
PyBytes_AS_STRING(bytesep), PyBytes_GET_SIZE(bytesep)
|
|
|
|
);
|
|
|
|
|
|
|
|
Py_DECREF(bytesep);
|
2007-11-06 17:34:58 -04:00
|
|
|
return make_nullbytes_unique(result);
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Py_LOCAL_INLINE(PyObject *)
|
|
|
|
rsplit_char(const char *s, Py_ssize_t len, char ch, Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
register Py_ssize_t i, j, count=0;
|
|
|
|
PyObject *str;
|
|
|
|
PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
|
|
|
|
|
|
|
|
if (list == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
i = j = len - 1;
|
|
|
|
while ((i >= 0) && (maxcount-- > 0)) {
|
|
|
|
for (; i >= 0; i--) {
|
|
|
|
if (s[i] == ch) {
|
|
|
|
SPLIT_ADD(s, i + 1, j + 1);
|
|
|
|
j = i = i - 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (j >= -1) {
|
|
|
|
SPLIT_ADD(s, 0, j + 1);
|
|
|
|
}
|
|
|
|
FIX_PREALLOC_SIZE(list);
|
|
|
|
if (PyList_Reverse(list) < 0)
|
|
|
|
goto onError;
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
|
|
|
onError:
|
|
|
|
Py_DECREF(list);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-09-10 13:53:45 -03:00
|
|
|
Py_LOCAL_INLINE(PyObject *)
|
|
|
|
rsplit_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxcount)
|
|
|
|
{
|
|
|
|
register Py_ssize_t i, j, count = 0;
|
|
|
|
PyObject *str;
|
|
|
|
PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
|
|
|
|
|
|
|
|
if (list == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = j = len - 1; i >= 0; ) {
|
2007-11-06 17:34:58 -04:00
|
|
|
/* find a token */
|
2008-01-30 05:51:48 -04:00
|
|
|
while (i >= 0 && ISSPACE(s[i]))
|
2007-11-06 17:34:58 -04:00
|
|
|
i--;
|
|
|
|
j = i;
|
2008-01-30 05:51:48 -04:00
|
|
|
while (i >= 0 && !ISSPACE(s[i]))
|
2007-11-06 17:34:58 -04:00
|
|
|
i--;
|
|
|
|
if (j > i) {
|
|
|
|
if (maxcount-- <= 0)
|
|
|
|
break;
|
|
|
|
SPLIT_ADD(s, i + 1, j + 1);
|
2008-01-30 05:51:48 -04:00
|
|
|
while (i >= 0 && ISSPACE(s[i]))
|
2007-11-06 17:34:58 -04:00
|
|
|
i--;
|
|
|
|
j = i;
|
|
|
|
}
|
2007-09-10 13:53:45 -03:00
|
|
|
}
|
|
|
|
if (j >= 0) {
|
2007-11-06 17:34:58 -04:00
|
|
|
SPLIT_ADD(s, 0, j + 1);
|
2007-09-10 13:53:45 -03:00
|
|
|
}
|
|
|
|
FIX_PREALLOC_SIZE(list);
|
|
|
|
if (PyList_Reverse(list) < 0)
|
|
|
|
goto onError;
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
|
|
|
onError:
|
|
|
|
Py_DECREF(list);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-27 15:02:19 -04:00
|
|
|
PyDoc_STRVAR(rsplit__doc__,
|
2007-11-21 15:29:53 -04:00
|
|
|
"B.rsplit(sep[, maxsplit]) -> list of bytearray\n\
|
2007-02-27 15:02:19 -04:00
|
|
|
\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Return a list of the sections in B, using sep as the delimiter,\n\
|
|
|
|
starting at the end of B and working to the front.\n\
|
2007-09-10 13:53:45 -03:00
|
|
|
If sep is not given, B is split on ASCII whitespace characters\n\
|
|
|
|
(space, tab, return, newline, formfeed, vertical tab).\n\
|
|
|
|
If maxsplit is given, at most maxsplit splits are done.");
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_rsplit(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
Py_ssize_t len = PyBytes_GET_SIZE(self), n, i, j;
|
2007-09-10 13:53:45 -03:00
|
|
|
Py_ssize_t maxsplit = -1, count = 0;
|
2007-02-27 15:02:19 -04:00
|
|
|
const char *s = PyBytes_AS_STRING(self), *sub;
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject *list, *str, *subobj = Py_None;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer vsub;
|
2007-02-27 15:02:19 -04:00
|
|
|
|
2007-09-10 13:53:45 -03:00
|
|
|
if (!PyArg_ParseTuple(args, "|On:rsplit", &subobj, &maxsplit))
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
|
|
|
if (maxsplit < 0)
|
|
|
|
maxsplit = PY_SSIZE_T_MAX;
|
2007-09-10 13:53:45 -03:00
|
|
|
|
|
|
|
if (subobj == Py_None)
|
|
|
|
return rsplit_whitespace(s, len, maxsplit);
|
|
|
|
|
|
|
|
if (_getbuffer(subobj, &vsub) < 0)
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
2007-09-10 13:53:45 -03:00
|
|
|
sub = vsub.buf;
|
|
|
|
n = vsub.len;
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (n == 0) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "empty separator");
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject_ReleaseBuffer(subobj, &vsub);
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else if (n == 1)
|
|
|
|
return rsplit_char(s, len, sub[0], maxsplit);
|
|
|
|
|
|
|
|
list = PyList_New(PREALLOC_SIZE(maxsplit));
|
2007-09-10 13:53:45 -03:00
|
|
|
if (list == NULL) {
|
|
|
|
PyObject_ReleaseBuffer(subobj, &vsub);
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
2007-09-10 13:53:45 -03:00
|
|
|
}
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
j = len;
|
|
|
|
i = j - n;
|
|
|
|
|
|
|
|
while ( (i >= 0) && (maxsplit-- > 0) ) {
|
|
|
|
for (; i>=0; i--) {
|
|
|
|
if (Py_STRING_MATCH(s, i, sub, n)) {
|
|
|
|
SPLIT_ADD(s, i + n, j);
|
|
|
|
j = i;
|
|
|
|
i -= n;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SPLIT_ADD(s, 0, j);
|
|
|
|
FIX_PREALLOC_SIZE(list);
|
|
|
|
if (PyList_Reverse(list) < 0)
|
|
|
|
goto onError;
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject_ReleaseBuffer(subobj, &vsub);
|
2007-02-27 15:02:19 -04:00
|
|
|
return list;
|
|
|
|
|
|
|
|
onError:
|
|
|
|
Py_DECREF(list);
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject_ReleaseBuffer(subobj, &vsub);
|
2007-02-27 15:02:19 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(reverse__doc__,
|
|
|
|
"B.reverse() -> None\n\
|
|
|
|
\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Reverse the order of the values in B in place.");
|
2007-02-27 15:02:19 -04:00
|
|
|
static PyObject *
|
|
|
|
bytes_reverse(PyBytesObject *self, PyObject *unused)
|
|
|
|
{
|
|
|
|
char swap, *head, *tail;
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_ssize_t i, j, n = Py_SIZE(self);
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
j = n / 2;
|
|
|
|
head = self->ob_bytes;
|
|
|
|
tail = head + n - 1;
|
|
|
|
for (i = 0; i < j; i++) {
|
|
|
|
swap = *head;
|
|
|
|
*head++ = *tail;
|
|
|
|
*tail-- = swap;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(insert__doc__,
|
|
|
|
"B.insert(index, int) -> None\n\
|
|
|
|
\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
Insert a single item into the bytearray before the given index.");
|
2007-02-27 15:02:19 -04:00
|
|
|
static PyObject *
|
|
|
|
bytes_insert(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
int value;
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_ssize_t where, n = Py_SIZE(self);
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "ni:insert", &where, &value))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (n == PY_SSIZE_T_MAX) {
|
|
|
|
PyErr_SetString(PyExc_OverflowError,
|
|
|
|
"cannot add more objects to bytes");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (value < 0 || value >= 256) {
|
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"byte must be in range(0, 256)");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (PyBytes_Resize((PyObject *)self, n + 1) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (where < 0) {
|
|
|
|
where += n;
|
|
|
|
if (where < 0)
|
|
|
|
where = 0;
|
|
|
|
}
|
|
|
|
if (where > n)
|
|
|
|
where = n;
|
2007-02-27 16:57:45 -04:00
|
|
|
memmove(self->ob_bytes + where + 1, self->ob_bytes + where, n - where);
|
2007-02-27 15:02:19 -04:00
|
|
|
self->ob_bytes[where] = value;
|
|
|
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(append__doc__,
|
|
|
|
"B.append(int) -> None\n\
|
|
|
|
\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Append a single item to the end of B.");
|
2007-02-27 15:02:19 -04:00
|
|
|
static PyObject *
|
|
|
|
bytes_append(PyBytesObject *self, PyObject *arg)
|
|
|
|
{
|
|
|
|
int value;
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_ssize_t n = Py_SIZE(self);
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (! _getbytevalue(arg, &value))
|
|
|
|
return NULL;
|
|
|
|
if (n == PY_SSIZE_T_MAX) {
|
|
|
|
PyErr_SetString(PyExc_OverflowError,
|
|
|
|
"cannot add more objects to bytes");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (PyBytes_Resize((PyObject *)self, n + 1) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
self->ob_bytes[n] = value;
|
|
|
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
}
|
|
|
|
|
2007-12-04 01:51:13 -04:00
|
|
|
PyDoc_STRVAR(extend__doc__,
|
|
|
|
"B.extend(iterable int) -> None\n\
|
|
|
|
\n\
|
|
|
|
Append all the elements from the iterator or sequence to the\n\
|
|
|
|
end of B.");
|
|
|
|
static PyObject *
|
|
|
|
bytes_extend(PyBytesObject *self, PyObject *arg)
|
|
|
|
{
|
2008-04-14 17:51:05 -03:00
|
|
|
PyObject *it, *item, *bytes_obj;
|
2007-12-04 01:51:13 -04:00
|
|
|
Py_ssize_t buf_size = 0, len = 0;
|
|
|
|
int value;
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
/* bytes_setslice code only accepts something supporting PEP 3118. */
|
|
|
|
if (PyObject_CheckBuffer(arg)) {
|
2007-12-18 22:45:37 -04:00
|
|
|
if (bytes_setslice(self, Py_SIZE(self), Py_SIZE(self), arg) == -1)
|
2007-12-04 01:51:13 -04:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
it = PyObject_GetIter(arg);
|
|
|
|
if (it == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
Merged revisions 59376-59406 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r59377 | georg.brandl | 2007-12-06 01:24:23 +0100 (Thu, 06 Dec 2007) | 2 lines
Add another GHOP student to ACKS.
........
r59378 | raymond.hettinger | 2007-12-06 01:56:53 +0100 (Thu, 06 Dec 2007) | 5 lines
Fix Issue 1045.
Factor-out common calling code by simplifying the length_hint API.
Speed-up the function by caching the PyObject_String for the attribute lookup.
........
r59380 | georg.brandl | 2007-12-06 02:52:24 +0100 (Thu, 06 Dec 2007) | 2 lines
Diverse markup fixes.
........
r59383 | georg.brandl | 2007-12-06 10:45:39 +0100 (Thu, 06 Dec 2007) | 2 lines
Better re.split examples.
........
r59386 | christian.heimes | 2007-12-06 14:15:13 +0100 (Thu, 06 Dec 2007) | 2 lines
Fixed get_config_h_filename for Windows. Without the patch it can't find the pyconfig.h file inside a build tree.
Added several small unit tests for sysconfig.
........
r59387 | christian.heimes | 2007-12-06 14:30:11 +0100 (Thu, 06 Dec 2007) | 1 line
Silence more warnings, _CRT_NONSTDC_NO_DEPRECATE is already defined in pyconfig.h but several projects don't include it.
........
r59389 | christian.heimes | 2007-12-06 14:55:01 +0100 (Thu, 06 Dec 2007) | 1 line
Disabled one test that is failing on Unix
........
r59399 | christian.heimes | 2007-12-06 22:13:06 +0100 (Thu, 06 Dec 2007) | 8 lines
Several Windows related cleanups:
* Removed a #define from pyconfig.h. The macro was already defined a few lines higher.
* Fixed path to tix in the build_tkinter.py script
* Changed make_buildinfo.c to use versions of unlink and strcat which are considered safe by Windows (as suggested by MvL).
* Removed two defines from pyproject.vsprops that are no longer required. Both are defined in pyconfig.h and make_buildinfo.c doesn't use the unsafe versions any more (as suggested by MvL).
* Added some more information about PGO and the property files to PCbuild9/readme.txt.
Are you fine with the changes, Martin?
........
r59400 | raymond.hettinger | 2007-12-07 02:53:01 +0100 (Fri, 07 Dec 2007) | 4 lines
Don't have the docs berate themselves. Keep a professional tone.
If a todo is needed, put it in the tracker.
........
r59402 | georg.brandl | 2007-12-07 10:07:10 +0100 (Fri, 07 Dec 2007) | 3 lines
Increase unit test coverage of SimpleXMLRPCServer.
Written for GHOP by Turkay Eren.
........
r59406 | georg.brandl | 2007-12-07 16:16:57 +0100 (Fri, 07 Dec 2007) | 2 lines
Update to windows doc from Robert.
........
2007-12-08 11:33:56 -04:00
|
|
|
/* Try to determine the length of the argument. 32 is abitrary. */
|
|
|
|
buf_size = _PyObject_LengthHint(arg, 32);
|
2007-12-04 01:51:13 -04:00
|
|
|
|
2008-04-14 17:51:05 -03:00
|
|
|
bytes_obj = PyBytes_FromStringAndSize(NULL, buf_size);
|
|
|
|
if (bytes_obj == NULL)
|
|
|
|
return NULL;
|
|
|
|
buf = PyBytes_AS_STRING(bytes_obj);
|
2007-12-04 01:51:13 -04:00
|
|
|
|
|
|
|
while ((item = PyIter_Next(it)) != NULL) {
|
|
|
|
if (! _getbytevalue(item, &value)) {
|
|
|
|
Py_DECREF(item);
|
|
|
|
Py_DECREF(it);
|
2008-04-14 17:51:05 -03:00
|
|
|
Py_DECREF(bytes_obj);
|
2007-12-04 01:51:13 -04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
buf[len++] = value;
|
|
|
|
Py_DECREF(item);
|
2008-04-14 17:51:05 -03:00
|
|
|
|
2007-12-04 01:51:13 -04:00
|
|
|
if (len >= buf_size) {
|
|
|
|
buf_size = len + (len >> 1) + 1;
|
2008-04-14 17:51:05 -03:00
|
|
|
if (PyBytes_Resize((PyObject *)bytes_obj, buf_size) < 0) {
|
2007-12-04 01:51:13 -04:00
|
|
|
Py_DECREF(it);
|
2008-04-14 17:51:05 -03:00
|
|
|
Py_DECREF(bytes_obj);
|
|
|
|
return NULL;
|
2007-12-04 01:51:13 -04:00
|
|
|
}
|
2008-04-14 17:51:05 -03:00
|
|
|
/* Recompute the `buf' pointer, since the resizing operation may
|
|
|
|
have invalidated it. */
|
|
|
|
buf = PyBytes_AS_STRING(bytes_obj);
|
2007-12-04 01:51:13 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Py_DECREF(it);
|
|
|
|
|
2008-04-14 17:51:05 -03:00
|
|
|
/* Resize down to exact size. */
|
|
|
|
if (PyBytes_Resize((PyObject *)bytes_obj, len) < 0) {
|
|
|
|
Py_DECREF(bytes_obj);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-12-04 01:51:13 -04:00
|
|
|
|
2008-04-14 17:51:05 -03:00
|
|
|
if (bytes_setslice(self, Py_SIZE(self), Py_SIZE(self), bytes_obj) == -1)
|
|
|
|
return NULL;
|
|
|
|
Py_DECREF(bytes_obj);
|
|
|
|
|
|
|
|
Py_RETURN_NONE;
|
2007-12-04 01:51:13 -04:00
|
|
|
}
|
|
|
|
|
2007-02-27 15:02:19 -04:00
|
|
|
PyDoc_STRVAR(pop__doc__,
|
|
|
|
"B.pop([index]) -> int\n\
|
|
|
|
\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Remove and return a single item from B. If no index\n\
|
2007-02-27 15:02:19 -04:00
|
|
|
argument is give, will pop the last value.");
|
|
|
|
static PyObject *
|
|
|
|
bytes_pop(PyBytesObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
int value;
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_ssize_t where = -1, n = Py_SIZE(self);
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "|n:pop", &where))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (n == 0) {
|
|
|
|
PyErr_SetString(PyExc_OverflowError,
|
|
|
|
"cannot pop an empty bytes");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (where < 0)
|
2007-12-18 22:45:37 -04:00
|
|
|
where += Py_SIZE(self);
|
|
|
|
if (where < 0 || where >= Py_SIZE(self)) {
|
2007-02-27 15:02:19 -04:00
|
|
|
PyErr_SetString(PyExc_IndexError, "pop index out of range");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
value = self->ob_bytes[where];
|
|
|
|
memmove(self->ob_bytes + where, self->ob_bytes + where + 1, n - where);
|
|
|
|
if (PyBytes_Resize((PyObject *)self, n - 1) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2007-12-02 10:31:20 -04:00
|
|
|
return PyLong_FromLong(value);
|
2007-02-27 15:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(remove__doc__,
|
|
|
|
"B.remove(int) -> None\n\
|
|
|
|
\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Remove the first occurance of a value in B.");
|
2007-02-27 15:02:19 -04:00
|
|
|
static PyObject *
|
|
|
|
bytes_remove(PyBytesObject *self, PyObject *arg)
|
|
|
|
{
|
|
|
|
int value;
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_ssize_t where, n = Py_SIZE(self);
|
2007-02-27 15:02:19 -04:00
|
|
|
|
|
|
|
if (! _getbytevalue(arg, &value))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (where = 0; where < n; where++) {
|
|
|
|
if (self->ob_bytes[where] == value)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (where == n) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "value not found in bytes");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
memmove(self->ob_bytes + where, self->ob_bytes + where + 1, n - where);
|
|
|
|
if (PyBytes_Resize((PyObject *)self, n - 1) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
}
|
|
|
|
|
2007-04-12 22:39:34 -03:00
|
|
|
/* XXX These two helpers could be optimized if argsize == 1 */
|
|
|
|
|
2007-08-27 03:19:22 -03:00
|
|
|
static Py_ssize_t
|
2007-04-12 22:39:34 -03:00
|
|
|
lstrip_helper(unsigned char *myptr, Py_ssize_t mysize,
|
|
|
|
void *argptr, Py_ssize_t argsize)
|
|
|
|
{
|
|
|
|
Py_ssize_t i = 0;
|
|
|
|
while (i < mysize && memchr(argptr, myptr[i], argsize))
|
|
|
|
i++;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2007-08-27 03:19:22 -03:00
|
|
|
static Py_ssize_t
|
2007-04-12 22:39:34 -03:00
|
|
|
rstrip_helper(unsigned char *myptr, Py_ssize_t mysize,
|
|
|
|
void *argptr, Py_ssize_t argsize)
|
|
|
|
{
|
|
|
|
Py_ssize_t i = mysize - 1;
|
|
|
|
while (i >= 0 && memchr(argptr, myptr[i], argsize))
|
|
|
|
i--;
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(strip__doc__,
|
2007-11-21 15:29:53 -04:00
|
|
|
"B.strip([bytes]) -> bytearray\n\
|
2007-04-12 22:39:34 -03:00
|
|
|
\n\
|
2007-09-10 13:53:45 -03:00
|
|
|
Strip leading and trailing bytes contained in the argument.\n\
|
|
|
|
If the argument is omitted, strip ASCII whitespace.");
|
2007-04-12 22:39:34 -03:00
|
|
|
static PyObject *
|
2007-09-10 13:53:45 -03:00
|
|
|
bytes_strip(PyBytesObject *self, PyObject *args)
|
2007-04-12 22:39:34 -03:00
|
|
|
{
|
|
|
|
Py_ssize_t left, right, mysize, argsize;
|
|
|
|
void *myptr, *argptr;
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject *arg = Py_None;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer varg;
|
2007-09-10 13:53:45 -03:00
|
|
|
if (!PyArg_ParseTuple(args, "|O:strip", &arg))
|
2007-04-12 22:39:34 -03:00
|
|
|
return NULL;
|
2007-09-10 13:53:45 -03:00
|
|
|
if (arg == Py_None) {
|
|
|
|
argptr = "\t\n\r\f\v ";
|
|
|
|
argsize = 6;
|
|
|
|
}
|
|
|
|
else {
|
2007-11-06 17:34:58 -04:00
|
|
|
if (_getbuffer(arg, &varg) < 0)
|
|
|
|
return NULL;
|
|
|
|
argptr = varg.buf;
|
|
|
|
argsize = varg.len;
|
2007-04-12 22:39:34 -03:00
|
|
|
}
|
|
|
|
myptr = self->ob_bytes;
|
2007-12-18 22:45:37 -04:00
|
|
|
mysize = Py_SIZE(self);
|
2007-04-12 22:39:34 -03:00
|
|
|
left = lstrip_helper(myptr, mysize, argptr, argsize);
|
2007-08-08 18:55:33 -03:00
|
|
|
if (left == mysize)
|
|
|
|
right = left;
|
|
|
|
else
|
|
|
|
right = rstrip_helper(myptr, mysize, argptr, argsize);
|
2007-09-10 13:53:45 -03:00
|
|
|
if (arg != Py_None)
|
2007-11-06 17:34:58 -04:00
|
|
|
PyObject_ReleaseBuffer(arg, &varg);
|
2007-04-12 22:39:34 -03:00
|
|
|
return PyBytes_FromStringAndSize(self->ob_bytes + left, right - left);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(lstrip__doc__,
|
2007-11-21 15:29:53 -04:00
|
|
|
"B.lstrip([bytes]) -> bytearray\n\
|
2007-04-12 22:39:34 -03:00
|
|
|
\n\
|
2007-09-10 13:53:45 -03:00
|
|
|
Strip leading bytes contained in the argument.\n\
|
|
|
|
If the argument is omitted, strip leading ASCII whitespace.");
|
2007-04-12 22:39:34 -03:00
|
|
|
static PyObject *
|
2007-09-10 13:53:45 -03:00
|
|
|
bytes_lstrip(PyBytesObject *self, PyObject *args)
|
2007-04-12 22:39:34 -03:00
|
|
|
{
|
|
|
|
Py_ssize_t left, right, mysize, argsize;
|
|
|
|
void *myptr, *argptr;
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject *arg = Py_None;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer varg;
|
2007-09-10 13:53:45 -03:00
|
|
|
if (!PyArg_ParseTuple(args, "|O:lstrip", &arg))
|
2007-04-12 22:39:34 -03:00
|
|
|
return NULL;
|
2007-09-10 13:53:45 -03:00
|
|
|
if (arg == Py_None) {
|
|
|
|
argptr = "\t\n\r\f\v ";
|
|
|
|
argsize = 6;
|
|
|
|
}
|
|
|
|
else {
|
2007-11-06 17:34:58 -04:00
|
|
|
if (_getbuffer(arg, &varg) < 0)
|
|
|
|
return NULL;
|
|
|
|
argptr = varg.buf;
|
|
|
|
argsize = varg.len;
|
2007-04-12 22:39:34 -03:00
|
|
|
}
|
|
|
|
myptr = self->ob_bytes;
|
2007-12-18 22:45:37 -04:00
|
|
|
mysize = Py_SIZE(self);
|
2007-04-12 22:39:34 -03:00
|
|
|
left = lstrip_helper(myptr, mysize, argptr, argsize);
|
|
|
|
right = mysize;
|
2007-09-10 13:53:45 -03:00
|
|
|
if (arg != Py_None)
|
2007-11-06 17:34:58 -04:00
|
|
|
PyObject_ReleaseBuffer(arg, &varg);
|
2007-04-12 22:39:34 -03:00
|
|
|
return PyBytes_FromStringAndSize(self->ob_bytes + left, right - left);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(rstrip__doc__,
|
2007-11-21 15:29:53 -04:00
|
|
|
"B.rstrip([bytes]) -> bytearray\n\
|
2007-04-12 22:39:34 -03:00
|
|
|
\n\
|
2007-09-10 13:53:45 -03:00
|
|
|
Strip trailing bytes contained in the argument.\n\
|
|
|
|
If the argument is omitted, strip trailing ASCII whitespace.");
|
2007-04-12 22:39:34 -03:00
|
|
|
static PyObject *
|
2007-09-10 13:53:45 -03:00
|
|
|
bytes_rstrip(PyBytesObject *self, PyObject *args)
|
2007-04-12 22:39:34 -03:00
|
|
|
{
|
|
|
|
Py_ssize_t left, right, mysize, argsize;
|
|
|
|
void *myptr, *argptr;
|
2007-09-10 13:53:45 -03:00
|
|
|
PyObject *arg = Py_None;
|
2007-09-22 23:00:13 -03:00
|
|
|
Py_buffer varg;
|
2007-09-10 13:53:45 -03:00
|
|
|
if (!PyArg_ParseTuple(args, "|O:rstrip", &arg))
|
2007-04-12 22:39:34 -03:00
|
|
|
return NULL;
|
2007-09-10 13:53:45 -03:00
|
|
|
if (arg == Py_None) {
|
|
|
|
argptr = "\t\n\r\f\v ";
|
|
|
|
argsize = 6;
|
|
|
|
}
|
|
|
|
else {
|
2007-11-06 17:34:58 -04:00
|
|
|
if (_getbuffer(arg, &varg) < 0)
|
|
|
|
return NULL;
|
|
|
|
argptr = varg.buf;
|
|
|
|
argsize = varg.len;
|
2007-04-12 22:39:34 -03:00
|
|
|
}
|
|
|
|
myptr = self->ob_bytes;
|
2007-12-18 22:45:37 -04:00
|
|
|
mysize = Py_SIZE(self);
|
2007-04-12 22:39:34 -03:00
|
|
|
left = 0;
|
|
|
|
right = rstrip_helper(myptr, mysize, argptr, argsize);
|
2007-09-10 13:53:45 -03:00
|
|
|
if (arg != Py_None)
|
2007-11-06 17:34:58 -04:00
|
|
|
PyObject_ReleaseBuffer(arg, &varg);
|
2007-04-12 22:39:34 -03:00
|
|
|
return PyBytes_FromStringAndSize(self->ob_bytes + left, right - left);
|
|
|
|
}
|
2007-02-27 15:02:19 -04:00
|
|
|
|
2006-04-24 10:47:05 -03:00
|
|
|
PyDoc_STRVAR(decode_doc,
|
2007-11-06 17:34:58 -04:00
|
|
|
"B.decode([encoding[, errors]]) -> unicode object.\n\
|
2006-04-24 10:47:05 -03:00
|
|
|
\n\
|
|
|
|
Decodes B using the codec registered for encoding. encoding defaults\n\
|
|
|
|
to the default encoding. errors may be given to set a different error\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
handling scheme. Default is 'strict' meaning that encoding errors raise\n\
|
|
|
|
a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'\n\
|
2007-12-09 19:05:36 -04:00
|
|
|
as well as any other name registered with codecs.register_error that is\n\
|
2006-04-24 10:47:05 -03:00
|
|
|
able to handle UnicodeDecodeErrors.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_decode(PyObject *self, PyObject *args)
|
2007-04-12 19:49:52 -03:00
|
|
|
{
|
2006-04-24 10:47:05 -03:00
|
|
|
const char *encoding = NULL;
|
|
|
|
const char *errors = NULL;
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "|ss:decode", &encoding, &errors))
|
|
|
|
return NULL;
|
|
|
|
if (encoding == NULL)
|
|
|
|
encoding = PyUnicode_GetDefaultEncoding();
|
|
|
|
return PyCodec_Decode(self, encoding, errors);
|
|
|
|
}
|
|
|
|
|
2006-05-05 01:34:18 -03:00
|
|
|
PyDoc_STRVAR(alloc_doc,
|
|
|
|
"B.__alloc__() -> int\n\
|
|
|
|
\n\
|
|
|
|
Returns the number of bytes actually allocated.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_alloc(PyBytesObject *self)
|
|
|
|
{
|
2007-12-02 10:31:20 -04:00
|
|
|
return PyLong_FromSsize_t(self->ob_alloc);
|
2006-05-05 01:34:18 -03:00
|
|
|
}
|
|
|
|
|
2006-05-05 12:15:40 -03:00
|
|
|
PyDoc_STRVAR(join_doc,
|
2007-05-09 16:52:16 -03:00
|
|
|
"B.join(iterable_of_bytes) -> bytes\n\
|
2006-05-05 12:15:40 -03:00
|
|
|
\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
Concatenates any number of bytearray objects, with B in between each pair.");
|
2006-05-05 12:15:40 -03:00
|
|
|
|
|
|
|
static PyObject *
|
2007-05-09 16:52:16 -03:00
|
|
|
bytes_join(PyBytesObject *self, PyObject *it)
|
2006-05-05 12:15:40 -03:00
|
|
|
{
|
|
|
|
PyObject *seq;
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_ssize_t mysize = Py_SIZE(self);
|
2006-05-05 12:15:40 -03:00
|
|
|
Py_ssize_t i;
|
|
|
|
Py_ssize_t n;
|
|
|
|
PyObject **items;
|
|
|
|
Py_ssize_t totalsize = 0;
|
|
|
|
PyObject *result;
|
|
|
|
char *dest;
|
|
|
|
|
|
|
|
seq = PySequence_Fast(it, "can only join an iterable");
|
|
|
|
if (seq == NULL)
|
2007-02-27 04:49:18 -04:00
|
|
|
return NULL;
|
2006-05-05 12:15:40 -03:00
|
|
|
n = PySequence_Fast_GET_SIZE(seq);
|
|
|
|
items = PySequence_Fast_ITEMS(seq);
|
|
|
|
|
|
|
|
/* Compute the total size, and check that they are all bytes */
|
2007-11-06 17:34:58 -04:00
|
|
|
/* XXX Shouldn't we use _getbuffer() on these items instead? */
|
2006-05-05 12:15:40 -03:00
|
|
|
for (i = 0; i < n; i++) {
|
2007-02-27 04:49:18 -04:00
|
|
|
PyObject *obj = items[i];
|
2007-11-06 17:34:58 -04:00
|
|
|
if (!PyBytes_Check(obj) && !PyString_Check(obj)) {
|
2007-02-27 04:49:18 -04:00
|
|
|
PyErr_Format(PyExc_TypeError,
|
|
|
|
"can only join an iterable of bytes "
|
|
|
|
"(item %ld has type '%.100s')",
|
2006-07-27 18:53:35 -03:00
|
|
|
/* XXX %ld isn't right on Win64 */
|
2007-12-18 22:45:37 -04:00
|
|
|
(long)i, Py_TYPE(obj)->tp_name);
|
2007-02-27 04:49:18 -04:00
|
|
|
goto error;
|
|
|
|
}
|
2007-05-09 16:52:16 -03:00
|
|
|
if (i > 0)
|
|
|
|
totalsize += mysize;
|
2007-12-18 22:45:37 -04:00
|
|
|
totalsize += Py_SIZE(obj);
|
2007-02-27 04:49:18 -04:00
|
|
|
if (totalsize < 0) {
|
|
|
|
PyErr_NoMemory();
|
|
|
|
goto error;
|
|
|
|
}
|
2006-05-05 12:15:40 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate the result, and copy the bytes */
|
|
|
|
result = PyBytes_FromStringAndSize(NULL, totalsize);
|
|
|
|
if (result == NULL)
|
2007-02-27 04:49:18 -04:00
|
|
|
goto error;
|
2006-05-05 12:15:40 -03:00
|
|
|
dest = PyBytes_AS_STRING(result);
|
|
|
|
for (i = 0; i < n; i++) {
|
2007-02-27 04:49:18 -04:00
|
|
|
PyObject *obj = items[i];
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_ssize_t size = Py_SIZE(obj);
|
2007-11-06 17:34:58 -04:00
|
|
|
char *buf;
|
|
|
|
if (PyBytes_Check(obj))
|
|
|
|
buf = PyBytes_AS_STRING(obj);
|
|
|
|
else
|
|
|
|
buf = PyString_AS_STRING(obj);
|
|
|
|
if (i) {
|
2007-05-09 16:52:16 -03:00
|
|
|
memcpy(dest, self->ob_bytes, mysize);
|
|
|
|
dest += mysize;
|
|
|
|
}
|
2007-11-06 17:34:58 -04:00
|
|
|
memcpy(dest, buf, size);
|
2007-02-27 04:49:18 -04:00
|
|
|
dest += size;
|
2006-05-05 12:15:40 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Done */
|
|
|
|
Py_DECREF(seq);
|
|
|
|
return result;
|
|
|
|
|
|
|
|
/* Error handling */
|
|
|
|
error:
|
|
|
|
Py_DECREF(seq);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-27 04:40:54 -04:00
|
|
|
PyDoc_STRVAR(fromhex_doc,
|
2007-11-21 15:29:53 -04:00
|
|
|
"bytearray.fromhex(string) -> bytearray\n\
|
2007-02-27 04:40:54 -04:00
|
|
|
\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
Create a bytearray object from a string of hexadecimal numbers.\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
Spaces between two numbers are accepted.\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
Example: bytearray.fromhex('B9 01EF') -> bytearray(b'\\xb9\\x01\\xef').");
|
2007-02-27 04:40:54 -04:00
|
|
|
|
|
|
|
static int
|
2007-10-26 18:46:44 -03:00
|
|
|
hex_digit_to_int(Py_UNICODE c)
|
2007-02-27 04:40:54 -04:00
|
|
|
{
|
2007-10-26 18:46:44 -03:00
|
|
|
if (c >= 128)
|
|
|
|
return -1;
|
2007-10-16 03:31:30 -03:00
|
|
|
if (ISDIGIT(c))
|
2007-02-27 04:49:18 -04:00
|
|
|
return c - '0';
|
|
|
|
else {
|
2007-10-16 03:31:30 -03:00
|
|
|
if (ISUPPER(c))
|
|
|
|
c = TOLOWER(c);
|
2007-02-27 04:49:18 -04:00
|
|
|
if (c >= 'a' && c <= 'f')
|
|
|
|
return c - 'a' + 10;
|
|
|
|
}
|
|
|
|
return -1;
|
2007-02-27 04:40:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_fromhex(PyObject *cls, PyObject *args)
|
|
|
|
{
|
2007-10-16 03:31:30 -03:00
|
|
|
PyObject *newbytes, *hexobj;
|
|
|
|
char *buf;
|
2007-10-26 18:46:44 -03:00
|
|
|
Py_UNICODE *hex;
|
|
|
|
Py_ssize_t hexlen, byteslen, i, j;
|
2007-02-27 04:40:54 -04:00
|
|
|
int top, bot;
|
|
|
|
|
2007-10-26 18:46:44 -03:00
|
|
|
if (!PyArg_ParseTuple(args, "U:fromhex", &hexobj))
|
2007-02-27 04:40:54 -04:00
|
|
|
return NULL;
|
2007-10-26 18:46:44 -03:00
|
|
|
assert(PyUnicode_Check(hexobj));
|
|
|
|
hexlen = PyUnicode_GET_SIZE(hexobj);
|
|
|
|
hex = PyUnicode_AS_UNICODE(hexobj);
|
|
|
|
byteslen = hexlen/2; /* This overestimates if there are spaces */
|
2007-02-27 04:40:54 -04:00
|
|
|
newbytes = PyBytes_FromStringAndSize(NULL, byteslen);
|
2007-10-26 18:46:44 -03:00
|
|
|
if (!newbytes)
|
2007-02-27 04:40:54 -04:00
|
|
|
return NULL;
|
|
|
|
buf = PyBytes_AS_STRING(newbytes);
|
2007-10-26 18:46:44 -03:00
|
|
|
for (i = j = 0; i < hexlen; i += 2) {
|
2007-02-27 04:40:54 -04:00
|
|
|
/* skip over spaces in the input */
|
2007-10-26 18:46:44 -03:00
|
|
|
while (hex[i] == ' ')
|
2007-02-27 04:40:54 -04:00
|
|
|
i++;
|
2007-10-26 18:46:44 -03:00
|
|
|
if (i >= hexlen)
|
2007-02-27 04:40:54 -04:00
|
|
|
break;
|
2007-10-26 18:46:44 -03:00
|
|
|
top = hex_digit_to_int(hex[i]);
|
|
|
|
bot = hex_digit_to_int(hex[i+1]);
|
2007-02-27 04:40:54 -04:00
|
|
|
if (top == -1 || bot == -1) {
|
|
|
|
PyErr_Format(PyExc_ValueError,
|
2007-10-26 18:46:44 -03:00
|
|
|
"non-hexadecimal number found in "
|
|
|
|
"fromhex() arg at position %zd", i);
|
2007-02-27 04:40:54 -04:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
buf[j++] = (top << 4) + bot;
|
|
|
|
}
|
|
|
|
if (PyBytes_Resize(newbytes, j) < 0)
|
|
|
|
goto error;
|
|
|
|
return newbytes;
|
|
|
|
|
|
|
|
error:
|
|
|
|
Py_DECREF(newbytes);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-04-11 02:40:58 -03:00
|
|
|
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_reduce(PyBytesObject *self)
|
|
|
|
{
|
2007-11-02 21:24:24 -03:00
|
|
|
PyObject *latin1, *dict;
|
2007-08-05 17:26:11 -03:00
|
|
|
if (self->ob_bytes)
|
2007-08-29 01:05:57 -03:00
|
|
|
latin1 = PyUnicode_DecodeLatin1(self->ob_bytes,
|
2007-12-18 22:45:37 -04:00
|
|
|
Py_SIZE(self), NULL);
|
2007-08-05 17:26:11 -03:00
|
|
|
else
|
2007-08-29 01:05:57 -03:00
|
|
|
latin1 = PyUnicode_FromString("");
|
2007-11-02 21:24:24 -03:00
|
|
|
|
|
|
|
dict = PyObject_GetAttrString((PyObject *)self, "__dict__");
|
|
|
|
if (dict == NULL) {
|
|
|
|
PyErr_Clear();
|
|
|
|
dict = Py_None;
|
|
|
|
Py_INCREF(dict);
|
|
|
|
}
|
|
|
|
|
2007-12-18 22:45:37 -04:00
|
|
|
return Py_BuildValue("(O(Ns)N)", Py_TYPE(self), latin1, "latin-1", dict);
|
2007-04-11 02:40:58 -03:00
|
|
|
}
|
|
|
|
|
2006-04-22 20:28:04 -03:00
|
|
|
static PySequenceMethods bytes_as_sequence = {
|
2007-02-27 04:40:54 -04:00
|
|
|
(lenfunc)bytes_length, /* sq_length */
|
2007-11-06 17:34:58 -04:00
|
|
|
(binaryfunc)PyBytes_Concat, /* sq_concat */
|
2007-02-27 04:40:54 -04:00
|
|
|
(ssizeargfunc)bytes_repeat, /* sq_repeat */
|
|
|
|
(ssizeargfunc)bytes_getitem, /* sq_item */
|
|
|
|
0, /* sq_slice */
|
|
|
|
(ssizeobjargproc)bytes_setitem, /* sq_ass_item */
|
|
|
|
0, /* sq_ass_slice */
|
2006-04-24 10:47:05 -03:00
|
|
|
(objobjproc)bytes_contains, /* sq_contains */
|
2007-02-27 04:40:54 -04:00
|
|
|
(binaryfunc)bytes_iconcat, /* sq_inplace_concat */
|
|
|
|
(ssizeargfunc)bytes_irepeat, /* sq_inplace_repeat */
|
2006-04-22 20:28:04 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
static PyMappingMethods bytes_as_mapping = {
|
2006-04-24 10:47:05 -03:00
|
|
|
(lenfunc)bytes_length,
|
2006-12-19 04:30:14 -04:00
|
|
|
(binaryfunc)bytes_subscript,
|
|
|
|
(objobjargproc)bytes_ass_subscript,
|
2006-04-22 20:28:04 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
static PyBufferProcs bytes_as_buffer = {
|
2007-08-18 08:21:56 -03:00
|
|
|
(getbufferproc)bytes_getbuffer,
|
|
|
|
(releasebufferproc)bytes_releasebuffer,
|
2006-04-22 20:28:04 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
static PyMethodDef
|
|
|
|
bytes_methods[] = {
|
2007-10-26 18:46:44 -03:00
|
|
|
{"__alloc__", (PyCFunction)bytes_alloc, METH_NOARGS, alloc_doc},
|
|
|
|
{"__reduce__", (PyCFunction)bytes_reduce, METH_NOARGS, reduce_doc},
|
|
|
|
{"append", (PyCFunction)bytes_append, METH_O, append__doc__},
|
2007-10-16 03:31:30 -03:00
|
|
|
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
|
|
|
|
_Py_capitalize__doc__},
|
2007-10-26 18:46:44 -03:00
|
|
|
{"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__},
|
|
|
|
{"count", (PyCFunction)bytes_count, METH_VARARGS, count__doc__},
|
2006-04-24 10:47:05 -03:00
|
|
|
{"decode", (PyCFunction)bytes_decode, METH_VARARGS, decode_doc},
|
2007-10-26 18:46:44 -03:00
|
|
|
{"endswith", (PyCFunction)bytes_endswith, METH_VARARGS, endswith__doc__},
|
|
|
|
{"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS,
|
|
|
|
expandtabs__doc__},
|
|
|
|
{"extend", (PyCFunction)bytes_extend, METH_O, extend__doc__},
|
|
|
|
{"find", (PyCFunction)bytes_find, METH_VARARGS, find__doc__},
|
2007-04-11 02:40:58 -03:00
|
|
|
{"fromhex", (PyCFunction)bytes_fromhex, METH_VARARGS|METH_CLASS,
|
|
|
|
fromhex_doc},
|
2007-10-26 18:46:44 -03:00
|
|
|
{"index", (PyCFunction)bytes_index, METH_VARARGS, index__doc__},
|
|
|
|
{"insert", (PyCFunction)bytes_insert, METH_VARARGS, insert__doc__},
|
|
|
|
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
|
|
|
|
_Py_isalnum__doc__},
|
|
|
|
{"isalpha", (PyCFunction)stringlib_isalpha, METH_NOARGS,
|
|
|
|
_Py_isalpha__doc__},
|
|
|
|
{"isdigit", (PyCFunction)stringlib_isdigit, METH_NOARGS,
|
|
|
|
_Py_isdigit__doc__},
|
|
|
|
{"islower", (PyCFunction)stringlib_islower, METH_NOARGS,
|
|
|
|
_Py_islower__doc__},
|
|
|
|
{"isspace", (PyCFunction)stringlib_isspace, METH_NOARGS,
|
|
|
|
_Py_isspace__doc__},
|
|
|
|
{"istitle", (PyCFunction)stringlib_istitle, METH_NOARGS,
|
|
|
|
_Py_istitle__doc__},
|
|
|
|
{"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,
|
|
|
|
_Py_isupper__doc__},
|
2007-05-09 16:52:16 -03:00
|
|
|
{"join", (PyCFunction)bytes_join, METH_O, join_doc},
|
2007-10-16 03:31:30 -03:00
|
|
|
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
|
2007-10-26 18:46:44 -03:00
|
|
|
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
|
|
|
|
{"lstrip", (PyCFunction)bytes_lstrip, METH_VARARGS, lstrip__doc__},
|
|
|
|
{"partition", (PyCFunction)bytes_partition, METH_O, partition__doc__},
|
|
|
|
{"pop", (PyCFunction)bytes_pop, METH_VARARGS, pop__doc__},
|
|
|
|
{"remove", (PyCFunction)bytes_remove, METH_O, remove__doc__},
|
|
|
|
{"replace", (PyCFunction)bytes_replace, METH_VARARGS, replace__doc__},
|
|
|
|
{"reverse", (PyCFunction)bytes_reverse, METH_NOARGS, reverse__doc__},
|
|
|
|
{"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, rfind__doc__},
|
|
|
|
{"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, rindex__doc__},
|
2007-10-16 03:31:30 -03:00
|
|
|
{"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__},
|
2007-10-26 18:46:44 -03:00
|
|
|
{"rpartition", (PyCFunction)bytes_rpartition, METH_O, rpartition__doc__},
|
|
|
|
{"rsplit", (PyCFunction)bytes_rsplit, METH_VARARGS, rsplit__doc__},
|
|
|
|
{"rstrip", (PyCFunction)bytes_rstrip, METH_VARARGS, rstrip__doc__},
|
|
|
|
{"split", (PyCFunction)bytes_split, METH_VARARGS, split__doc__},
|
2007-10-16 03:31:30 -03:00
|
|
|
{"splitlines", (PyCFunction)stringlib_splitlines, METH_VARARGS,
|
|
|
|
splitlines__doc__},
|
2007-10-26 18:46:44 -03:00
|
|
|
{"startswith", (PyCFunction)bytes_startswith, METH_VARARGS ,
|
|
|
|
startswith__doc__},
|
|
|
|
{"strip", (PyCFunction)bytes_strip, METH_VARARGS, strip__doc__},
|
|
|
|
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
|
|
|
|
_Py_swapcase__doc__},
|
|
|
|
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
|
|
|
|
{"translate", (PyCFunction)bytes_translate, METH_VARARGS,
|
|
|
|
translate__doc__},
|
|
|
|
{"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},
|
|
|
|
{"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__},
|
2006-05-05 01:34:18 -03:00
|
|
|
{NULL}
|
2006-04-22 20:28:04 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
PyDoc_STRVAR(bytes_doc,
|
2007-11-21 15:29:53 -04:00
|
|
|
"bytearray(iterable_of_ints) -> bytearray.\n\
|
|
|
|
bytearray(string, encoding[, errors]) -> bytearray.\n\
|
|
|
|
bytearray(bytes_or_bytearray) -> mutable copy of bytes_or_bytearray.\n\
|
|
|
|
bytearray(memory_view) -> bytearray.\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
Construct an mutable bytearray object from:\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
- an iterable yielding integers in range(256)\n\
|
|
|
|
- a text string encoded using the specified encoding\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
- a bytes or a bytearray object\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
- any object implementing the buffer API.\n\
|
2006-04-22 20:28:04 -03:00
|
|
|
\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
bytearray(int) -> bytearray.\n\
|
2007-11-06 17:34:58 -04:00
|
|
|
\n\
|
2007-11-21 15:29:53 -04:00
|
|
|
Construct a zero-initialized bytearray of the given length.");
|
2007-11-06 17:34:58 -04:00
|
|
|
|
2006-04-22 20:28:04 -03:00
|
|
|
|
2007-10-26 14:39:48 -03:00
|
|
|
static PyObject *bytes_iter(PyObject *seq);
|
|
|
|
|
2006-04-22 20:28:04 -03:00
|
|
|
PyTypeObject PyBytes_Type = {
|
Merged revisions 56467-56482 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/p3yk
................
r56477 | martin.v.loewis | 2007-07-21 09:04:38 +0200 (Sa, 21 Jul 2007) | 11 lines
Merged revisions 56466-56476 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r56476 | martin.v.loewis | 2007-07-21 08:55:02 +0200 (Sa, 21 Jul 2007) | 4 lines
PEP 3123: Provide forward compatibility with Python 3.0, while keeping
backwards compatibility. Add Py_Refcnt, Py_Type, Py_Size, and
PyVarObject_HEAD_INIT.
........
................
r56478 | martin.v.loewis | 2007-07-21 09:47:23 +0200 (Sa, 21 Jul 2007) | 2 lines
PEP 3123: Use proper C inheritance for PyObject.
................
r56479 | martin.v.loewis | 2007-07-21 10:06:55 +0200 (Sa, 21 Jul 2007) | 3 lines
Add longintrepr.h to Python.h, so that the compiler can
see that PyFalse is really some kind of PyObject*.
................
r56480 | martin.v.loewis | 2007-07-21 10:47:18 +0200 (Sa, 21 Jul 2007) | 2 lines
Qualify SHIFT, MASK, BASE.
................
r56482 | martin.v.loewis | 2007-07-21 19:10:57 +0200 (Sa, 21 Jul 2007) | 2 lines
Correctly refer to _ob_next.
................
2007-07-21 14:22:18 -03:00
|
|
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
2007-11-21 15:29:53 -04:00
|
|
|
"bytearray",
|
2006-04-22 20:28:04 -03:00
|
|
|
sizeof(PyBytesObject),
|
|
|
|
0,
|
2006-04-24 10:47:05 -03:00
|
|
|
(destructor)bytes_dealloc, /* tp_dealloc */
|
|
|
|
0, /* tp_print */
|
|
|
|
0, /* tp_getattr */
|
|
|
|
0, /* tp_setattr */
|
|
|
|
0, /* tp_compare */
|
|
|
|
(reprfunc)bytes_repr, /* tp_repr */
|
|
|
|
0, /* tp_as_number */
|
|
|
|
&bytes_as_sequence, /* tp_as_sequence */
|
|
|
|
&bytes_as_mapping, /* tp_as_mapping */
|
2007-02-27 04:49:18 -04:00
|
|
|
0, /* tp_hash */
|
2006-04-24 10:47:05 -03:00
|
|
|
0, /* tp_call */
|
2007-11-06 17:34:58 -04:00
|
|
|
bytes_str, /* tp_str */
|
2006-04-24 10:47:05 -03:00
|
|
|
PyObject_GenericGetAttr, /* tp_getattro */
|
|
|
|
0, /* tp_setattro */
|
|
|
|
&bytes_as_buffer, /* tp_as_buffer */
|
2007-11-02 21:24:24 -03:00
|
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
2006-04-24 10:47:05 -03:00
|
|
|
bytes_doc, /* tp_doc */
|
|
|
|
0, /* tp_traverse */
|
|
|
|
0, /* tp_clear */
|
|
|
|
(richcmpfunc)bytes_richcompare, /* tp_richcompare */
|
|
|
|
0, /* tp_weaklistoffset */
|
2007-10-26 14:39:48 -03:00
|
|
|
bytes_iter, /* tp_iter */
|
2006-04-24 10:47:05 -03:00
|
|
|
0, /* tp_iternext */
|
|
|
|
bytes_methods, /* tp_methods */
|
|
|
|
0, /* tp_members */
|
|
|
|
0, /* tp_getset */
|
|
|
|
0, /* tp_base */
|
|
|
|
0, /* tp_dict */
|
|
|
|
0, /* tp_descr_get */
|
|
|
|
0, /* tp_descr_set */
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
(initproc)bytes_init, /* tp_init */
|
|
|
|
PyType_GenericAlloc, /* tp_alloc */
|
|
|
|
PyType_GenericNew, /* tp_new */
|
|
|
|
PyObject_Del, /* tp_free */
|
2006-04-22 20:28:04 -03:00
|
|
|
};
|
2007-10-26 14:39:48 -03:00
|
|
|
|
|
|
|
/*********************** Bytes Iterator ****************************/
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
PyObject_HEAD
|
|
|
|
Py_ssize_t it_index;
|
|
|
|
PyBytesObject *it_seq; /* Set to NULL when iterator is exhausted */
|
|
|
|
} bytesiterobject;
|
|
|
|
|
|
|
|
static void
|
|
|
|
bytesiter_dealloc(bytesiterobject *it)
|
|
|
|
{
|
|
|
|
_PyObject_GC_UNTRACK(it);
|
|
|
|
Py_XDECREF(it->it_seq);
|
|
|
|
PyObject_GC_Del(it);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
bytesiter_traverse(bytesiterobject *it, visitproc visit, void *arg)
|
|
|
|
{
|
|
|
|
Py_VISIT(it->it_seq);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytesiter_next(bytesiterobject *it)
|
|
|
|
{
|
|
|
|
PyBytesObject *seq;
|
|
|
|
PyObject *item;
|
|
|
|
|
|
|
|
assert(it != NULL);
|
|
|
|
seq = it->it_seq;
|
|
|
|
if (seq == NULL)
|
|
|
|
return NULL;
|
|
|
|
assert(PyBytes_Check(seq));
|
|
|
|
|
|
|
|
if (it->it_index < PyBytes_GET_SIZE(seq)) {
|
2007-12-02 10:31:20 -04:00
|
|
|
item = PyLong_FromLong(
|
2007-10-26 14:39:48 -03:00
|
|
|
(unsigned char)seq->ob_bytes[it->it_index]);
|
|
|
|
if (item != NULL)
|
|
|
|
++it->it_index;
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_DECREF(seq);
|
|
|
|
it->it_seq = NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytesiter_length_hint(bytesiterobject *it)
|
|
|
|
{
|
|
|
|
Py_ssize_t len = 0;
|
|
|
|
if (it->it_seq)
|
|
|
|
len = PyBytes_GET_SIZE(it->it_seq) - it->it_index;
|
2007-12-02 10:31:20 -04:00
|
|
|
return PyLong_FromSsize_t(len);
|
2007-10-26 14:39:48 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(length_hint_doc,
|
|
|
|
"Private method returning an estimate of len(list(it)).");
|
|
|
|
|
|
|
|
static PyMethodDef bytesiter_methods[] = {
|
|
|
|
{"__length_hint__", (PyCFunction)bytesiter_length_hint, METH_NOARGS,
|
|
|
|
length_hint_doc},
|
|
|
|
{NULL, NULL} /* sentinel */
|
|
|
|
};
|
|
|
|
|
|
|
|
PyTypeObject PyBytesIter_Type = {
|
|
|
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
2007-11-21 15:29:53 -04:00
|
|
|
"bytearray_iterator", /* tp_name */
|
2007-10-26 14:39:48 -03:00
|
|
|
sizeof(bytesiterobject), /* tp_basicsize */
|
|
|
|
0, /* tp_itemsize */
|
|
|
|
/* methods */
|
|
|
|
(destructor)bytesiter_dealloc, /* tp_dealloc */
|
|
|
|
0, /* tp_print */
|
|
|
|
0, /* tp_getattr */
|
|
|
|
0, /* tp_setattr */
|
|
|
|
0, /* tp_compare */
|
|
|
|
0, /* tp_repr */
|
|
|
|
0, /* tp_as_number */
|
|
|
|
0, /* tp_as_sequence */
|
|
|
|
0, /* tp_as_mapping */
|
|
|
|
0, /* tp_hash */
|
|
|
|
0, /* tp_call */
|
|
|
|
0, /* tp_str */
|
|
|
|
PyObject_GenericGetAttr, /* tp_getattro */
|
|
|
|
0, /* tp_setattro */
|
|
|
|
0, /* tp_as_buffer */
|
|
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
|
|
0, /* tp_doc */
|
|
|
|
(traverseproc)bytesiter_traverse, /* tp_traverse */
|
|
|
|
0, /* tp_clear */
|
|
|
|
0, /* tp_richcompare */
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
PyObject_SelfIter, /* tp_iter */
|
|
|
|
(iternextfunc)bytesiter_next, /* tp_iternext */
|
|
|
|
bytesiter_methods, /* tp_methods */
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
bytes_iter(PyObject *seq)
|
|
|
|
{
|
|
|
|
bytesiterobject *it;
|
|
|
|
|
|
|
|
if (!PyBytes_Check(seq)) {
|
|
|
|
PyErr_BadInternalCall();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
it = PyObject_GC_New(bytesiterobject, &PyBytesIter_Type);
|
|
|
|
if (it == NULL)
|
|
|
|
return NULL;
|
|
|
|
it->it_index = 0;
|
|
|
|
Py_INCREF(seq);
|
|
|
|
it->it_seq = (PyBytesObject *)seq;
|
|
|
|
_PyObject_GC_TRACK(it);
|
|
|
|
return (PyObject *)it;
|
|
|
|
}
|