Author: thomas.wouters
Date: Tue Aug 22 21:54:34 2006
New Revision: 51486
Modified:
python/branches/p3yk-noslice/Include/opcode.h
python/branches/p3yk-noslice/Lib/UserList.py
python/branches/p3yk-noslice/Lib/UserString.py
python/branches/p3yk-noslice/Lib/sre_parse.py
python/branches/p3yk-noslice/Lib/test/list_tests.py
python/branches/p3yk-noslice/Lib/test/output/test_class
python/branches/p3yk-noslice/Lib/test/seq_tests.py
python/branches/p3yk-noslice/Lib/test/string_tests.py
python/branches/p3yk-noslice/Lib/test/test_descr.py
python/branches/p3yk-noslice/Lib/test/test_index.py
python/branches/p3yk-noslice/Lib/test/test_support.py
python/branches/p3yk-noslice/Lib/test/test_userlist.py
python/branches/p3yk-noslice/Objects/bufferobject.c
python/branches/p3yk-noslice/Objects/bytesobject.c
python/branches/p3yk-noslice/Objects/structseq.c
python/branches/p3yk-noslice/Python/ceval.c
python/branches/p3yk-noslice/Python/compile.c
Log:
Checkpoint current status of removing-slice work:
- Add 'extended' (now really just 'normal') slicing support to buffer,
bytes and structseq, including non-default step sizes.
- Fix proxying in UserList, UserString
- Adjust sre_parse to cope with slice objects
(Those three items could be forward-ported to 2.6)
- Remove all 12 SLICE opcodes, freeing up an otherwise unused register vrbl
in ceval.c's PyEval_EvalFrameEx
- Fix tests to not look at __getslice__ (possibly by removing tests too
rigorously)
TODO:
- Fix mmap to support slice objects (test currently fails)
- Fix ctypes to support slice objects (test currently fails)
- Remove PySequenceMethod hooks and rework various API's to index using
slice objects instead
- Remove PySequence_Check and PyMapping_Check (or think of a new way of
spelling them)
- Check removed tests to see if they should be readded
Modified: python/branches/p3yk-noslice/Include/opcode.h
==============================================================================
--- python/branches/p3yk-noslice/Include/opcode.h (original)
+++ python/branches/p3yk-noslice/Include/opcode.h Tue Aug 22 21:54:34 2006
@@ -36,15 +36,6 @@
#define INPLACE_FLOOR_DIVIDE 28
#define INPLACE_TRUE_DIVIDE 29
-#define SLICE 30
-/* Also uses 31-33 */
-
-#define STORE_SLICE 40
-/* Also uses 41-43 */
-
-#define DELETE_SLICE 50
-/* Also uses 51-53 */
-
#define INPLACE_ADD 55
#define INPLACE_SUBTRACT 56
#define INPLACE_MULTIPLY 57
Modified: python/branches/p3yk-noslice/Lib/UserList.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/UserList.py (original)
+++ python/branches/p3yk-noslice/Lib/UserList.py Tue Aug 22 21:54:34 2006
@@ -28,20 +28,6 @@
def __getitem__(self, i): return self.data[i]
def __setitem__(self, i, item): self.data[i] = item
def __delitem__(self, i): del self.data[i]
- def __getslice__(self, i, j):
- i = max(i, 0); j = max(j, 0)
- return self.__class__(self.data[i:j])
- def __setslice__(self, i, j, other):
- i = max(i, 0); j = max(j, 0)
- if isinstance(other, UserList):
- self.data[i:j] = other.data
- elif isinstance(other, type(self.data)):
- self.data[i:j] = other
- else:
- self.data[i:j] = list(other)
- def __delslice__(self, i, j):
- i = max(i, 0); j = max(j, 0)
- del self.data[i:j]
def __add__(self, other):
if isinstance(other, UserList):
return self.__class__(self.data + other.data)
Modified: python/branches/p3yk-noslice/Lib/UserString.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/UserString.py (original)
+++ python/branches/p3yk-noslice/Lib/UserString.py Tue Aug 22 21:54:34 2006
@@ -35,9 +35,6 @@
def __len__(self): return len(self.data)
def __getitem__(self, index): return self.__class__(self.data[index])
- def __getslice__(self, start, end):
- start = max(start, 0); end = max(end, 0)
- return self.__class__(self.data[start:end])
def __add__(self, other):
if isinstance(other, UserString):
@@ -149,26 +146,31 @@
def __hash__(self):
raise TypeError, "unhashable type (it is mutable)"
def __setitem__(self, index, sub):
- if index < 0:
- index += len(self.data)
- if index < 0 or index >= len(self.data): raise IndexError
- self.data = self.data[:index] + sub + self.data[index+1:]
+ if isinstance(index, slice):
+ if isinstance(sub, UserString):
+ sub = sub.data
+ elif not isinstance(sub, basestring):
+ sub = str(sub)
+ start, stop, step = index.indices(len(self.data))
+ if step != 1:
+ raise TypeError, "invalid step in slicing assignment"
+ self.data = self.data[:start] + sub + self.data[stop:]
+ else:
+ if index < 0:
+ index += len(self.data)
+ if index < 0 or index >= len(self.data): raise IndexError
+ self.data = self.data[:index] + sub + self.data[index+1:]
def __delitem__(self, index):
- if index < 0:
- index += len(self.data)
- if index < 0 or index >= len(self.data): raise IndexError
- self.data = self.data[:index] + self.data[index+1:]
- def __setslice__(self, start, end, sub):
- start = max(start, 0); end = max(end, 0)
- if isinstance(sub, UserString):
- self.data = self.data[:start]+sub.data+self.data[end:]
- elif isinstance(sub, basestring):
- self.data = self.data[:start]+sub+self.data[end:]
- else:
- self.data = self.data[:start]+str(sub)+self.data[end:]
- def __delslice__(self, start, end):
- start = max(start, 0); end = max(end, 0)
- self.data = self.data[:start] + self.data[end:]
+ if isinstance(index, slice):
+ start, stop, step = index.indices(len(self.data))
+ if step != 1:
+ raise TypeError, "invalid step in slicing assignment"
+ self.data = self.data[:start] + self.data[stop:]
+ else:
+ if index < 0:
+ index += len(self.data)
+ if index < 0 or index >= len(self.data): raise IndexError
+ self.data = self.data[:index] + self.data[index+1:]
def immutable(self):
return UserString(self.data)
def __iadd__(self, other):
Modified: python/branches/p3yk-noslice/Lib/sre_parse.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/sre_parse.py (original)
+++ python/branches/p3yk-noslice/Lib/sre_parse.py Tue Aug 22 21:54:34 2006
@@ -134,11 +134,11 @@
def __delitem__(self, index):
del self.data[index]
def __getitem__(self, index):
+ if isinstance(index, slice):
+ return SubPattern(self.pattern, self.data[index])
return self.data[index]
def __setitem__(self, index, code):
self.data[index] = code
- def __getslice__(self, start, stop):
- return SubPattern(self.pattern, self.data[start:stop])
def insert(self, index, code):
self.data.insert(index, code)
def append(self, code):
Modified: python/branches/p3yk-noslice/Lib/test/list_tests.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/list_tests.py (original)
+++ python/branches/p3yk-noslice/Lib/test/list_tests.py Tue Aug 22 21:54:34 2006
@@ -178,9 +178,9 @@
a[:] = tuple(range(10))
self.assertEqual(a, self.type2test(range(10)))
- self.assertRaises(TypeError, a.__setslice__, 0, 1, 5)
+ self.assertRaises(TypeError, a.__setitem__, slice(0, 1, 5))
- self.assertRaises(TypeError, a.__setslice__)
+ self.assertRaises(TypeError, a.__setitem__)
def test_delslice(self):
a = self.type2test([0, 1])
Modified: python/branches/p3yk-noslice/Lib/test/output/test_class
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/output/test_class (original)
+++ python/branches/p3yk-noslice/Lib/test/output/test_class Tue Aug 22 21:54:34 2006
@@ -28,9 +28,9 @@
__getitem__: (1,)
__setitem__: (1, 1)
__delitem__: (1,)
-__getslice__: (0, 42)
-__setslice__: (0, 42, 'The Answer')
-__delslice__: (0, 42)
+__getitem__: (slice(None, 42, None),)
+__setitem__: (slice(None, 42, None), 'The Answer')
+__delitem__: (slice(None, 42, None),)
__getitem__: (slice(2, 1024, 10),)
__setitem__: (slice(2, 1024, 10), 'A lot')
__delitem__: (slice(2, 1024, 10),)
Modified: python/branches/p3yk-noslice/Lib/test/seq_tests.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/seq_tests.py (original)
+++ python/branches/p3yk-noslice/Lib/test/seq_tests.py Tue Aug 22 21:54:34 2006
@@ -196,8 +196,6 @@
self.assertEqual(a[ -pow(2,128L): 3 ], self.type2test([0,1,2]))
self.assertEqual(a[ 3: pow(2,145L) ], self.type2test([3,4]))
- self.assertRaises(TypeError, u.__getslice__)
-
def test_contains(self):
u = self.type2test([0, 1, 2])
for i in u:
Modified: python/branches/p3yk-noslice/Lib/test/string_tests.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/string_tests.py (original)
+++ python/branches/p3yk-noslice/Lib/test/string_tests.py Tue Aug 22 21:54:34 2006
@@ -911,20 +911,6 @@
self.checkraises(TypeError, 'abc', '__getitem__', 'def')
- def test_slice(self):
- self.checkequal('abc', 'abc', '__getslice__', 0, 1000)
- self.checkequal('abc', 'abc', '__getslice__', 0, 3)
- self.checkequal('ab', 'abc', '__getslice__', 0, 2)
- self.checkequal('bc', 'abc', '__getslice__', 1, 3)
- self.checkequal('b', 'abc', '__getslice__', 1, 2)
- self.checkequal('', 'abc', '__getslice__', 2, 2)
- self.checkequal('', 'abc', '__getslice__', 1000, 1000)
- self.checkequal('', 'abc', '__getslice__', 2000, 1000)
- self.checkequal('', 'abc', '__getslice__', 2, 1)
- # FIXME What about negative indizes? This is handled differently by [] and __getslice__
-
- self.checkraises(TypeError, 'abc', '__getslice__', 'def')
-
def test_mul(self):
self.checkequal('', 'abc', '__mul__', -1)
self.checkequal('', 'abc', '__mul__', 0)
Modified: python/branches/p3yk-noslice/Lib/test/test_descr.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/test_descr.py (original)
+++ python/branches/p3yk-noslice/Lib/test/test_descr.py Tue Aug 22 21:54:34 2006
@@ -39,7 +39,7 @@
bm = getattr(a, meth)
vereq(bm(b), res)
-def testternop(a, b, c, res, expr="a[b:c]", meth="__getslice__"):
+def testternop(a, b, c, res, expr="a[b:c]", meth="__getitem__"):
if verbose: print "checking", expr
dict = {'a': a, 'b': b, 'c': c}
vereq(eval(expr, dict), res)
@@ -48,9 +48,9 @@
while meth not in t.__dict__:
t = t.__bases__[0]
vereq(m, t.__dict__[meth])
- vereq(m(a, b, c), res)
+ vereq(m(a, slice(b, c, None)), res)
bm = getattr(a, meth)
- vereq(bm(b, c), res)
+ vereq(bm(slice(b, c, None)), res)
def testsetop(a, b, res, stmt="a+=b", meth="__iadd__"):
if verbose: print "checking", stmt
@@ -88,7 +88,7 @@
bm(b, c)
vereq(dict['a'], res)
-def testset3op(a, b, c, d, res, stmt="a[b:c]=d", meth="__setslice__"):
+def testset3op(a, b, c, d, res, stmt="a[b:c]=d", meth="__setitem__"):
if verbose: print "checking", stmt
dict = {'a': deepcopy(a), 'b': b, 'c': c, 'd': d}
exec stmt in dict
@@ -99,11 +99,11 @@
m = getattr(t, meth)
vereq(m, t.__dict__[meth])
dict['a'] = deepcopy(a)
- m(dict['a'], b, c, d)
+ m(dict['a'], slice(b, c, None), d)
vereq(dict['a'], res)
dict['a'] = deepcopy(a)
bm = getattr(dict['a'], meth)
- bm(b, c, d)
+ bm(slice(b, c, None), d)
vereq(dict['a'], res)
def class_docstrings():
@@ -140,14 +140,14 @@
testbinop([1,2,3], 2, 1, "b in a", "__contains__")
testbinop([1,2,3], 4, 0, "b in a", "__contains__")
testbinop([1,2,3], 1, 2, "a[b]", "__getitem__")
- testternop([1,2,3], 0, 2, [1,2], "a[b:c]", "__getslice__")
+ testternop([1,2,3], 0, 2, [1,2], "a[b:c]", "__getitem__")
testsetop([1], [2], [1,2], "a+=b", "__iadd__")
testsetop([1,2], 3, [1,2,1,2,1,2], "a*=b", "__imul__")
testunop([1,2,3], 3, "len(a)", "__len__")
testbinop([1,2], 3, [1,2,1,2,1,2], "a*b", "__mul__")
testbinop([1,2], 3, [1,2,1,2,1,2], "b*a", "__rmul__")
testset2op([1,2], 1, 3, [1,3], "a[b]=c", "__setitem__")
- testset3op([1,2,3,4], 1, 3, [5,6], [1,5,6,4], "a[b:c]=d", "__setslice__")
+ testset3op([1,2,3,4], 1, 3, [5,6], [1,5,6,4], "a[b:c]=d", "__setitem__")
def dicts():
if verbose: print "Testing dict operations..."
@@ -490,7 +490,7 @@
testbinop(spamlist([1,2,3]), 4, 0, "b in a", "__contains__")
testbinop(spamlist([1,2,3]), 1, 2, "a[b]", "__getitem__")
testternop(spamlist([1,2,3]), 0, 2, spamlist([1,2]),
- "a[b:c]", "__getslice__")
+ "a[b:c]", "__getitem__")
testsetop(spamlist([1]), spamlist([2]), spamlist([1,2]),
"a+=b", "__iadd__")
testsetop(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "a*=b", "__imul__")
@@ -499,7 +499,7 @@
testbinop(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "b*a", "__rmul__")
testset2op(spamlist([1,2]), 1, 3, spamlist([1,3]), "a[b]=c", "__setitem__")
testset3op(spamlist([1,2,3,4]), 1, 3, spamlist([5,6]),
- spamlist([1,5,6,4]), "a[b:c]=d", "__setslice__")
+ spamlist([1,5,6,4]), "a[b:c]=d", "__setitem__")
# Test subclassing
class C(spam.spamlist):
def foo(self): return 1
@@ -613,9 +613,9 @@
if verbose: print "Testing Python subclass of list..."
class C(list):
def __getitem__(self, i):
+ if isinstance(i, slice):
+ return i.start, i.stop
return list.__getitem__(self, i) + 100
- def __getslice__(self, i, j):
- return (i, j)
a = C()
a.extend([0,1,2])
vereq(a[0], 100)
@@ -1580,13 +1580,6 @@
def __delitem__(self, key):
self.delitem = key
- def __getslice__(self, i, j):
- return ("getslice", i, j)
- def __setslice__(self, i, j, value):
- self.setslice = (i, j, value)
- def __delslice__(self, i, j):
- self.delslice = (i, j)
-
a = C()
vereq(a.foo, ("getattr", "foo"))
a.foo = 12
@@ -1600,11 +1593,11 @@
del a[12]
vereq(a.delitem, 12)
- vereq(a[0:10], ("getslice", 0, 10))
+ vereq(a[0:10], ("getitem", slice(0, 10, None)))
a[0:10] = "foo"
- vereq(a.setslice, (0, 10, "foo"))
+ vereq(a.setitem, (slice(0, 10, None), "foo"))
del a[0:10]
- vereq(a.delslice, (0, 10))
+ vereq(a.delitem, slice(0, 10, None))
def methods():
if verbose: print "Testing methods..."
Modified: python/branches/p3yk-noslice/Lib/test/test_index.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/test_index.py (original)
+++ python/branches/p3yk-noslice/Lib/test/test_index.py Tue Aug 22 21:54:34 2006
@@ -188,12 +188,10 @@
return maxint
def __getitem__(self, key):
return key
- def __getslice__(self, i, j):
- return i, j
x = GetItem()
self.assertEqual(x[self.pos], self.pos)
self.assertEqual(x[self.neg], self.neg)
- self.assertEqual(x[self.neg:self.pos], (-1, maxint))
+ self.assertEqual(x[self.neg:self.pos], slice(self.neg, self.pos, None))
self.assertEqual(x[self.neg:self.pos:1].indices(maxint), (0, maxint, 1))
def test_getitem(self):
Modified: python/branches/p3yk-noslice/Lib/test/test_support.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/test_support.py (original)
+++ python/branches/p3yk-noslice/Lib/test/test_support.py Tue Aug 22 21:54:34 2006
@@ -314,10 +314,7 @@
_2G = 2 * _1G
# Hack to get at the maximum value an internal index can take.
-class _Dummy:
- def __getslice__(self, i, j):
- return j
-MAX_Py_ssize_t = _Dummy()[:]
+MAX_Py_ssize_t = 1<<63
def set_memlimit(limit):
import re
Modified: python/branches/p3yk-noslice/Lib/test/test_userlist.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/test_userlist.py (original)
+++ python/branches/p3yk-noslice/Lib/test/test_userlist.py Tue Aug 22 21:54:34 2006
@@ -7,16 +7,6 @@
class UserListTest(list_tests.CommonTest):
type2test = UserList
- def test_getslice(self):
- super(UserListTest, self).test_getslice()
- l = [0, 1, 2, 3, 4]
- u = self.type2test(l)
- for i in range(-3, 6):
- self.assertEqual(u[:i], l[:i])
- self.assertEqual(u[i:], l[i:])
- for j in xrange(-3, 6):
- self.assertEqual(u[i:j], l[i:j])
-
def test_add_specials(self):
u = UserList("spam")
u2 = u + "eggs"
Modified: python/branches/p3yk-noslice/Objects/bufferobject.c
==============================================================================
--- python/branches/p3yk-noslice/Objects/bufferobject.c (original)
+++ python/branches/p3yk-noslice/Objects/bufferobject.c Tue Aug 22 21:54:34 2006
@@ -466,6 +466,62 @@
right - left);
}
+static PyObject *
+buffer_subscript(PyBufferObject *self, PyObject *item)
+{
+ void *p;
+ Py_ssize_t size;
+
+ if (!get_buf(self, &p, &size, ANY_BUFFER))
+ return NULL;
+ if (PyIndex_Check(item)) {
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ if (i < 0)
+ i += size;
+ return buffer_item(self, i);
+ }
+ else if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelength, cur, i;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)item, size,
+ &start, &stop, &step, &slicelength) < 0) {
+ return NULL;
+ }
+
+ if (slicelength <= 0)
+ return PyString_FromStringAndSize("", 0);
+ else if (step == 1)
+ return PyString_FromStringAndSize((char *)p + start,
+ stop - start);
+ else {
+ PyObject *result;
+ char *source_buf = (char *)p;
+ char *result_buf = (char *)PyMem_Malloc(slicelength);
+
+ if (result_buf == NULL)
+ return PyErr_NoMemory();
+
+ for (cur = start, i = 0; i < slicelength;
+ cur += step, i++) {
+ result_buf[i] = source_buf[cur];
+ }
+
+ result = PyString_FromStringAndSize(result_buf,
+ slicelength);
+ PyMem_Free(result_buf);
+ return result;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "string indices must be integers");
+ return NULL;
+ }
+}
+
+
static int
buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
{
@@ -575,6 +631,101 @@
return 0;
}
+static int
+buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
+{
+ PyBufferProcs *pb;
+ void *ptr1, *ptr2;
+ Py_ssize_t selfsize;
+ Py_ssize_t othersize;
+ Py_ssize_t start, stop, step, slicelength;
+
+ if ( self->b_readonly ) {
+ PyErr_SetString(PyExc_TypeError,
+ "buffer is read-only");
+ return -1;
+ }
+
+ pb = value ? value->ob_type->tp_as_buffer : NULL;
+ if ( pb == NULL ||
+ pb->bf_getreadbuffer == NULL ||
+ pb->bf_getsegcount == NULL )
+ {
+ PyErr_BadArgument();
+ return -1;
+ }
+ if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
+ {
+ /* ### use a different exception type/message? */
+ PyErr_SetString(PyExc_TypeError,
+ "single-segment buffer object expected");
+ return -1;
+ }
+ if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
+ return -1;
+ 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 += selfsize;
+ return buffer_ass_item(self, i, value);
+ }
+ else if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
+ &start, &stop, &step, &slicelength) < 0)
+ return -1;
+
+ pb = value ? value->ob_type->tp_as_buffer : NULL;
+ if (pb == NULL ||
+ pb->bf_getreadbuffer == NULL ||
+ pb->bf_getsegcount == NULL) {
+ PyErr_BadArgument();
+ return -1;
+ }
+ if ((*pb->bf_getsegcount)(value, NULL) != 1) {
+ /* ### use a different exception type/message? */
+ PyErr_SetString(PyExc_TypeError,
+ "single-segment buffer object expected");
+ return -1;
+ }
+ if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
+ return -1;
+
+ if (othersize != slicelength) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "right operand length must match slice length");
+ return -1;
+ }
+
+ if (slicelength == 0)
+ return 0;
+ else if (step == 1) {
+ memcpy((char *)ptr1 + start, ptr2, slicelength);
+ return 0;
+ }
+ else {
+ Py_ssize_t cur, i;
+ char *resultbuf = (char *)ptr1;
+ char *sourcebuf = (char *)ptr2;
+
+ for (cur = start, i = 0; i < slicelength;
+ cur += step, i++) {
+ ((char *)ptr1)[cur] = ((char *)ptr2)[i];
+ }
+
+ return 0;
+ }
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "buffer indices must be integers");
+ return -1;
+ }
+}
+
/* Buffer methods */
static Py_ssize_t
@@ -650,6 +801,12 @@
(ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
};
+static PyMappingMethods buffer_as_mapping = {
+ (lenfunc)buffer_length,
+ (binaryfunc)buffer_subscript,
+ (objobjargproc)buffer_ass_subscript,
+};
+
static PyBufferProcs buffer_as_buffer = {
(readbufferproc)buffer_getreadbuf,
(writebufferproc)buffer_getwritebuf,
@@ -671,7 +828,7 @@
(reprfunc)buffer_repr, /* tp_repr */
0, /* tp_as_number */
&buffer_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
+ &buffer_as_mapping, /* tp_as_mapping */
(hashfunc)buffer_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)buffer_str, /* tp_str */
Modified: python/branches/p3yk-noslice/Objects/bytesobject.c
==============================================================================
--- python/branches/p3yk-noslice/Objects/bytesobject.c (original)
+++ python/branches/p3yk-noslice/Objects/bytesobject.c Tue Aug 22 21:54:34 2006
@@ -280,6 +280,61 @@
return PyBytes_FromStringAndSize(self->ob_bytes + lo, hi - lo);
}
+static PyObject *
+bytes_subscript(PyBytesObject *self, PyObject *item)
+{
+ if (PyIndex_Check(item)) {
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+
+ if (i < 0)
+ i += PyBytes_GET_SIZE(self);
+
+ if (i < 0 || i >= self->ob_size) {
+ PyErr_SetString(PyExc_IndexError, "bytes index out of range");
+ return NULL;
+ }
+ return PyInt_FromLong((unsigned char)(self->ob_bytes[i]));
+ }
+ 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;
+ }
+
+ 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;
+
+ if (result_buf == NULL)
+ return PyErr_NoMemory();
+
+ 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 {
+ PyErr_SetString(PyExc_TypeError, "bytes indices must be integers");
+ return NULL;
+ }
+}
+
static int
bytes_setslice(PyBytesObject *self, Py_ssize_t lo, Py_ssize_t hi,
PyObject *values)
@@ -379,6 +434,158 @@
}
static int
+bytes_ass_subscript(PyBytesObject *self, PyObject *item, PyObject *values)
+{
+ Py_ssize_t start, stop, step, slicelen, needed;
+ char *bytes;
+
+ 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);
+
+ if (i < 0 || i >= self->ob_size) {
+ PyErr_SetString(PyExc_IndexError, "bytes index out of range");
+ return -1;
+ }
+
+ 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 {
+ PyErr_SetString(PyExc_TypeError, "bytes indices must be integer");
+ 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;
+ needed = ((PyBytesObject *)values)->ob_size;
+ }
+
+ 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,
+ self->ob_size - stop);
+ }
+ if (PyBytes_Resize((PyObject *)self,
+ self->ob_size + needed - slicelen) < 0)
+ 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,
+ self->ob_size - start - needed);
+ }
+ }
+
+ if (needed > 0)
+ memcpy(self->ob_bytes + start, bytes, needed);
+
+ return 0;
+ }
+ else {
+ if (needed == 0) {
+ /* Delete slice */
+ Py_ssize_t cur, i;
+
+ 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;
+
+ if (cur + step >= PyBytes_GET_SIZE(self))
+ lim = PyBytes_GET_SIZE(self) - cur - 1;
+
+ 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 + 1;
+ 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;
+
+ 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;
+ }
+ }
+}
+
+static int
bytes_init(PyBytesObject *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"source", "encoding", "errors", 0};
@@ -784,8 +991,8 @@
static PyMappingMethods bytes_as_mapping = {
(lenfunc)bytes_length,
- (binaryfunc)0,
- 0,
+ (binaryfunc)bytes_subscript,
+ (objobjargproc)bytes_ass_subscript,
};
static PyBufferProcs bytes_as_buffer = {
Modified: python/branches/p3yk-noslice/Objects/structseq.c
==============================================================================
--- python/branches/p3yk-noslice/Objects/structseq.c (original)
+++ python/branches/p3yk-noslice/Objects/structseq.c Tue Aug 22 21:54:34 2006
@@ -90,6 +90,54 @@
}
static PyObject *
+structseq_subscript(PyStructSequence *self, PyObject *item)
+{
+ if (PyIndex_Check(item)) {
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+
+ if (i < 0)
+ i += VISIBLE_SIZE(self);
+
+ if (i < 0 || i >= VISIBLE_SIZE(self)) {
+ PyErr_SetString(PyExc_IndexError,
+ "tuple index out of range");
+ return NULL;
+ }
+ Py_INCREF(self->ob_item[i]);
+ return self->ob_item[i];
+ }
+ else if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelen, cur, i;
+ PyObject *result;
+
+ if (PySlice_GetIndicesEx((PySliceObject *)item,
+ VISIBLE_SIZE(self), &start, &stop,
+ &step, &slicelen) < 0) {
+ return NULL;
+ }
+ if (slicelen <= 0)
+ return PyTuple_New(0);
+ result = PyTuple_New(slicelen);
+ if (result == NULL)
+ return NULL;
+ for (cur = start, i = 0; i < slicelen;
+ cur += step, i++) {
+ PyObject *v = self->ob_item[cur];
+ Py_INCREF(v);
+ PyTuple_SET_ITEM(result, i, v);
+ }
+ return result;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "structseq indices must be integers");
+ return NULL;
+ }
+}
+
+static PyObject *
structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *arg = NULL;
@@ -298,6 +346,11 @@
(objobjproc)structseq_contains, /* sq_contains */
};
+static PyMappingMethods structseq_as_mapping = {
+ (lenfunc)structseq_length,
+ (binaryfunc)structseq_subscript,
+};
+
static PyMethodDef structseq_methods[] = {
{"__reduce__", (PyCFunction)structseq_reduce,
METH_NOARGS, NULL},
@@ -318,7 +371,7 @@
(reprfunc)structseq_repr, /* tp_repr */
0, /* tp_as_number */
&structseq_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
+ &structseq_as_mapping, /* tp_as_mapping */
structseq_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
Modified: python/branches/p3yk-noslice/Python/ceval.c
==============================================================================
--- python/branches/p3yk-noslice/Python/ceval.c (original)
+++ python/branches/p3yk-noslice/Python/ceval.c Tue Aug 22 21:54:34 2006
@@ -111,9 +111,6 @@
static int maybe_call_line_trace(Py_tracefunc, PyObject *,
PyFrameObject *, int *, int *, int *);
-static PyObject * apply_slice(PyObject *, PyObject *, PyObject *);
-static int assign_slice(PyObject *, PyObject *,
- PyObject *, PyObject *);
static PyObject * cmp_outcome(int, PyObject *, PyObject *);
static PyObject * import_from(PyObject *, PyObject *);
static int import_all_from(PyObject *, PyObject *);
@@ -525,7 +522,6 @@
register PyObject *v; /* Temporary objects popped off stack */
register PyObject *w;
register PyObject *u;
- register PyObject *t;
register PyObject *stream = NULL; /* for PRINT opcodes */
register PyObject **fastlocals, **freevars;
PyObject *retval = NULL; /* Return value */
@@ -1398,70 +1394,6 @@
if (x != NULL) continue;
break;
- case SLICE+0:
- case SLICE+1:
- case SLICE+2:
- case SLICE+3:
- if ((opcode-SLICE) & 2)
- w = POP();
- else
- w = NULL;
- if ((opcode-SLICE) & 1)
- v = POP();
- else
- v = NULL;
- u = TOP();
- x = apply_slice(u, v, w);
- Py_DECREF(u);
- Py_XDECREF(v);
- Py_XDECREF(w);
- SET_TOP(x);
- if (x != NULL) continue;
- break;
-
- case STORE_SLICE+0:
- case STORE_SLICE+1:
- case STORE_SLICE+2:
- case STORE_SLICE+3:
- if ((opcode-STORE_SLICE) & 2)
- w = POP();
- else
- w = NULL;
- if ((opcode-STORE_SLICE) & 1)
- v = POP();
- else
- v = NULL;
- u = POP();
- t = POP();
- err = assign_slice(u, v, w, t); /* u[v:w] = t */
- Py_DECREF(t);
- Py_DECREF(u);
- Py_XDECREF(v);
- Py_XDECREF(w);
- if (err == 0) continue;
- break;
-
- case DELETE_SLICE+0:
- case DELETE_SLICE+1:
- case DELETE_SLICE+2:
- case DELETE_SLICE+3:
- if ((opcode-DELETE_SLICE) & 2)
- w = POP();
- else
- w = NULL;
- if ((opcode-DELETE_SLICE) & 1)
- v = POP();
- else
- v = NULL;
- u = POP();
- err = assign_slice(u, v, w, (PyObject *)NULL);
- /* del u[v:w] */
- Py_DECREF(u);
- Py_XDECREF(v);
- Py_XDECREF(w);
- if (err == 0) continue;
- break;
-
case STORE_SUBSCR:
w = TOP();
v = SECOND();
@@ -3842,70 +3774,6 @@
return 1;
}
-#undef ISINDEX
-#define ISINDEX(x) ((x) == NULL || \
- PyInt_Check(x) || PyLong_Check(x) || PyIndex_Check(x))
-
-static PyObject *
-apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
-{
- PyTypeObject *tp = u->ob_type;
- PySequenceMethods *sq = tp->tp_as_sequence;
-
- if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) {
- Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
- if (!_PyEval_SliceIndex(v, &ilow))
- return NULL;
- if (!_PyEval_SliceIndex(w, &ihigh))
- return NULL;
- return PySequence_GetSlice(u, ilow, ihigh);
- }
- else {
- PyObject *slice = PySlice_New(v, w, NULL);
- if (slice != NULL) {
- PyObject *res = PyObject_GetItem(u, slice);
- Py_DECREF(slice);
- return res;
- }
- else
- return NULL;
- }
-}
-
-static int
-assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
- /* u[v:w] = x */
-{
- PyTypeObject *tp = u->ob_type;
- PySequenceMethods *sq = tp->tp_as_sequence;
-
- if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) {
- Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
- if (!_PyEval_SliceIndex(v, &ilow))
- return -1;
- if (!_PyEval_SliceIndex(w, &ihigh))
- return -1;
- if (x == NULL)
- return PySequence_DelSlice(u, ilow, ihigh);
- else
- return PySequence_SetSlice(u, ilow, ihigh, x);
- }
- else {
- PyObject *slice = PySlice_New(v, w, NULL);
- if (slice != NULL) {
- int res;
- if (x != NULL)
- res = PyObject_SetItem(u, slice, x);
- else
- res = PyObject_DelItem(u, slice);
- Py_DECREF(slice);
- return res;
- }
- else
- return -1;
- }
-}
-
static PyObject *
cmp_outcome(int op, register PyObject *v, register PyObject *w)
{
Modified: python/branches/p3yk-noslice/Python/compile.c
==============================================================================
--- python/branches/p3yk-noslice/Python/compile.c (original)
+++ python/branches/p3yk-noslice/Python/compile.c Tue Aug 22 21:54:34 2006
@@ -741,33 +741,6 @@
case INPLACE_TRUE_DIVIDE:
return -1;
- case SLICE+0:
- return 1;
- case SLICE+1:
- return 0;
- case SLICE+2:
- return 0;
- case SLICE+3:
- return -1;
-
- case STORE_SLICE+0:
- return -2;
- case STORE_SLICE+1:
- return -3;
- case STORE_SLICE+2:
- return -3;
- case STORE_SLICE+3:
- return -4;
-
- case DELETE_SLICE+0:
- return -1;
- case DELETE_SLICE+1:
- return -2;
- case DELETE_SLICE+2:
- return -2;
- case DELETE_SLICE+3:
- return -3;
-
case INPLACE_ADD:
case INPLACE_SUBTRACT:
case INPLACE_MULTIPLY:
@@ -3214,57 +3187,6 @@
}
static int
-compiler_simple_slice(struct compiler *c, slice_ty s, expr_context_ty ctx)
-{
- int op = 0, slice_offset = 0, stack_count = 0;
-
- assert(s->v.Slice.step == NULL);
- if (s->v.Slice.lower) {
- slice_offset++;
- stack_count++;
- if (ctx != AugStore)
- VISIT(c, expr, s->v.Slice.lower);
- }
- if (s->v.Slice.upper) {
- slice_offset += 2;
- stack_count++;
- if (ctx != AugStore)
- VISIT(c, expr, s->v.Slice.upper);
- }
-
- if (ctx == AugLoad) {
- switch (stack_count) {
- case 0: ADDOP(c, DUP_TOP); break;
- case 1: ADDOP_I(c, DUP_TOPX, 2); break;
- case 2: ADDOP_I(c, DUP_TOPX, 3); break;
- }
- }
- else if (ctx == AugStore) {
- switch (stack_count) {
- case 0: ADDOP(c, ROT_TWO); break;
- case 1: ADDOP(c, ROT_THREE); break;
- case 2: ADDOP(c, ROT_FOUR); break;
- }
- }
-
- switch (ctx) {
- case AugLoad: /* fall through to Load */
- case Load: op = SLICE; break;
- case AugStore:/* fall through to Store */
- case Store: op = STORE_SLICE; break;
- case Del: op = DELETE_SLICE; break;
- case Param:
- default:
- PyErr_SetString(PyExc_SystemError,
- "param invalid in simple slice");
- return 0;
- }
-
- ADDOP(c, op + slice_offset);
- return 1;
-}
-
-static int
compiler_visit_nested_slice(struct compiler *c, slice_ty s,
expr_context_ty ctx)
{
@@ -3306,8 +3228,6 @@
break;
case Slice_kind:
kindname = "slice";
- if (!s->v.Slice.step)
- return compiler_simple_slice(c, s, ctx);
if (ctx != AugStore) {
if (!compiler_slice(c, s, ctx))
return 0;