[Python-checkins] r46166 - in sandbox/trunk/newstruct: Modules/_newstruct.c test_newstruct.py

bob.ippolito python-checkins at python.org
Wed May 24 14:27:24 CEST 2006


Author: bob.ippolito
Date: Wed May 24 14:27:22 2006
New Revision: 46166

Modified:
   sandbox/trunk/newstruct/Modules/_newstruct.c
   sandbox/trunk/newstruct/test_newstruct.py
Log:
unpack_from and tests

Modified: sandbox/trunk/newstruct/Modules/_newstruct.c
==============================================================================
--- sandbox/trunk/newstruct/Modules/_newstruct.c	(original)
+++ sandbox/trunk/newstruct/Modules/_newstruct.c	Wed May 24 14:27:22 2006
@@ -1112,43 +1112,19 @@
 	s->ob_type->tp_free((PyObject *)s);
 }
 
-PyDoc_STRVAR(s_unpack__doc__,
-"unpack(str) -> (v1, v2, ...)\n\
-\n\
-Return tuple containing values unpacked according to this Struct's format.\n\
-Requires len(str) == self.size. See newstruct.__doc__ for more on format\n\
-strings.");
-
 static PyObject *
-s_unpack(PyObject *self, PyObject *inputstr)
-{
-	PyStructObject *soself;
-	PyObject *result;
-	char *restart;
+s_unpack_internal(PyStructObject *soself, char *startfrom) {
 	formatcode *code;
-	Py_ssize_t i;
-	
-	soself = (PyStructObject *)self;
-	assert(PyStruct_Check(self));
-	assert(soself->s_codes != NULL);	
-	if (inputstr == NULL || !PyString_Check(inputstr) ||
-	    PyString_GET_SIZE(inputstr) != soself->s_size) {
-		PyErr_Format(StructError,
-			"unpack requires a string argument of length %d", soself->s_size);
-		return NULL;
-	}
-	result = PyTuple_New(soself->s_len);
+	Py_ssize_t i = 0;
+	PyObject *result = PyTuple_New(soself->s_len);
 	if (result == NULL)
 		return NULL;
-	
 
-	restart = PyString_AS_STRING(inputstr);
-	i = 0;
 	for (code = soself->s_codes; code->fmtdef != NULL; code++) {
 		Py_ssize_t n;
 		PyObject *v;
 		const formatdef *e = code->fmtdef;
-		const char *res = restart + code->offset;
+		const char *res = startfrom + code->offset;
 		if (e->format == 's') {
 			v = PyString_FromStringAndSize(res, code->repeat);
 			if (v == NULL)
@@ -1180,6 +1156,73 @@
 };
 
 
+PyDoc_STRVAR(s_unpack__doc__,
+"unpack(str) -> (v1, v2, ...)\n\
+\n\
+Return tuple containing values unpacked according to this Struct's format.\n\
+Requires len(str) == self.size. See newstruct.__doc__ for more on format\n\
+strings.");
+
+static PyObject *
+s_unpack(PyObject *self, PyObject *inputstr)
+{
+	PyStructObject *soself = (PyStructObject *)self;
+	assert(PyStruct_Check(self));
+	assert(soself->s_codes != NULL);	
+	if (inputstr == NULL || !PyString_Check(inputstr) ||
+		PyString_GET_SIZE(inputstr) != soself->s_size) {
+		PyErr_Format(StructError,
+			"unpack requires a string argument of length %d", soself->s_size);
+		return NULL;
+	}
+	return s_unpack_internal(soself, PyString_AS_STRING(inputstr));
+}
+
+PyDoc_STRVAR(s_unpack_from__doc__,
+"unpack_from(buffer[, offset]) -> (v1, v2, ...)\n\
+\n\
+Return tuple containing values unpacked according to this Struct's format.\n\
+Unlike unpack, unpack_from can unpack values from any object supporting\n\
+the buffer API, not just str. Requires len(buffer[offset:]) >= self.size.\n\
+See newstruct.__doc__ for more on format strings.");
+
+static PyObject *
+s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
+{
+	static char *kwlist[] = {"buffer", "offset", 0};
+#if (PY_VERSION_HEX < 0x02050000)
+	static char *fmt = "z#|i:unpack_from";
+#else
+	static char *fmt = "z#|n:unpack_from";
+#endif
+	Py_ssize_t buffer_len = 0, offset = 0;
+	char *buffer = NULL;
+	PyStructObject *soself = (PyStructObject *)self;
+	assert(PyStruct_Check(self));
+	assert(soself->s_codes != NULL);
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist,
+					 &buffer, &buffer_len, &offset))
+        	return NULL;
+
+	if (buffer == NULL) {
+		PyErr_Format(StructError,
+			"unpack_from requires a buffer argument");
+		return NULL;
+	}
+	
+	if (offset < 0)
+		offset += buffer_len;
+
+	if (offset < 0 || (buffer_len - offset) < soself->s_size) {
+		PyErr_Format(StructError,
+			"unpack_from requires a buffer of at least %d bytes",
+			soself->s_size);
+		return NULL;
+	}
+	return s_unpack_internal(soself, buffer + offset);
+}
+
 PyDoc_STRVAR(s_pack__doc__,
 "pack(v1, v2, ...) -> string\n\
 \n\
@@ -1267,8 +1310,9 @@
 /* List of functions */
 
 static struct PyMethodDef s_methods[] = {
-	{"pack",	s_pack,		METH_VARARGS, s_pack__doc__},
-	{"unpack",	s_unpack,	METH_O, s_unpack__doc__},
+	{"pack",	(PyCFunction)s_pack,		METH_VARARGS, s_pack__doc__},
+	{"unpack",	(PyCFunction)s_unpack,		METH_O, s_unpack__doc__},
+	{"unpack_from",	(PyCFunction)s_unpack_from,	METH_KEYWORDS, s_unpack_from__doc__},
 	{NULL,	 NULL}		/* sentinel */
 };
 

Modified: sandbox/trunk/newstruct/test_newstruct.py
==============================================================================
--- sandbox/trunk/newstruct/test_newstruct.py	(original)
+++ sandbox/trunk/newstruct/test_newstruct.py	Wed May 24 14:27:22 2006
@@ -437,3 +437,33 @@
         TestFailed("expected OverflowError")
 
 test_705836()
+
+def test_unpack_from():
+    test_string = 'abcd01234'
+    s = struct.Struct('4s')
+    for cls in (str, buffer):
+        data = cls(test_string)
+        assert s.unpack_from(data) == ('abcd',)
+        assert s.unpack_from(data, 2) == ('cd01',)
+        assert s.unpack_from(data, 4) == ('0123',)
+        for i in xrange(6):
+            assert s.unpack_from(data, i) == (data[i:i+4],)
+        for i in xrange(6, len(test_string) + 1):
+            simple_err(s.unpack_from, data, i)
+
+test_unpack_from()
+
+def test_1229380():
+    for endian in ('', '>', '<'):
+        for cls in (int, long):
+            for fmt in ('B', 'H', 'I', 'L'):
+                any_err(struct.pack, endian + fmt, cls(-1))
+
+            any_err(struct.pack, endian + 'B', cls(300))
+            any_err(struct.pack, endian + 'H', cls(70000))
+
+        any_err(struct.pack, endian + 'I', sys.maxint * 4L)
+        any_err(struct.pack, endian + 'L', sys.maxint * 4L)
+
+if 0:
+    test_1229380()


More information about the Python-checkins mailing list