[pypy-commit] pypy cpyext-ext: start to implement ByteArrayObject without exposing CAPI ByteArrayObject.ob_* attributes
mattip
pypy.commits at gmail.com
Wed Jun 1 15:21:23 EDT 2016
Author: Matti Picus <matti.picus at gmail.com>
Branch: cpyext-ext
Changeset: r84867:0c496ba45fe1
Date: 2016-06-01 22:10 +0300
http://bitbucket.org/pypy/pypy/changeset/0c496ba45fe1/
Log: start to implement ByteArrayObject without exposing CAPI
ByteArrayObject.ob_* attributes
diff --git a/pypy/module/cpyext/bytearrayobject.py b/pypy/module/cpyext/bytearrayobject.py
--- a/pypy/module/cpyext/bytearrayobject.py
+++ b/pypy/module/cpyext/bytearrayobject.py
@@ -1,5 +1,6 @@
from pypy.interpreter.error import OperationError, oefmt
from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.objspace.std.bytearrayobject import new_bytearray
from pypy.module.cpyext.api import (
cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
PyVarObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
@@ -25,18 +26,18 @@
PyByteArrayObjectStruct = lltype.ForwardReference()
PyByteArrayObject = lltype.Ptr(PyByteArrayObjectStruct)
-PyByteArrayObjectFields = PyVarObjectFields + \
- (("ob_exports", rffi.INT), ("ob_alloc", rffi.LONG), ("ob_bytes", rffi.CCHARP))
+PyByteArrayObjectFields = PyVarObjectFields
+# (("ob_exports", rffi.INT), ("ob_alloc", rffi.LONG), ("ob_bytes", rffi.CCHARP))
cpython_struct("PyByteArrayObject", PyByteArrayObjectFields, PyByteArrayObjectStruct)
@bootstrap_function
def init_bytearrayobject(space):
"Type description of PyByteArrayObject"
- make_typedescr(space.w_str.layout.typedef,
- basestruct=PyByteArrayObject.TO,
- attach=bytearray_attach,
- dealloc=bytearray_dealloc,
- realize=bytearray_realize)
+ #make_typedescr(space.w_bytearray.layout.typedef,
+ # basestruct=PyByteArrayObject.TO,
+ # attach=bytearray_attach,
+ # dealloc=bytearray_dealloc,
+ # realize=bytearray_realize)
PyByteArray_Check, PyByteArray_CheckExact = build_type_checkers("ByteArray", "w_bytearray")
@@ -83,11 +84,16 @@
XXX expand about the buffer protocol, at least somewhere"""
raise NotImplementedError
- at cpython_api([rffi.CCHARP, Py_ssize_t], PyObject)
-def PyByteArray_FromStringAndSize(space, string, len):
+ at cpython_api([rffi.CCHARP, Py_ssize_t], PyObject, result_is_ll=True)
+def PyByteArray_FromStringAndSize(space, char_p, length):
"""Create a new bytearray object from string and its length, len. On
failure, NULL is returned."""
- raise NotImplementedError
+ if char_p:
+ s = rffi.charpsize2str(char_p, length)
+ else:
+ s = length
+ w_buffer = space.call_function(space.w_bytearray, space.wrap(s))
+ return make_ref(space, w_buffer)
@cpython_api([PyObject, PyObject], PyObject)
def PyByteArray_Concat(space, a, b):
@@ -95,12 +101,14 @@
raise NotImplementedError
@cpython_api([PyObject], Py_ssize_t, error=-1)
-def PyByteArray_Size(space, bytearray):
+def PyByteArray_Size(space, w_obj):
"""Return the size of bytearray after checking for a NULL pointer."""
- raise NotImplementedError
+ if not w_obj:
+ return 0
+ return space.len_w(w_obj)
- at cpython_api([PyObject], rffi.CCHARP)
-def PyByteArray_AsString(space, bytearray):
+ at cpython_api([PyObject], rffi.CCHARP, error=0)
+def PyByteArray_AsString(space, w_obj):
"""Return the contents of bytearray as a char array after checking for a
NULL pointer."""
raise NotImplementedError
diff --git a/pypy/module/cpyext/include/bytearrayobject.h b/pypy/module/cpyext/include/bytearrayobject.h
--- a/pypy/module/cpyext/include/bytearrayobject.h
+++ b/pypy/module/cpyext/include/bytearrayobject.h
@@ -14,17 +14,17 @@
* Bytes are not characters; they may be used to encode characters.
* The only way to go between bytes and str/unicode is via encoding
* and decoding.
- * For the convenience of C programmers, the bytes type is considered
- * to contain a char pointer, not an unsigned char pointer.
+ * While CPython exposes interfaces to this object, pypy does not
*/
/* Object layout */
typedef struct {
PyObject_VAR_HEAD
- /* XXX(nnorwitz): should ob_exports be Py_ssize_t? */
+#if 0
int ob_exports; /* how many buffer exports */
Py_ssize_t ob_alloc; /* How many bytes allocated */
char *ob_bytes;
+#endif
} PyByteArrayObject;
#ifdef __cplusplus
diff --git a/pypy/module/cpyext/test/test_bytearrayobject.py b/pypy/module/cpyext/test/test_bytearrayobject.py
--- a/pypy/module/cpyext/test/test_bytearrayobject.py
+++ b/pypy/module/cpyext/test/test_bytearrayobject.py
@@ -22,7 +22,7 @@
result = 1;
}
#ifdef PYPY_VERSION
- expected_size = sizeof(void*)*7;
+ expected_size = sizeof(void*)*3;
#elif defined Py_DEBUG
expected_size = 64;
#else
@@ -62,6 +62,8 @@
return NULL;
Py_DECREF(t);
c = PyByteArray_AsString(s);
+ if (c == NULL)
+ return NULL;
c[0] = 'a';
c[1] = 'b';
c[2] = 0;
@@ -78,7 +80,7 @@
("mutable", "METH_NOARGS",
"""
PyObject *base;
- PyByteArrayObject *obj;
+ PyObject *obj;
char * p_str;
base = PyByteArray_FromStringAndSize("test", 10);
if (PyByteArray_GET_SIZE(base) != 10)
@@ -118,6 +120,22 @@
PyTuple_GetItem(args, 0)), 4);
'''
),
+ ("str_from_bytearray", "METH_VARARGS",
+ '''
+ char * buf;
+ int n;
+ PyObject * obj;
+ obj = PyTuple_GetItem(args, 0);
+ buf = PyByteArray_AsString(obj);
+ if (buf == NULL)
+ {
+ PyErr_SetString(PyExc_ValueError, "non-null bytearray object expected");
+ return NULL;
+ }
+ n = PyByteArray_Size(obj);
+ return PyString_FromStringAndSize(buf, n);
+ '''
+ ),
("concat", "METH_VARARGS",
"""
PyObject * ret, *right, *left;
@@ -136,6 +154,8 @@
return ret;
""")])
assert module.bytearray_from_string("huheduwe") == "huhe"
+ assert module.str_from_bytearray(bytearray('abc')) == 'abc'
+ raises(ValueError, module.str_from_bytearray, 4.0)
ret = module.concat('abc', 'def')
assert ret == 'abcdef'
assert not isinstance(ret, str)
More information about the pypy-commit
mailing list