diff -r 60163fc72017 Doc/howto/clinic.rst --- a/Doc/howto/clinic.rst Mon Jan 13 13:51:42 2014 -0500 +++ b/Doc/howto/clinic.rst Tue Jan 14 19:07:11 2014 +0200 @@ -729,6 +729,11 @@ ``'Z'`` ``Py_UNICODE(nullable=True)`` ``'z'`` ``str(nullable=True)`` ``'z*'`` ``Py_buffer(types='str bytes bytearray buffer', nullable=True)`` +\ ``unsigned_short`` +\ ``unsigned_int`` +\ ``unsigned_long`` +\ ``unsigned_PY_LONG_LONG`` +\ ``size_t`` ========= ================================================================================= As an example, here's our sample ``pickle.Pickler.dump`` using the proper diff -r 60163fc72017 Include/longobject.h --- a/Include/longobject.h Mon Jan 13 13:51:42 2014 -0500 +++ b/Include/longobject.h Tue Jan 14 19:07:11 2014 +0200 @@ -65,6 +65,13 @@ # error "void* different in size from int, long and long long" #endif /* SIZEOF_VOID_P */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _Py_UnsignedShort_Converter(PyObject *, void *); +PyAPI_FUNC(int) _Py_UnsignedInt_Converter(PyObject *, void *); +PyAPI_FUNC(int) _Py_UnsignedLong_Converter(PyObject *, void *); +PyAPI_FUNC(int) _Py_Size_t_Converter(PyObject *, void *); +#endif + /* Used by Python/mystrtoul.c. */ #ifndef Py_LIMITED_API PyAPI_DATA(unsigned char) _PyLong_DigitValue[256]; @@ -91,6 +98,9 @@ PyAPI_FUNC(unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(PyObject *); PyAPI_FUNC(unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLongMask(PyObject *); PyAPI_FUNC(PY_LONG_LONG) PyLong_AsLongLongAndOverflow(PyObject *, int *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _Py_UnsignedLongLong_Converter(PyObject *, void *); +#endif #endif /* HAVE_LONG_LONG */ PyAPI_FUNC(PyObject *) PyLong_FromString(const char *, char **, int); diff -r 60163fc72017 Modules/selectmodule.c --- a/Modules/selectmodule.c Mon Jan 13 13:51:42 2014 -0500 +++ b/Modules/selectmodule.c Tue Jan 14 19:07:11 2014 +0200 @@ -361,24 +361,6 @@ return 1; } -static int -ushort_converter(PyObject *obj, void *ptr) -{ - unsigned long uval; - - uval = PyLong_AsUnsignedLong(obj); - if (uval == (unsigned long)-1 && PyErr_Occurred()) - return 0; - if (uval > USHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "Python int too large for C unsigned short"); - return 0; - } - - *(unsigned short *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned short); - return 1; -} - PyDoc_STRVAR(poll_register_doc, "register(fd [, eventmask] ) -> None\n\n\ Register a file descriptor with the polling object.\n\ @@ -394,7 +376,7 @@ unsigned short events = POLLIN | POLLPRI | POLLOUT; int err; - if (!PyArg_ParseTuple(args, "O|O&:register", &o, ushort_converter, &events)) + if (!PyArg_ParseTuple(args, "O|O&:register", &o, _Py_UnsignedShort_Converter, &events)) return NULL; fd = PyObject_AsFileDescriptor(o); @@ -437,7 +419,7 @@ unsigned short events; int err; - if (!PyArg_ParseTuple(args, "OO&:modify", &o, ushort_converter, &events)) + if (!PyArg_ParseTuple(args, "OO&:modify", &o, _Py_UnsignedShort_Converter, &events)) return NULL; fd = PyObject_AsFileDescriptor(o); @@ -749,7 +731,7 @@ if (self->fd_devpoll < 0) return devpoll_err_closed(); - if (!PyArg_ParseTuple(args, "O|O&:register", &o, ushort_converter, &events)) + if (!PyArg_ParseTuple(args, "O|O&:register", &o, _Py_UnsignedShort_Converter, &events)) return NULL; fd = PyObject_AsFileDescriptor(o); diff -r 60163fc72017 Modules/zlibmodule.c --- a/Modules/zlibmodule.c Mon Jan 13 13:51:42 2014 -0500 +++ b/Modules/zlibmodule.c Tue Jan 14 19:07:11 2014 +0200 @@ -306,46 +306,6 @@ return ReturnVal; } -/*[python input] - -class uint_converter(CConverter): - type = 'unsigned int' - converter = 'uint_converter' - -[python start generated code]*/ -/*[python end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ - -static int -uint_converter(PyObject *obj, void *ptr) -{ - long val; - unsigned long uval; - - val = PyLong_AsLong(obj); - if (val == -1 && PyErr_Occurred()) { - uval = PyLong_AsUnsignedLong(obj); - if (uval == (unsigned long)-1 && PyErr_Occurred()) - return 0; - } - else { - if (val < 0) { - PyErr_SetString(PyExc_ValueError, - "value must be positive"); - return 0; - } - uval = (unsigned long)val; - } - - if (uval > UINT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "Python int too large for C unsigned int"); - return 0; - } - - *(unsigned int *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned int); - return 1; -} - PyDoc_STRVAR(decompress__doc__, "decompress(string[, wbits[, bufsize]]) -- Return decompressed string.\n" "\n" @@ -365,7 +325,7 @@ z_stream zst; if (!PyArg_ParseTuple(args, "y*|iO&:decompress", - &pinput, &wsize, uint_converter, &bufsize)) + &pinput, &wsize, _Py_UnsignedInt_Converter, &bufsize)) return NULL; if ((size_t)pinput.len > UINT_MAX) { @@ -751,7 +711,7 @@ data: Py_buffer The binary data to decompress. - max_length: uint = 0 + max_length: unsigned_int = 0 The maximum allowable length of the decompressed data. Unconsumed input data will be stored in the unconsumed_tail attribute. @@ -794,7 +754,7 @@ if (!PyArg_ParseTuple(args, "y*|O&:decompress", - &data, uint_converter, &max_length)) + &data, _Py_UnsignedInt_Converter, &max_length)) goto exit; return_value = zlib_Decompress_decompress_impl((compobject *)self, &data, max_length); @@ -808,7 +768,7 @@ static PyObject * zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, unsigned int max_length) -/*[clinic end generated code: checksum=e0058024c4a97b411d2e2197791b89fde175f76f]*/ +/*[clinic end generated code: checksum=d4f9c5d6804d7d74a6084acddbcee45975c88953]*/ { int err; unsigned int old_length, length = DEFAULTALLOC; @@ -1178,7 +1138,7 @@ unsigned long start_total_out; Py_ssize_t size; - if (!PyArg_ParseTuple(args, "|O&:flush", uint_converter, &length)) + if (!PyArg_ParseTuple(args, "|O&:flush", _Py_UnsignedInt_Converter, &length)) return NULL; if (length == 0) { PyErr_SetString(PyExc_ValueError, "length must be greater than zero"); diff -r 60163fc72017 Objects/longobject.c --- a/Objects/longobject.c Mon Jan 13 13:51:42 2014 -0500 +++ b/Objects/longobject.c Tue Jan 14 19:07:11 2014 +0200 @@ -1418,6 +1418,86 @@ #endif /* HAVE_LONG_LONG */ +int +_Py_UnsignedShort_Converter(PyObject *obj, void *ptr) +{ + unsigned long uval; + + uval = PyLong_AsUnsignedLong(obj); + if (uval == (unsigned long)-1 && PyErr_Occurred()) + return 0; + if (uval > USHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large for C unsigned short"); + return 0; + } + + *(unsigned short *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned short); + return 1; +} + +int +_Py_UnsignedInt_Converter(PyObject *obj, void *ptr) +{ + unsigned long uval; + + uval = PyLong_AsUnsignedLong(obj); + if (uval == (unsigned long)-1 && PyErr_Occurred()) + return 0; + if (uval > UINT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large for C unsigned int"); + return 0; + } + + *(unsigned int *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned int); + return 1; +} + +int +_Py_UnsignedLong_Converter(PyObject *obj, void *ptr) +{ + unsigned long uval; + + uval = PyLong_AsUnsignedLong(obj); + if (uval == (unsigned long)-1 && PyErr_Occurred()) + return 0; + + *(unsigned long *)ptr = uval; + return 1; +} + +#ifdef HAVE_LONG_LONG + +int +_Py_UnsignedLongLong_Converter(PyObject *obj, void *ptr) +{ + unsigned PY_LONG_LONG uval; + + uval = PyLong_AsUnsignedLongLong(obj); + if (uval == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) + return 0; + + *(unsigned PY_LONG_LONG *)ptr = uval; + return 1; +} + +#endif /* HAVE_LONG_LONG */ + +int +_Py_Size_t_Converter(PyObject *obj, void *ptr) +{ + size_t uval; + + uval = PyLong_AsSize_t(obj); + if (uval == (size_t)-1 && PyErr_Occurred()) + return 0; + + *(size_t *)ptr = uval; + return 1; +} + + #define CHECK_BINOP(v,w) \ do { \ if (!PyLong_Check(v) || !PyLong_Check(w)) \ diff -r 60163fc72017 Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py Mon Jan 13 13:51:42 2014 -0500 +++ b/Tools/clinic/clinic.py Tue Jan 14 19:07:11 2014 +0200 @@ -1681,12 +1681,13 @@ class unsigned_short_converter(CConverter): type = 'unsigned short' default_type = int - format_unit = 'H' c_ignored_default = "0" def converter_init(self, *, bitwise=False): - if not bitwise: - fail("Unsigned shorts must be bitwise (for now).") + if bitwise: + self.format_unit = 'H' + else: + self.converter = '_Py_UnsignedShort_Converter' @add_legacy_c_converter('C', types='str') class int_converter(CConverter): @@ -1704,12 +1705,13 @@ class unsigned_int_converter(CConverter): type = 'unsigned int' default_type = int - format_unit = 'I' c_ignored_default = "0" def converter_init(self, *, bitwise=False): - if not bitwise: - fail("Unsigned ints must be bitwise (for now).") + if bitwise: + self.format_unit = 'I' + else: + self.converter = '_Py_UnsignedInt_Converter' class long_converter(CConverter): type = 'long' @@ -1720,12 +1722,13 @@ class unsigned_long_converter(CConverter): type = 'unsigned long' default_type = int - format_unit = 'k' c_ignored_default = "0" def converter_init(self, *, bitwise=False): - if not bitwise: - fail("Unsigned longs must be bitwise (for now).") + if bitwise: + self.format_unit = 'k' + else: + self.converter = '_Py_UnsignedLong_Converter' class PY_LONG_LONG_converter(CConverter): type = 'PY_LONG_LONG' @@ -1736,12 +1739,13 @@ class unsigned_PY_LONG_LONG_converter(CConverter): type = 'unsigned PY_LONG_LONG' default_type = int - format_unit = 'K' c_ignored_default = "0" def converter_init(self, *, bitwise=False): - if not bitwise: - fail("Unsigned PY_LONG_LONGs must be bitwise (for now).") + if bitwise: + self.format_unit = 'K' + else: + self.converter = '_Py_UnsignedLongLong_Converter' class Py_ssize_t_converter(CConverter): type = 'Py_ssize_t' @@ -1749,6 +1753,11 @@ format_unit = 'n' c_ignored_default = "0" +class size_t_converter(CConverter): + type = 'size_t' + converter = '_Py_Size_t_Converter' + c_ignored_default = "0" + class float_converter(CConverter): type = 'float'