--- /dev/null
+A. HISTORY OF THE SOFTWARE\r
+==========================\r
+\r
+Python was created in the early 1990s by Guido van Rossum at Stichting\r
+Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands\r
+as a successor of a language called ABC. Guido remains Python's\r
+principal author, although it includes many contributions from others.\r
+\r
+In 1995, Guido continued his work on Python at the Corporation for\r
+National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)\r
+in Reston, Virginia where he released several versions of the\r
+software.\r
+\r
+In May 2000, Guido and the Python core development team moved to\r
+BeOpen.com to form the BeOpen PythonLabs team. In October of the same\r
+year, the PythonLabs team moved to Digital Creations (now Zope\r
+Corporation, see http://www.zope.com). In 2001, the Python Software\r
+Foundation (PSF, see http://www.python.org/psf/) was formed, a\r
+non-profit organization created specifically to own Python-related\r
+Intellectual Property. Zope Corporation is a sponsoring member of\r
+the PSF.\r
+\r
+All Python releases are Open Source (see http://www.opensource.org for\r
+the Open Source Definition). Historically, most, but not all, Python\r
+releases have also been GPL-compatible; the table below summarizes\r
+the various releases.\r
+\r
+ Release Derived Year Owner GPL-\r
+ from compatible? (1)\r
+\r
+ 0.9.0 thru 1.2 1991-1995 CWI yes\r
+ 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes\r
+ 1.6 1.5.2 2000 CNRI no\r
+ 2.0 1.6 2000 BeOpen.com no\r
+ 1.6.1 1.6 2001 CNRI yes (2)\r
+ 2.1 2.0+1.6.1 2001 PSF no\r
+ 2.0.1 2.0+1.6.1 2001 PSF yes\r
+ 2.1.1 2.1+2.0.1 2001 PSF yes\r
+ 2.1.2 2.1.1 2002 PSF yes\r
+ 2.1.3 2.1.2 2002 PSF yes\r
+ 2.2 and above 2.1.1 2001-now PSF yes\r
+\r
+Footnotes:\r
+\r
+(1) GPL-compatible doesn't mean that we're distributing Python under\r
+ the GPL. All Python licenses, unlike the GPL, let you distribute\r
+ a modified version without making your changes open source. The\r
+ GPL-compatible licenses make it possible to combine Python with\r
+ other software that is released under the GPL; the others don't.\r
+\r
+(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,\r
+ because its license has a choice of law clause. According to\r
+ CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1\r
+ is "not incompatible" with the GPL.\r
+\r
+Thanks to the many outside volunteers who have worked under Guido's\r
+direction to make these releases possible.\r
+\r
+\r
+B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON\r
+===============================================================\r
+\r
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2\r
+--------------------------------------------\r
+\r
+1. This LICENSE AGREEMENT is between the Python Software Foundation\r
+("PSF"), and the Individual or Organization ("Licensee") accessing and\r
+otherwise using this software ("Python") in source or binary form and\r
+its associated documentation.\r
+\r
+2. Subject to the terms and conditions of this License Agreement, PSF hereby\r
+grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,\r
+analyze, test, perform and/or display publicly, prepare derivative works,\r
+distribute, and otherwise use Python alone or in any derivative version,\r
+provided, however, that PSF's License Agreement and PSF's notice of copyright,\r
+i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,\r
+2011, 2012, 2013, 2014, 2015 Python Software Foundation; All Rights Reserved"\r
+are retained in Python alone or in any derivative version prepared by Licensee.\r
+\r
+3. In the event Licensee prepares a derivative work that is based on\r
+or incorporates Python or any part thereof, and wants to make\r
+the derivative work available to others as provided herein, then\r
+Licensee hereby agrees to include in any such work a brief summary of\r
+the changes made to Python.\r
+\r
+4. PSF is making Python available to Licensee on an "AS IS"\r
+basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\r
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND\r
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\r
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT\r
+INFRINGE ANY THIRD PARTY RIGHTS.\r
+\r
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON\r
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS\r
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,\r
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\r
+\r
+6. This License Agreement will automatically terminate upon a material\r
+breach of its terms and conditions.\r
+\r
+7. Nothing in this License Agreement shall be deemed to create any\r
+relationship of agency, partnership, or joint venture between PSF and\r
+Licensee. This License Agreement does not grant permission to use PSF\r
+trademarks or trade name in a trademark sense to endorse or promote\r
+products or services of Licensee, or any third party.\r
+\r
+8. By copying, installing or otherwise using Python, Licensee\r
+agrees to be bound by the terms and conditions of this License\r
+Agreement.\r
+\r
+\r
+BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0\r
+-------------------------------------------\r
+\r
+BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1\r
+\r
+1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an\r
+office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the\r
+Individual or Organization ("Licensee") accessing and otherwise using\r
+this software in source or binary form and its associated\r
+documentation ("the Software").\r
+\r
+2. Subject to the terms and conditions of this BeOpen Python License\r
+Agreement, BeOpen hereby grants Licensee a non-exclusive,\r
+royalty-free, world-wide license to reproduce, analyze, test, perform\r
+and/or display publicly, prepare derivative works, distribute, and\r
+otherwise use the Software alone or in any derivative version,\r
+provided, however, that the BeOpen Python License is retained in the\r
+Software, alone or in any derivative version prepared by Licensee.\r
+\r
+3. BeOpen is making the Software available to Licensee on an "AS IS"\r
+basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\r
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND\r
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\r
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT\r
+INFRINGE ANY THIRD PARTY RIGHTS.\r
+\r
+4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE\r
+SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS\r
+AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY\r
+DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\r
+\r
+5. This License Agreement will automatically terminate upon a material\r
+breach of its terms and conditions.\r
+\r
+6. This License Agreement shall be governed by and interpreted in all\r
+respects by the law of the State of California, excluding conflict of\r
+law provisions. Nothing in this License Agreement shall be deemed to\r
+create any relationship of agency, partnership, or joint venture\r
+between BeOpen and Licensee. This License Agreement does not grant\r
+permission to use BeOpen trademarks or trade names in a trademark\r
+sense to endorse or promote products or services of Licensee, or any\r
+third party. As an exception, the "BeOpen Python" logos available at\r
+http://www.pythonlabs.com/logos.html may be used according to the\r
+permissions granted on that web page.\r
+\r
+7. By copying, installing or otherwise using the software, Licensee\r
+agrees to be bound by the terms and conditions of this License\r
+Agreement.\r
+\r
+\r
+CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1\r
+---------------------------------------\r
+\r
+1. This LICENSE AGREEMENT is between the Corporation for National\r
+Research Initiatives, having an office at 1895 Preston White Drive,\r
+Reston, VA 20191 ("CNRI"), and the Individual or Organization\r
+("Licensee") accessing and otherwise using Python 1.6.1 software in\r
+source or binary form and its associated documentation.\r
+\r
+2. Subject to the terms and conditions of this License Agreement, CNRI\r
+hereby grants Licensee a nonexclusive, royalty-free, world-wide\r
+license to reproduce, analyze, test, perform and/or display publicly,\r
+prepare derivative works, distribute, and otherwise use Python 1.6.1\r
+alone or in any derivative version, provided, however, that CNRI's\r
+License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)\r
+1995-2001 Corporation for National Research Initiatives; All Rights\r
+Reserved" are retained in Python 1.6.1 alone or in any derivative\r
+version prepared by Licensee. Alternately, in lieu of CNRI's License\r
+Agreement, Licensee may substitute the following text (omitting the\r
+quotes): "Python 1.6.1 is made available subject to the terms and\r
+conditions in CNRI's License Agreement. This Agreement together with\r
+Python 1.6.1 may be located on the Internet using the following\r
+unique, persistent identifier (known as a handle): 1895.22/1013. This\r
+Agreement may also be obtained from a proxy server on the Internet\r
+using the following URL: http://hdl.handle.net/1895.22/1013".\r
+\r
+3. In the event Licensee prepares a derivative work that is based on\r
+or incorporates Python 1.6.1 or any part thereof, and wants to make\r
+the derivative work available to others as provided herein, then\r
+Licensee hereby agrees to include in any such work a brief summary of\r
+the changes made to Python 1.6.1.\r
+\r
+4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"\r
+basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\r
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND\r
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\r
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT\r
+INFRINGE ANY THIRD PARTY RIGHTS.\r
+\r
+5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON\r
+1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS\r
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,\r
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\r
+\r
+6. This License Agreement will automatically terminate upon a material\r
+breach of its terms and conditions.\r
+\r
+7. This License Agreement shall be governed by the federal\r
+intellectual property law of the United States, including without\r
+limitation the federal copyright law, and, to the extent such\r
+U.S. federal law does not apply, by the law of the Commonwealth of\r
+Virginia, excluding Virginia's conflict of law provisions.\r
+Notwithstanding the foregoing, with regard to derivative works based\r
+on Python 1.6.1 that incorporate non-separable material that was\r
+previously distributed under the GNU General Public License (GPL), the\r
+law of the Commonwealth of Virginia shall govern this License\r
+Agreement only as to issues arising under or with respect to\r
+Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this\r
+License Agreement shall be deemed to create any relationship of\r
+agency, partnership, or joint venture between CNRI and Licensee. This\r
+License Agreement does not grant permission to use CNRI trademarks or\r
+trade name in a trademark sense to endorse or promote products or\r
+services of Licensee, or any third party.\r
+\r
+8. By clicking on the "ACCEPT" button where indicated, or by copying,\r
+installing or otherwise using Python 1.6.1, Licensee agrees to be\r
+bound by the terms and conditions of this License Agreement.\r
+\r
+ ACCEPT\r
+\r
+\r
+CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2\r
+--------------------------------------------------\r
+\r
+Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,\r
+The Netherlands. All rights reserved.\r
+\r
+Permission to use, copy, modify, and distribute this software and its\r
+documentation for any purpose and without fee is hereby granted,\r
+provided that the above copyright notice appear in all copies and that\r
+both that copyright notice and this permission notice appear in\r
+supporting documentation, and that the name of Stichting Mathematisch\r
+Centrum or CWI not be used in advertising or publicity pertaining to\r
+distribution of the software without specific, written prior\r
+permission.\r
+\r
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO\r
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE\r
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT\r
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
--- /dev/null
+/* Abstract Object Interface (many thanks to Jim Fulton) */\r
+\r
+#include "Python.h"\r
+#include <ctype.h>\r
+#include "structmember.h" /* we need the offsetof() macro from there */\r
+#include "longintrepr.h"\r
+\r
+#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \\r
+ Py_TPFLAGS_CHECKTYPES)\r
+\r
+\r
+/* Shorthands to return certain errors */\r
+\r
+static PyObject *\r
+type_error(const char *msg, PyObject *obj)\r
+{\r
+ PyErr_Format(PyExc_TypeError, msg, obj->ob_type->tp_name);\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+null_error(void)\r
+{\r
+ if (!PyErr_Occurred())\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "null argument to internal routine");\r
+ return NULL;\r
+}\r
+\r
+/* Operations on any object */\r
+\r
+int\r
+PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)\r
+{\r
+ int r;\r
+\r
+ if (o1 == NULL || o2 == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+ r = PyObject_Compare(o1, o2);\r
+ if (PyErr_Occurred())\r
+ return -1;\r
+ *result = r;\r
+ return 0;\r
+}\r
+\r
+PyObject *\r
+PyObject_Type(PyObject *o)\r
+{\r
+ PyObject *v;\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+ v = (PyObject *)o->ob_type;\r
+ Py_INCREF(v);\r
+ return v;\r
+}\r
+\r
+Py_ssize_t\r
+PyObject_Size(PyObject *o)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (o == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+\r
+ m = o->ob_type->tp_as_sequence;\r
+ if (m && m->sq_length)\r
+ return m->sq_length(o);\r
+\r
+ return PyMapping_Size(o);\r
+}\r
+\r
+#undef PyObject_Length\r
+Py_ssize_t\r
+PyObject_Length(PyObject *o)\r
+{\r
+ return PyObject_Size(o);\r
+}\r
+#define PyObject_Length PyObject_Size\r
+\r
+\r
+/* The length hint function returns a non-negative value from o.__len__()\r
+ or o.__length_hint__(). If those methods aren't found or return a negative\r
+ value, then the defaultvalue is returned. If one of the calls fails,\r
+ this function returns -1.\r
+*/\r
+\r
+Py_ssize_t\r
+_PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue)\r
+{\r
+ static PyObject *hintstrobj = NULL;\r
+ PyObject *ro, *hintmeth;\r
+ Py_ssize_t rv;\r
+\r
+ /* try o.__len__() */\r
+ rv = PyObject_Size(o);\r
+ if (rv >= 0)\r
+ return rv;\r
+ if (PyErr_Occurred()) {\r
+ if (!PyErr_ExceptionMatches(PyExc_TypeError) &&\r
+ !PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ }\r
+\r
+ if (PyInstance_Check(o))\r
+ return defaultvalue;\r
+ /* try o.__length_hint__() */\r
+ hintmeth = _PyObject_LookupSpecial(o, "__length_hint__", &hintstrobj);\r
+ if (hintmeth == NULL) {\r
+ if (PyErr_Occurred())\r
+ return -1;\r
+ else\r
+ return defaultvalue;\r
+ }\r
+ ro = PyObject_CallFunctionObjArgs(hintmeth, NULL);\r
+ Py_DECREF(hintmeth);\r
+ if (ro == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_TypeError) &&\r
+ !PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ return defaultvalue;\r
+ }\r
+ rv = PyNumber_Check(ro) ? PyInt_AsSsize_t(ro) : defaultvalue;\r
+ Py_DECREF(ro);\r
+ return rv;\r
+}\r
+\r
+PyObject *\r
+PyObject_GetItem(PyObject *o, PyObject *key)\r
+{\r
+ PyMappingMethods *m;\r
+\r
+ if (o == NULL || key == NULL)\r
+ return null_error();\r
+\r
+ m = o->ob_type->tp_as_mapping;\r
+ if (m && m->mp_subscript)\r
+ return m->mp_subscript(o, key);\r
+\r
+ if (o->ob_type->tp_as_sequence) {\r
+ if (PyIndex_Check(key)) {\r
+ Py_ssize_t key_value;\r
+ key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);\r
+ if (key_value == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ return PySequence_GetItem(o, key_value);\r
+ }\r
+ else if (o->ob_type->tp_as_sequence->sq_item)\r
+ return type_error("sequence index must "\r
+ "be integer, not '%.200s'", key);\r
+ }\r
+\r
+ return type_error("'%.200s' object has no attribute '__getitem__'", o);\r
+}\r
+\r
+int\r
+PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)\r
+{\r
+ PyMappingMethods *m;\r
+\r
+ if (o == NULL || key == NULL || value == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+ m = o->ob_type->tp_as_mapping;\r
+ if (m && m->mp_ass_subscript)\r
+ return m->mp_ass_subscript(o, key, value);\r
+\r
+ if (o->ob_type->tp_as_sequence) {\r
+ if (PyIndex_Check(key)) {\r
+ Py_ssize_t key_value;\r
+ key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);\r
+ if (key_value == -1 && PyErr_Occurred())\r
+ return -1;\r
+ return PySequence_SetItem(o, key_value, value);\r
+ }\r
+ else if (o->ob_type->tp_as_sequence->sq_ass_item) {\r
+ type_error("sequence index must be "\r
+ "integer, not '%.200s'", key);\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ type_error("'%.200s' object does not support item assignment", o);\r
+ return -1;\r
+}\r
+\r
+int\r
+PyObject_DelItem(PyObject *o, PyObject *key)\r
+{\r
+ PyMappingMethods *m;\r
+\r
+ if (o == NULL || key == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+ m = o->ob_type->tp_as_mapping;\r
+ if (m && m->mp_ass_subscript)\r
+ return m->mp_ass_subscript(o, key, (PyObject*)NULL);\r
+\r
+ if (o->ob_type->tp_as_sequence) {\r
+ if (PyIndex_Check(key)) {\r
+ Py_ssize_t key_value;\r
+ key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);\r
+ if (key_value == -1 && PyErr_Occurred())\r
+ return -1;\r
+ return PySequence_DelItem(o, key_value);\r
+ }\r
+ else if (o->ob_type->tp_as_sequence->sq_ass_item) {\r
+ type_error("sequence index must be "\r
+ "integer, not '%.200s'", key);\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ type_error("'%.200s' object does not support item deletion", o);\r
+ return -1;\r
+}\r
+\r
+int\r
+PyObject_DelItemString(PyObject *o, char *key)\r
+{\r
+ PyObject *okey;\r
+ int ret;\r
+\r
+ if (o == NULL || key == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+ okey = PyString_FromString(key);\r
+ if (okey == NULL)\r
+ return -1;\r
+ ret = PyObject_DelItem(o, okey);\r
+ Py_DECREF(okey);\r
+ return ret;\r
+}\r
+\r
+int\r
+PyObject_AsCharBuffer(PyObject *obj,\r
+ const char **buffer,\r
+ Py_ssize_t *buffer_len)\r
+{\r
+ PyBufferProcs *pb;\r
+ char *pp;\r
+ Py_ssize_t len;\r
+\r
+ if (obj == NULL || buffer == NULL || buffer_len == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+ pb = obj->ob_type->tp_as_buffer;\r
+ if (pb == NULL ||\r
+ pb->bf_getcharbuffer == NULL ||\r
+ pb->bf_getsegcount == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected a character buffer object");\r
+ return -1;\r
+ }\r
+ if ((*pb->bf_getsegcount)(obj,NULL) != 1) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected a single-segment buffer object");\r
+ return -1;\r
+ }\r
+ len = (*pb->bf_getcharbuffer)(obj, 0, &pp);\r
+ if (len < 0)\r
+ return -1;\r
+ *buffer = pp;\r
+ *buffer_len = len;\r
+ return 0;\r
+}\r
+\r
+int\r
+PyObject_CheckReadBuffer(PyObject *obj)\r
+{\r
+ PyBufferProcs *pb = obj->ob_type->tp_as_buffer;\r
+\r
+ if (pb == NULL ||\r
+ pb->bf_getreadbuffer == NULL ||\r
+ pb->bf_getsegcount == NULL ||\r
+ (*pb->bf_getsegcount)(obj, NULL) != 1)\r
+ return 0;\r
+ return 1;\r
+}\r
+\r
+int PyObject_AsReadBuffer(PyObject *obj,\r
+ const void **buffer,\r
+ Py_ssize_t *buffer_len)\r
+{\r
+ PyBufferProcs *pb;\r
+ void *pp;\r
+ Py_ssize_t len;\r
+\r
+ if (obj == NULL || buffer == NULL || buffer_len == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+ pb = obj->ob_type->tp_as_buffer;\r
+ if (pb == NULL ||\r
+ pb->bf_getreadbuffer == NULL ||\r
+ pb->bf_getsegcount == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected a readable buffer object");\r
+ return -1;\r
+ }\r
+ if ((*pb->bf_getsegcount)(obj, NULL) != 1) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected a single-segment buffer object");\r
+ return -1;\r
+ }\r
+ len = (*pb->bf_getreadbuffer)(obj, 0, &pp);\r
+ if (len < 0)\r
+ return -1;\r
+ *buffer = pp;\r
+ *buffer_len = len;\r
+ return 0;\r
+}\r
+\r
+int PyObject_AsWriteBuffer(PyObject *obj,\r
+ void **buffer,\r
+ Py_ssize_t *buffer_len)\r
+{\r
+ PyBufferProcs *pb;\r
+ void*pp;\r
+ Py_ssize_t len;\r
+\r
+ if (obj == NULL || buffer == NULL || buffer_len == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+ pb = obj->ob_type->tp_as_buffer;\r
+ if (pb == NULL ||\r
+ pb->bf_getwritebuffer == NULL ||\r
+ pb->bf_getsegcount == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected a writeable buffer object");\r
+ return -1;\r
+ }\r
+ if ((*pb->bf_getsegcount)(obj, NULL) != 1) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected a single-segment buffer object");\r
+ return -1;\r
+ }\r
+ len = (*pb->bf_getwritebuffer)(obj,0,&pp);\r
+ if (len < 0)\r
+ return -1;\r
+ *buffer = pp;\r
+ *buffer_len = len;\r
+ return 0;\r
+}\r
+\r
+/* Buffer C-API for Python 3.0 */\r
+\r
+int\r
+PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)\r
+{\r
+ if (!PyObject_CheckBuffer(obj)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "'%100s' does not have the buffer interface",\r
+ Py_TYPE(obj)->tp_name);\r
+ return -1;\r
+ }\r
+ return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);\r
+}\r
+\r
+static int\r
+_IsFortranContiguous(Py_buffer *view)\r
+{\r
+ Py_ssize_t sd, dim;\r
+ int i;\r
+\r
+ if (view->ndim == 0) return 1;\r
+ if (view->strides == NULL) return (view->ndim == 1);\r
+\r
+ sd = view->itemsize;\r
+ if (view->ndim == 1) return (view->shape[0] == 1 ||\r
+ sd == view->strides[0]);\r
+ for (i=0; i<view->ndim; i++) {\r
+ dim = view->shape[i];\r
+ if (dim == 0) return 1;\r
+ if (view->strides[i] != sd) return 0;\r
+ sd *= dim;\r
+ }\r
+ return 1;\r
+}\r
+\r
+static int\r
+_IsCContiguous(Py_buffer *view)\r
+{\r
+ Py_ssize_t sd, dim;\r
+ int i;\r
+\r
+ if (view->ndim == 0) return 1;\r
+ if (view->strides == NULL) return 1;\r
+\r
+ sd = view->itemsize;\r
+ if (view->ndim == 1) return (view->shape[0] == 1 ||\r
+ sd == view->strides[0]);\r
+ for (i=view->ndim-1; i>=0; i--) {\r
+ dim = view->shape[i];\r
+ if (dim == 0) return 1;\r
+ if (view->strides[i] != sd) return 0;\r
+ sd *= dim;\r
+ }\r
+ return 1;\r
+}\r
+\r
+int\r
+PyBuffer_IsContiguous(Py_buffer *view, char fort)\r
+{\r
+\r
+ if (view->suboffsets != NULL) return 0;\r
+\r
+ if (fort == 'C')\r
+ return _IsCContiguous(view);\r
+ else if (fort == 'F')\r
+ return _IsFortranContiguous(view);\r
+ else if (fort == 'A')\r
+ return (_IsCContiguous(view) || _IsFortranContiguous(view));\r
+ return 0;\r
+}\r
+\r
+\r
+void*\r
+PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices)\r
+{\r
+ char* pointer;\r
+ int i;\r
+ pointer = (char *)view->buf;\r
+ for (i = 0; i < view->ndim; i++) {\r
+ pointer += view->strides[i]*indices[i];\r
+ if ((view->suboffsets != NULL) && (view->suboffsets[i] >= 0)) {\r
+ pointer = *((char**)pointer) + view->suboffsets[i];\r
+ }\r
+ }\r
+ return (void*)pointer;\r
+}\r
+\r
+\r
+void\r
+_Py_add_one_to_index_F(int nd, Py_ssize_t *index, const Py_ssize_t *shape)\r
+{\r
+ int k;\r
+\r
+ for (k=0; k<nd; k++) {\r
+ if (index[k] < shape[k]-1) {\r
+ index[k]++;\r
+ break;\r
+ }\r
+ else {\r
+ index[k] = 0;\r
+ }\r
+ }\r
+}\r
+\r
+void\r
+_Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape)\r
+{\r
+ int k;\r
+\r
+ for (k=nd-1; k>=0; k--) {\r
+ if (index[k] < shape[k]-1) {\r
+ index[k]++;\r
+ break;\r
+ }\r
+ else {\r
+ index[k] = 0;\r
+ }\r
+ }\r
+}\r
+\r
+ /* view is not checked for consistency in either of these. It is\r
+ assumed that the size of the buffer is view->len in\r
+ view->len / view->itemsize elements.\r
+ */\r
+\r
+int\r
+PyBuffer_ToContiguous(void *buf, Py_buffer *view, Py_ssize_t len, char fort)\r
+{\r
+ int k;\r
+ void (*addone)(int, Py_ssize_t *, const Py_ssize_t *);\r
+ Py_ssize_t *indices, elements;\r
+ char *dest, *ptr;\r
+\r
+ if (len > view->len) {\r
+ len = view->len;\r
+ }\r
+\r
+ if (PyBuffer_IsContiguous(view, fort)) {\r
+ /* simplest copy is all that is needed */\r
+ memcpy(buf, view->buf, len);\r
+ return 0;\r
+ }\r
+\r
+ /* Otherwise a more elaborate scheme is needed */\r
+\r
+ /* view->ndim <= 64 */\r
+ indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*(view->ndim));\r
+ if (indices == NULL) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ for (k=0; k<view->ndim;k++) {\r
+ indices[k] = 0;\r
+ }\r
+\r
+ if (fort == 'F') {\r
+ addone = _Py_add_one_to_index_F;\r
+ }\r
+ else {\r
+ addone = _Py_add_one_to_index_C;\r
+ }\r
+ dest = buf;\r
+ /* XXX : This is not going to be the fastest code in the world\r
+ several optimizations are possible.\r
+ */\r
+ elements = len / view->itemsize;\r
+ while (elements--) {\r
+ ptr = PyBuffer_GetPointer(view, indices);\r
+ memcpy(dest, ptr, view->itemsize);\r
+ dest += view->itemsize;\r
+ addone(view->ndim, indices, view->shape);\r
+ }\r
+ PyMem_Free(indices);\r
+ return 0;\r
+}\r
+\r
+int\r
+PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort)\r
+{\r
+ int k;\r
+ void (*addone)(int, Py_ssize_t *, const Py_ssize_t *);\r
+ Py_ssize_t *indices, elements;\r
+ char *src, *ptr;\r
+\r
+ if (len > view->len) {\r
+ len = view->len;\r
+ }\r
+\r
+ if (PyBuffer_IsContiguous(view, fort)) {\r
+ /* simplest copy is all that is needed */\r
+ memcpy(view->buf, buf, len);\r
+ return 0;\r
+ }\r
+\r
+ /* Otherwise a more elaborate scheme is needed */\r
+\r
+ /* view->ndim <= 64 */\r
+ indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*(view->ndim));\r
+ if (indices == NULL) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ for (k=0; k<view->ndim;k++) {\r
+ indices[k] = 0;\r
+ }\r
+\r
+ if (fort == 'F') {\r
+ addone = _Py_add_one_to_index_F;\r
+ }\r
+ else {\r
+ addone = _Py_add_one_to_index_C;\r
+ }\r
+ src = buf;\r
+ /* XXX : This is not going to be the fastest code in the world\r
+ several optimizations are possible.\r
+ */\r
+ elements = len / view->itemsize;\r
+ while (elements--) {\r
+ ptr = PyBuffer_GetPointer(view, indices);\r
+ memcpy(ptr, src, view->itemsize);\r
+ src += view->itemsize;\r
+ addone(view->ndim, indices, view->shape);\r
+ }\r
+\r
+ PyMem_Free(indices);\r
+ return 0;\r
+}\r
+\r
+int PyObject_CopyData(PyObject *dest, PyObject *src)\r
+{\r
+ Py_buffer view_dest, view_src;\r
+ int k;\r
+ Py_ssize_t *indices, elements;\r
+ char *dptr, *sptr;\r
+\r
+ if (!PyObject_CheckBuffer(dest) ||\r
+ !PyObject_CheckBuffer(src)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "both destination and source must have the "\\r
+ "buffer interface");\r
+ return -1;\r
+ }\r
+\r
+ if (PyObject_GetBuffer(dest, &view_dest, PyBUF_FULL) != 0) return -1;\r
+ if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) {\r
+ PyBuffer_Release(&view_dest);\r
+ return -1;\r
+ }\r
+\r
+ if (view_dest.len < view_src.len) {\r
+ PyErr_SetString(PyExc_BufferError,\r
+ "destination is too small to receive data from source");\r
+ PyBuffer_Release(&view_dest);\r
+ PyBuffer_Release(&view_src);\r
+ return -1;\r
+ }\r
+\r
+ if ((PyBuffer_IsContiguous(&view_dest, 'C') &&\r
+ PyBuffer_IsContiguous(&view_src, 'C')) ||\r
+ (PyBuffer_IsContiguous(&view_dest, 'F') &&\r
+ PyBuffer_IsContiguous(&view_src, 'F'))) {\r
+ /* simplest copy is all that is needed */\r
+ memcpy(view_dest.buf, view_src.buf, view_src.len);\r
+ PyBuffer_Release(&view_dest);\r
+ PyBuffer_Release(&view_src);\r
+ return 0;\r
+ }\r
+\r
+ /* Otherwise a more elaborate copy scheme is needed */\r
+\r
+ /* XXX(nnorwitz): need to check for overflow! */\r
+ indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim);\r
+ if (indices == NULL) {\r
+ PyErr_NoMemory();\r
+ PyBuffer_Release(&view_dest);\r
+ PyBuffer_Release(&view_src);\r
+ return -1;\r
+ }\r
+ for (k=0; k<view_src.ndim;k++) {\r
+ indices[k] = 0;\r
+ }\r
+ elements = 1;\r
+ for (k=0; k<view_src.ndim; k++) {\r
+ /* XXX(nnorwitz): can this overflow? */\r
+ elements *= view_src.shape[k];\r
+ }\r
+ while (elements--) {\r
+ _Py_add_one_to_index_C(view_src.ndim, indices, view_src.shape);\r
+ dptr = PyBuffer_GetPointer(&view_dest, indices);\r
+ sptr = PyBuffer_GetPointer(&view_src, indices);\r
+ memcpy(dptr, sptr, view_src.itemsize);\r
+ }\r
+ PyMem_Free(indices);\r
+ PyBuffer_Release(&view_dest);\r
+ PyBuffer_Release(&view_src);\r
+ return 0;\r
+}\r
+\r
+void\r
+PyBuffer_FillContiguousStrides(int nd, Py_ssize_t *shape,\r
+ Py_ssize_t *strides, int itemsize,\r
+ char fort)\r
+{\r
+ int k;\r
+ Py_ssize_t sd;\r
+\r
+ sd = itemsize;\r
+ if (fort == 'F') {\r
+ for (k=0; k<nd; k++) {\r
+ strides[k] = sd;\r
+ sd *= shape[k];\r
+ }\r
+ }\r
+ else {\r
+ for (k=nd-1; k>=0; k--) {\r
+ strides[k] = sd;\r
+ sd *= shape[k];\r
+ }\r
+ }\r
+ return;\r
+}\r
+\r
+int\r
+PyBuffer_FillInfo(Py_buffer *view, PyObject *obj, void *buf, Py_ssize_t len,\r
+ int readonly, int flags)\r
+{\r
+ if (view == NULL) return 0;\r
+ if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) &&\r
+ (readonly == 1)) {\r
+ PyErr_SetString(PyExc_BufferError,\r
+ "Object is not writable.");\r
+ return -1;\r
+ }\r
+\r
+ view->obj = obj;\r
+ if (obj)\r
+ Py_INCREF(obj);\r
+ view->buf = buf;\r
+ view->len = len;\r
+ view->readonly = readonly;\r
+ view->itemsize = 1;\r
+ view->format = NULL;\r
+ if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)\r
+ view->format = "B";\r
+ view->ndim = 1;\r
+ view->shape = NULL;\r
+ if ((flags & PyBUF_ND) == PyBUF_ND)\r
+ view->shape = &(view->len);\r
+ view->strides = NULL;\r
+ if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES)\r
+ view->strides = &(view->itemsize);\r
+ view->suboffsets = NULL;\r
+ view->internal = NULL;\r
+ return 0;\r
+}\r
+\r
+void\r
+PyBuffer_Release(Py_buffer *view)\r
+{\r
+ PyObject *obj = view->obj;\r
+ if (obj && Py_TYPE(obj)->tp_as_buffer && Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer)\r
+ Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view);\r
+ Py_XDECREF(obj);\r
+ view->obj = NULL;\r
+}\r
+\r
+PyObject *\r
+PyObject_Format(PyObject* obj, PyObject *format_spec)\r
+{\r
+ PyObject *empty = NULL;\r
+ PyObject *result = NULL;\r
+#ifdef Py_USING_UNICODE\r
+ int spec_is_unicode;\r
+ int result_is_unicode;\r
+#endif\r
+\r
+ /* If no format_spec is provided, use an empty string */\r
+ if (format_spec == NULL) {\r
+ empty = PyString_FromStringAndSize(NULL, 0);\r
+ format_spec = empty;\r
+ }\r
+\r
+ /* Check the format_spec type, and make sure it's str or unicode */\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(format_spec))\r
+ spec_is_unicode = 1;\r
+ else if (PyString_Check(format_spec))\r
+ spec_is_unicode = 0;\r
+ else {\r
+#else\r
+ if (!PyString_Check(format_spec)) {\r
+#endif\r
+ PyErr_Format(PyExc_TypeError,\r
+ "format expects arg 2 to be string "\r
+ "or unicode, not %.100s", Py_TYPE(format_spec)->tp_name);\r
+ goto done;\r
+ }\r
+\r
+ /* Check for a __format__ method and call it. */\r
+ if (PyInstance_Check(obj)) {\r
+ /* We're an instance of a classic class */\r
+ PyObject *bound_method = PyObject_GetAttrString(obj, "__format__");\r
+ if (bound_method != NULL) {\r
+ result = PyObject_CallFunctionObjArgs(bound_method,\r
+ format_spec,\r
+ NULL);\r
+ Py_DECREF(bound_method);\r
+ } else {\r
+ PyObject *self_as_str = NULL;\r
+ PyObject *format_method = NULL;\r
+ Py_ssize_t format_len;\r
+\r
+ PyErr_Clear();\r
+ /* Per the PEP, convert to str (or unicode,\r
+ depending on the type of the format\r
+ specifier). For new-style classes, this\r
+ logic is done by object.__format__(). */\r
+#ifdef Py_USING_UNICODE\r
+ if (spec_is_unicode) {\r
+ format_len = PyUnicode_GET_SIZE(format_spec);\r
+ self_as_str = PyObject_Unicode(obj);\r
+ } else\r
+#endif\r
+ {\r
+ format_len = PyString_GET_SIZE(format_spec);\r
+ self_as_str = PyObject_Str(obj);\r
+ }\r
+ if (self_as_str == NULL)\r
+ goto done1;\r
+\r
+ if (format_len > 0) {\r
+ /* See the almost identical code in\r
+ typeobject.c for new-style\r
+ classes. */\r
+ if (PyErr_WarnEx(\r
+ PyExc_PendingDeprecationWarning,\r
+ "object.__format__ with a non-empty "\r
+ "format string is deprecated", 1)\r
+ < 0) {\r
+ goto done1;\r
+ }\r
+ /* Eventually this will become an\r
+ error:\r
+ PyErr_Format(PyExc_TypeError,\r
+ "non-empty format string passed to "\r
+ "object.__format__");\r
+ goto done1;\r
+ */\r
+ }\r
+\r
+ /* Then call str.__format__ on that result */\r
+ format_method = PyObject_GetAttrString(self_as_str, "__format__");\r
+ if (format_method == NULL) {\r
+ goto done1;\r
+ }\r
+ result = PyObject_CallFunctionObjArgs(format_method,\r
+ format_spec,\r
+ NULL);\r
+done1:\r
+ Py_XDECREF(self_as_str);\r
+ Py_XDECREF(format_method);\r
+ if (result == NULL)\r
+ goto done;\r
+ }\r
+ } else {\r
+ /* Not an instance of a classic class, use the code\r
+ from py3k */\r
+ static PyObject *format_cache = NULL;\r
+\r
+ /* Find the (unbound!) __format__ method (a borrowed\r
+ reference) */\r
+ PyObject *method = _PyObject_LookupSpecial(obj, "__format__",\r
+ &format_cache);\r
+ if (method == NULL) {\r
+ if (!PyErr_Occurred())\r
+ PyErr_Format(PyExc_TypeError,\r
+ "Type %.100s doesn't define __format__",\r
+ Py_TYPE(obj)->tp_name);\r
+ goto done;\r
+ }\r
+ /* And call it. */\r
+ result = PyObject_CallFunctionObjArgs(method, format_spec, NULL);\r
+ Py_DECREF(method);\r
+ }\r
+\r
+ if (result == NULL)\r
+ goto done;\r
+\r
+ /* Check the result type, and make sure it's str or unicode */\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(result))\r
+ result_is_unicode = 1;\r
+ else if (PyString_Check(result))\r
+ result_is_unicode = 0;\r
+ else {\r
+#else\r
+ if (!PyString_Check(result)) {\r
+#endif\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%.100s.__format__ must return string or "\r
+ "unicode, not %.100s", Py_TYPE(obj)->tp_name,\r
+ Py_TYPE(result)->tp_name);\r
+ Py_DECREF(result);\r
+ result = NULL;\r
+ goto done;\r
+ }\r
+\r
+ /* Convert to unicode, if needed. Required if spec is unicode\r
+ and result is str */\r
+#ifdef Py_USING_UNICODE\r
+ if (spec_is_unicode && !result_is_unicode) {\r
+ PyObject *tmp = PyObject_Unicode(result);\r
+ /* This logic works whether or not tmp is NULL */\r
+ Py_DECREF(result);\r
+ result = tmp;\r
+ }\r
+#endif\r
+\r
+done:\r
+ Py_XDECREF(empty);\r
+ return result;\r
+}\r
+\r
+/* Operations on numbers */\r
+\r
+int\r
+PyNumber_Check(PyObject *o)\r
+{\r
+ return o && o->ob_type->tp_as_number &&\r
+ (o->ob_type->tp_as_number->nb_int ||\r
+ o->ob_type->tp_as_number->nb_float);\r
+}\r
+\r
+/* Binary operators */\r
+\r
+/* New style number protocol support */\r
+\r
+#define NB_SLOT(x) offsetof(PyNumberMethods, x)\r
+#define NB_BINOP(nb_methods, slot) \\r
+ (*(binaryfunc*)(& ((char*)nb_methods)[slot]))\r
+#define NB_TERNOP(nb_methods, slot) \\r
+ (*(ternaryfunc*)(& ((char*)nb_methods)[slot]))\r
+\r
+/*\r
+ Calling scheme used for binary operations:\r
+\r
+ v w Action\r
+ -------------------------------------------------------------------\r
+ new new w.op(v,w)[*], v.op(v,w), w.op(v,w)\r
+ new old v.op(v,w), coerce(v,w), v.op(v,w)\r
+ old new w.op(v,w), coerce(v,w), v.op(v,w)\r
+ old old coerce(v,w), v.op(v,w)\r
+\r
+ [*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of\r
+ v->ob_type\r
+\r
+ Legend:\r
+ -------\r
+ * new == new style number\r
+ * old == old style number\r
+ * Action indicates the order in which operations are tried until either\r
+ a valid result is produced or an error occurs.\r
+\r
+ */\r
+\r
+static PyObject *\r
+binary_op1(PyObject *v, PyObject *w, const int op_slot)\r
+{\r
+ PyObject *x;\r
+ binaryfunc slotv = NULL;\r
+ binaryfunc slotw = NULL;\r
+\r
+ if (v->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(v))\r
+ slotv = NB_BINOP(v->ob_type->tp_as_number, op_slot);\r
+ if (w->ob_type != v->ob_type &&\r
+ w->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(w)) {\r
+ slotw = NB_BINOP(w->ob_type->tp_as_number, op_slot);\r
+ if (slotw == slotv)\r
+ slotw = NULL;\r
+ }\r
+ if (slotv) {\r
+ if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {\r
+ x = slotw(v, w);\r
+ if (x != Py_NotImplemented)\r
+ return x;\r
+ Py_DECREF(x); /* can't do it */\r
+ slotw = NULL;\r
+ }\r
+ x = slotv(v, w);\r
+ if (x != Py_NotImplemented)\r
+ return x;\r
+ Py_DECREF(x); /* can't do it */\r
+ }\r
+ if (slotw) {\r
+ x = slotw(v, w);\r
+ if (x != Py_NotImplemented)\r
+ return x;\r
+ Py_DECREF(x); /* can't do it */\r
+ }\r
+ if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w)) {\r
+ int err = PyNumber_CoerceEx(&v, &w);\r
+ if (err < 0) {\r
+ return NULL;\r
+ }\r
+ if (err == 0) {\r
+ PyNumberMethods *mv = v->ob_type->tp_as_number;\r
+ if (mv) {\r
+ binaryfunc slot;\r
+ slot = NB_BINOP(mv, op_slot);\r
+ if (slot) {\r
+ x = slot(v, w);\r
+ Py_DECREF(v);\r
+ Py_DECREF(w);\r
+ return x;\r
+ }\r
+ }\r
+ /* CoerceEx incremented the reference counts */\r
+ Py_DECREF(v);\r
+ Py_DECREF(w);\r
+ }\r
+ }\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+}\r
+\r
+static PyObject *\r
+binop_type_error(PyObject *v, PyObject *w, const char *op_name)\r
+{\r
+ PyErr_Format(PyExc_TypeError,\r
+ "unsupported operand type(s) for %.100s: "\r
+ "'%.100s' and '%.100s'",\r
+ op_name,\r
+ v->ob_type->tp_name,\r
+ w->ob_type->tp_name);\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)\r
+{\r
+ PyObject *result = binary_op1(v, w, op_slot);\r
+ if (result == Py_NotImplemented) {\r
+ Py_DECREF(result);\r
+ return binop_type_error(v, w, op_name);\r
+ }\r
+ return result;\r
+}\r
+\r
+\r
+/*\r
+ Calling scheme used for ternary operations:\r
+\r
+ *** In some cases, w.op is called before v.op; see binary_op1. ***\r
+\r
+ v w z Action\r
+ -------------------------------------------------------------------\r
+ new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)\r
+ new old new v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)\r
+ old new new w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)\r
+ old old new z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)\r
+ new new old v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)\r
+ new old old v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)\r
+ old new old w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)\r
+ old old old coerce(v,w,z), v.op(v,w,z)\r
+\r
+ Legend:\r
+ -------\r
+ * new == new style number\r
+ * old == old style number\r
+ * Action indicates the order in which operations are tried until either\r
+ a valid result is produced or an error occurs.\r
+ * coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and\r
+ only if z != Py_None; if z == Py_None, then it is treated as absent\r
+ variable and only coerce(v,w) is tried.\r
+\r
+ */\r
+\r
+static PyObject *\r
+ternary_op(PyObject *v,\r
+ PyObject *w,\r
+ PyObject *z,\r
+ const int op_slot,\r
+ const char *op_name)\r
+{\r
+ PyNumberMethods *mv, *mw, *mz;\r
+ PyObject *x = NULL;\r
+ ternaryfunc slotv = NULL;\r
+ ternaryfunc slotw = NULL;\r
+ ternaryfunc slotz = NULL;\r
+\r
+ mv = v->ob_type->tp_as_number;\r
+ mw = w->ob_type->tp_as_number;\r
+ if (mv != NULL && NEW_STYLE_NUMBER(v))\r
+ slotv = NB_TERNOP(mv, op_slot);\r
+ if (w->ob_type != v->ob_type &&\r
+ mw != NULL && NEW_STYLE_NUMBER(w)) {\r
+ slotw = NB_TERNOP(mw, op_slot);\r
+ if (slotw == slotv)\r
+ slotw = NULL;\r
+ }\r
+ if (slotv) {\r
+ if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {\r
+ x = slotw(v, w, z);\r
+ if (x != Py_NotImplemented)\r
+ return x;\r
+ Py_DECREF(x); /* can't do it */\r
+ slotw = NULL;\r
+ }\r
+ x = slotv(v, w, z);\r
+ if (x != Py_NotImplemented)\r
+ return x;\r
+ Py_DECREF(x); /* can't do it */\r
+ }\r
+ if (slotw) {\r
+ x = slotw(v, w, z);\r
+ if (x != Py_NotImplemented)\r
+ return x;\r
+ Py_DECREF(x); /* can't do it */\r
+ }\r
+ mz = z->ob_type->tp_as_number;\r
+ if (mz != NULL && NEW_STYLE_NUMBER(z)) {\r
+ slotz = NB_TERNOP(mz, op_slot);\r
+ if (slotz == slotv || slotz == slotw)\r
+ slotz = NULL;\r
+ if (slotz) {\r
+ x = slotz(v, w, z);\r
+ if (x != Py_NotImplemented)\r
+ return x;\r
+ Py_DECREF(x); /* can't do it */\r
+ }\r
+ }\r
+\r
+ if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w) ||\r
+ (z != Py_None && !NEW_STYLE_NUMBER(z))) {\r
+ /* we have an old style operand, coerce */\r
+ PyObject *v1, *z1, *w2, *z2;\r
+ int c;\r
+\r
+ c = PyNumber_Coerce(&v, &w);\r
+ if (c != 0)\r
+ goto error3;\r
+\r
+ /* Special case: if the third argument is None, it is\r
+ treated as absent argument and not coerced. */\r
+ if (z == Py_None) {\r
+ if (v->ob_type->tp_as_number) {\r
+ slotz = NB_TERNOP(v->ob_type->tp_as_number,\r
+ op_slot);\r
+ if (slotz)\r
+ x = slotz(v, w, z);\r
+ else\r
+ c = -1;\r
+ }\r
+ else\r
+ c = -1;\r
+ goto error2;\r
+ }\r
+ v1 = v;\r
+ z1 = z;\r
+ c = PyNumber_Coerce(&v1, &z1);\r
+ if (c != 0)\r
+ goto error2;\r
+ w2 = w;\r
+ z2 = z1;\r
+ c = PyNumber_Coerce(&w2, &z2);\r
+ if (c != 0)\r
+ goto error1;\r
+\r
+ if (v1->ob_type->tp_as_number != NULL) {\r
+ slotv = NB_TERNOP(v1->ob_type->tp_as_number,\r
+ op_slot);\r
+ if (slotv)\r
+ x = slotv(v1, w2, z2);\r
+ else\r
+ c = -1;\r
+ }\r
+ else\r
+ c = -1;\r
+\r
+ Py_DECREF(w2);\r
+ Py_DECREF(z2);\r
+ error1:\r
+ Py_DECREF(v1);\r
+ Py_DECREF(z1);\r
+ error2:\r
+ Py_DECREF(v);\r
+ Py_DECREF(w);\r
+ error3:\r
+ if (c >= 0)\r
+ return x;\r
+ }\r
+\r
+ if (z == Py_None)\r
+ PyErr_Format(\r
+ PyExc_TypeError,\r
+ "unsupported operand type(s) for ** or pow(): "\r
+ "'%.100s' and '%.100s'",\r
+ v->ob_type->tp_name,\r
+ w->ob_type->tp_name);\r
+ else\r
+ PyErr_Format(\r
+ PyExc_TypeError,\r
+ "unsupported operand type(s) for pow(): "\r
+ "'%.100s', '%.100s', '%.100s'",\r
+ v->ob_type->tp_name,\r
+ w->ob_type->tp_name,\r
+ z->ob_type->tp_name);\r
+ return NULL;\r
+}\r
+\r
+#define BINARY_FUNC(func, op, op_name) \\r
+ PyObject * \\r
+ func(PyObject *v, PyObject *w) { \\r
+ return binary_op(v, w, NB_SLOT(op), op_name); \\r
+ }\r
+\r
+BINARY_FUNC(PyNumber_Or, nb_or, "|")\r
+BINARY_FUNC(PyNumber_Xor, nb_xor, "^")\r
+BINARY_FUNC(PyNumber_And, nb_and, "&")\r
+BINARY_FUNC(PyNumber_Lshift, nb_lshift, "<<")\r
+BINARY_FUNC(PyNumber_Rshift, nb_rshift, ">>")\r
+BINARY_FUNC(PyNumber_Subtract, nb_subtract, "-")\r
+BINARY_FUNC(PyNumber_Divide, nb_divide, "/")\r
+BINARY_FUNC(PyNumber_Divmod, nb_divmod, "divmod()")\r
+\r
+PyObject *\r
+PyNumber_Add(PyObject *v, PyObject *w)\r
+{\r
+ PyObject *result = binary_op1(v, w, NB_SLOT(nb_add));\r
+ if (result == Py_NotImplemented) {\r
+ PySequenceMethods *m = v->ob_type->tp_as_sequence;\r
+ Py_DECREF(result);\r
+ if (m && m->sq_concat) {\r
+ return (*m->sq_concat)(v, w);\r
+ }\r
+ result = binop_type_error(v, w, "+");\r
+ }\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)\r
+{\r
+ Py_ssize_t count;\r
+ if (PyIndex_Check(n)) {\r
+ count = PyNumber_AsSsize_t(n, PyExc_OverflowError);\r
+ if (count == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ }\r
+ else {\r
+ return type_error("can't multiply sequence by "\r
+ "non-int of type '%.200s'", n);\r
+ }\r
+ return (*repeatfunc)(seq, count);\r
+}\r
+\r
+PyObject *\r
+PyNumber_Multiply(PyObject *v, PyObject *w)\r
+{\r
+ PyObject *result = binary_op1(v, w, NB_SLOT(nb_multiply));\r
+ if (result == Py_NotImplemented) {\r
+ PySequenceMethods *mv = v->ob_type->tp_as_sequence;\r
+ PySequenceMethods *mw = w->ob_type->tp_as_sequence;\r
+ Py_DECREF(result);\r
+ if (mv && mv->sq_repeat) {\r
+ return sequence_repeat(mv->sq_repeat, v, w);\r
+ }\r
+ else if (mw && mw->sq_repeat) {\r
+ return sequence_repeat(mw->sq_repeat, w, v);\r
+ }\r
+ result = binop_type_error(v, w, "*");\r
+ }\r
+ return result;\r
+}\r
+\r
+PyObject *\r
+PyNumber_FloorDivide(PyObject *v, PyObject *w)\r
+{\r
+ /* XXX tp_flags test */\r
+ return binary_op(v, w, NB_SLOT(nb_floor_divide), "//");\r
+}\r
+\r
+PyObject *\r
+PyNumber_TrueDivide(PyObject *v, PyObject *w)\r
+{\r
+ /* XXX tp_flags test */\r
+ return binary_op(v, w, NB_SLOT(nb_true_divide), "/");\r
+}\r
+\r
+PyObject *\r
+PyNumber_Remainder(PyObject *v, PyObject *w)\r
+{\r
+ return binary_op(v, w, NB_SLOT(nb_remainder), "%");\r
+}\r
+\r
+PyObject *\r
+PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)\r
+{\r
+ return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");\r
+}\r
+\r
+/* Binary in-place operators */\r
+\r
+/* The in-place operators are defined to fall back to the 'normal',\r
+ non in-place operations, if the in-place methods are not in place.\r
+\r
+ - If the left hand object has the appropriate struct members, and\r
+ they are filled, call the appropriate function and return the\r
+ result. No coercion is done on the arguments; the left-hand object\r
+ is the one the operation is performed on, and it's up to the\r
+ function to deal with the right-hand object.\r
+\r
+ - Otherwise, in-place modification is not supported. Handle it exactly as\r
+ a non in-place operation of the same kind.\r
+\r
+ */\r
+\r
+#define HASINPLACE(t) \\r
+ PyType_HasFeature((t)->ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)\r
+\r
+static PyObject *\r
+binary_iop1(PyObject *v, PyObject *w, const int iop_slot, const int op_slot)\r
+{\r
+ PyNumberMethods *mv = v->ob_type->tp_as_number;\r
+ if (mv != NULL && HASINPLACE(v)) {\r
+ binaryfunc slot = NB_BINOP(mv, iop_slot);\r
+ if (slot) {\r
+ PyObject *x = (slot)(v, w);\r
+ if (x != Py_NotImplemented) {\r
+ return x;\r
+ }\r
+ Py_DECREF(x);\r
+ }\r
+ }\r
+ return binary_op1(v, w, op_slot);\r
+}\r
+\r
+static PyObject *\r
+binary_iop(PyObject *v, PyObject *w, const int iop_slot, const int op_slot,\r
+ const char *op_name)\r
+{\r
+ PyObject *result = binary_iop1(v, w, iop_slot, op_slot);\r
+ if (result == Py_NotImplemented) {\r
+ Py_DECREF(result);\r
+ return binop_type_error(v, w, op_name);\r
+ }\r
+ return result;\r
+}\r
+\r
+#define INPLACE_BINOP(func, iop, op, op_name) \\r
+ PyObject * \\r
+ func(PyObject *v, PyObject *w) { \\r
+ return binary_iop(v, w, NB_SLOT(iop), NB_SLOT(op), op_name); \\r
+ }\r
+\r
+INPLACE_BINOP(PyNumber_InPlaceOr, nb_inplace_or, nb_or, "|=")\r
+INPLACE_BINOP(PyNumber_InPlaceXor, nb_inplace_xor, nb_xor, "^=")\r
+INPLACE_BINOP(PyNumber_InPlaceAnd, nb_inplace_and, nb_and, "&=")\r
+INPLACE_BINOP(PyNumber_InPlaceLshift, nb_inplace_lshift, nb_lshift, "<<=")\r
+INPLACE_BINOP(PyNumber_InPlaceRshift, nb_inplace_rshift, nb_rshift, ">>=")\r
+INPLACE_BINOP(PyNumber_InPlaceSubtract, nb_inplace_subtract, nb_subtract, "-=")\r
+INPLACE_BINOP(PyNumber_InPlaceDivide, nb_inplace_divide, nb_divide, "/=")\r
+\r
+PyObject *\r
+PyNumber_InPlaceFloorDivide(PyObject *v, PyObject *w)\r
+{\r
+ /* XXX tp_flags test */\r
+ return binary_iop(v, w, NB_SLOT(nb_inplace_floor_divide),\r
+ NB_SLOT(nb_floor_divide), "//=");\r
+}\r
+\r
+PyObject *\r
+PyNumber_InPlaceTrueDivide(PyObject *v, PyObject *w)\r
+{\r
+ /* XXX tp_flags test */\r
+ return binary_iop(v, w, NB_SLOT(nb_inplace_true_divide),\r
+ NB_SLOT(nb_true_divide), "/=");\r
+}\r
+\r
+PyObject *\r
+PyNumber_InPlaceAdd(PyObject *v, PyObject *w)\r
+{\r
+ PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_add),\r
+ NB_SLOT(nb_add));\r
+ if (result == Py_NotImplemented) {\r
+ PySequenceMethods *m = v->ob_type->tp_as_sequence;\r
+ Py_DECREF(result);\r
+ if (m != NULL) {\r
+ binaryfunc f = NULL;\r
+ if (HASINPLACE(v))\r
+ f = m->sq_inplace_concat;\r
+ if (f == NULL)\r
+ f = m->sq_concat;\r
+ if (f != NULL)\r
+ return (*f)(v, w);\r
+ }\r
+ result = binop_type_error(v, w, "+=");\r
+ }\r
+ return result;\r
+}\r
+\r
+PyObject *\r
+PyNumber_InPlaceMultiply(PyObject *v, PyObject *w)\r
+{\r
+ PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_multiply),\r
+ NB_SLOT(nb_multiply));\r
+ if (result == Py_NotImplemented) {\r
+ ssizeargfunc f = NULL;\r
+ PySequenceMethods *mv = v->ob_type->tp_as_sequence;\r
+ PySequenceMethods *mw = w->ob_type->tp_as_sequence;\r
+ Py_DECREF(result);\r
+ if (mv != NULL) {\r
+ if (HASINPLACE(v))\r
+ f = mv->sq_inplace_repeat;\r
+ if (f == NULL)\r
+ f = mv->sq_repeat;\r
+ if (f != NULL)\r
+ return sequence_repeat(f, v, w);\r
+ }\r
+ else if (mw != NULL) {\r
+ /* Note that the right hand operand should not be\r
+ * mutated in this case so sq_inplace_repeat is not\r
+ * used. */\r
+ if (mw->sq_repeat)\r
+ return sequence_repeat(mw->sq_repeat, w, v);\r
+ }\r
+ result = binop_type_error(v, w, "*=");\r
+ }\r
+ return result;\r
+}\r
+\r
+PyObject *\r
+PyNumber_InPlaceRemainder(PyObject *v, PyObject *w)\r
+{\r
+ return binary_iop(v, w, NB_SLOT(nb_inplace_remainder),\r
+ NB_SLOT(nb_remainder), "%=");\r
+}\r
+\r
+PyObject *\r
+PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)\r
+{\r
+ if (HASINPLACE(v) && v->ob_type->tp_as_number &&\r
+ v->ob_type->tp_as_number->nb_inplace_power != NULL) {\r
+ return ternary_op(v, w, z, NB_SLOT(nb_inplace_power), "**=");\r
+ }\r
+ else {\r
+ return ternary_op(v, w, z, NB_SLOT(nb_power), "**=");\r
+ }\r
+}\r
+\r
+\r
+/* Unary operators and functions */\r
+\r
+PyObject *\r
+PyNumber_Negative(PyObject *o)\r
+{\r
+ PyNumberMethods *m;\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+ m = o->ob_type->tp_as_number;\r
+ if (m && m->nb_negative)\r
+ return (*m->nb_negative)(o);\r
+\r
+ return type_error("bad operand type for unary -: '%.200s'", o);\r
+}\r
+\r
+PyObject *\r
+PyNumber_Positive(PyObject *o)\r
+{\r
+ PyNumberMethods *m;\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+ m = o->ob_type->tp_as_number;\r
+ if (m && m->nb_positive)\r
+ return (*m->nb_positive)(o);\r
+\r
+ return type_error("bad operand type for unary +: '%.200s'", o);\r
+}\r
+\r
+PyObject *\r
+PyNumber_Invert(PyObject *o)\r
+{\r
+ PyNumberMethods *m;\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+ m = o->ob_type->tp_as_number;\r
+ if (m && m->nb_invert)\r
+ return (*m->nb_invert)(o);\r
+\r
+ return type_error("bad operand type for unary ~: '%.200s'", o);\r
+}\r
+\r
+PyObject *\r
+PyNumber_Absolute(PyObject *o)\r
+{\r
+ PyNumberMethods *m;\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+ m = o->ob_type->tp_as_number;\r
+ if (m && m->nb_absolute)\r
+ return m->nb_absolute(o);\r
+\r
+ return type_error("bad operand type for abs(): '%.200s'", o);\r
+}\r
+\r
+/* Add a check for embedded NULL-bytes in the argument. */\r
+static PyObject *\r
+int_from_string(const char *s, Py_ssize_t len)\r
+{\r
+ char *end;\r
+ PyObject *x;\r
+\r
+ x = PyInt_FromString((char*)s, &end, 10);\r
+ if (x == NULL)\r
+ return NULL;\r
+ if (end != s + len) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "null byte in argument for int()");\r
+ Py_DECREF(x);\r
+ return NULL;\r
+ }\r
+ return x;\r
+}\r
+\r
+/* Return a Python Int or Long from the object item\r
+ Raise TypeError if the result is not an int-or-long\r
+ or if the object cannot be interpreted as an index.\r
+*/\r
+PyObject *\r
+PyNumber_Index(PyObject *item)\r
+{\r
+ PyObject *result = NULL;\r
+ if (item == NULL)\r
+ return null_error();\r
+ if (PyInt_Check(item) || PyLong_Check(item)) {\r
+ Py_INCREF(item);\r
+ return item;\r
+ }\r
+ if (PyIndex_Check(item)) {\r
+ result = item->ob_type->tp_as_number->nb_index(item);\r
+ if (result &&\r
+ !PyInt_Check(result) && !PyLong_Check(result)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__index__ returned non-(int,long) " \\r
+ "(type %.200s)",\r
+ result->ob_type->tp_name);\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "'%.200s' object cannot be interpreted "\r
+ "as an index", item->ob_type->tp_name);\r
+ }\r
+ return result;\r
+}\r
+\r
+/* Return an error on Overflow only if err is not NULL*/\r
+\r
+Py_ssize_t\r
+PyNumber_AsSsize_t(PyObject *item, PyObject *err)\r
+{\r
+ Py_ssize_t result;\r
+ PyObject *runerr;\r
+ PyObject *value = PyNumber_Index(item);\r
+ if (value == NULL)\r
+ return -1;\r
+\r
+ /* We're done if PyInt_AsSsize_t() returns without error. */\r
+ result = PyInt_AsSsize_t(value);\r
+ if (result != -1 || !(runerr = PyErr_Occurred()))\r
+ goto finish;\r
+\r
+ /* Error handling code -- only manage OverflowError differently */\r
+ if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))\r
+ goto finish;\r
+\r
+ PyErr_Clear();\r
+ /* If no error-handling desired then the default clipping\r
+ is sufficient.\r
+ */\r
+ if (!err) {\r
+ assert(PyLong_Check(value));\r
+ /* Whether or not it is less than or equal to\r
+ zero is determined by the sign of ob_size\r
+ */\r
+ if (_PyLong_Sign(value) < 0)\r
+ result = PY_SSIZE_T_MIN;\r
+ else\r
+ result = PY_SSIZE_T_MAX;\r
+ }\r
+ else {\r
+ /* Otherwise replace the error with caller's error object. */\r
+ PyErr_Format(err,\r
+ "cannot fit '%.200s' into an index-sized integer",\r
+ item->ob_type->tp_name);\r
+ }\r
+\r
+ finish:\r
+ Py_DECREF(value);\r
+ return result;\r
+}\r
+\r
+\r
+PyObject *\r
+_PyNumber_ConvertIntegralToInt(PyObject *integral, const char* error_format)\r
+{\r
+ const char *type_name;\r
+ static PyObject *int_name = NULL;\r
+ if (int_name == NULL) {\r
+ int_name = PyString_InternFromString("__int__");\r
+ if (int_name == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ if (integral && (!PyInt_Check(integral) &&\r
+ !PyLong_Check(integral))) {\r
+ /* Don't go through tp_as_number->nb_int to avoid\r
+ hitting the classic class fallback to __trunc__. */\r
+ PyObject *int_func = PyObject_GetAttr(integral, int_name);\r
+ if (int_func == NULL) {\r
+ PyErr_Clear(); /* Raise a different error. */\r
+ goto non_integral_error;\r
+ }\r
+ Py_DECREF(integral);\r
+ integral = PyEval_CallObject(int_func, NULL);\r
+ Py_DECREF(int_func);\r
+ if (integral && (!PyInt_Check(integral) &&\r
+ !PyLong_Check(integral))) {\r
+ goto non_integral_error;\r
+ }\r
+ }\r
+ return integral;\r
+\r
+non_integral_error:\r
+ if (PyInstance_Check(integral)) {\r
+ type_name = PyString_AS_STRING(((PyInstanceObject *)integral)\r
+ ->in_class->cl_name);\r
+ }\r
+ else {\r
+ type_name = integral->ob_type->tp_name;\r
+ }\r
+ PyErr_Format(PyExc_TypeError, error_format, type_name);\r
+ Py_DECREF(integral);\r
+ return NULL;\r
+}\r
+\r
+\r
+PyObject *\r
+PyNumber_Int(PyObject *o)\r
+{\r
+ PyNumberMethods *m;\r
+ static PyObject *trunc_name = NULL;\r
+ PyObject *trunc_func;\r
+ const char *buffer;\r
+ Py_ssize_t buffer_len;\r
+\r
+ if (trunc_name == NULL) {\r
+ trunc_name = PyString_InternFromString("__trunc__");\r
+ if (trunc_name == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+ if (PyInt_CheckExact(o)) {\r
+ Py_INCREF(o);\r
+ return o;\r
+ }\r
+ m = o->ob_type->tp_as_number;\r
+ if (m && m->nb_int) { /* This should include subclasses of int */\r
+ /* Classic classes always take this branch. */\r
+ PyObject *res = m->nb_int(o);\r
+ if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__int__ returned non-int (type %.200s)",\r
+ res->ob_type->tp_name);\r
+ Py_DECREF(res);\r
+ return NULL;\r
+ }\r
+ return res;\r
+ }\r
+ if (PyInt_Check(o)) { /* A int subclass without nb_int */\r
+ PyIntObject *io = (PyIntObject*)o;\r
+ return PyInt_FromLong(io->ob_ival);\r
+ }\r
+ trunc_func = PyObject_GetAttr(o, trunc_name);\r
+ if (trunc_func) {\r
+ PyObject *truncated = PyEval_CallObject(trunc_func, NULL);\r
+ Py_DECREF(trunc_func);\r
+ /* __trunc__ is specified to return an Integral type, but\r
+ int() needs to return an int. */\r
+ return _PyNumber_ConvertIntegralToInt(\r
+ truncated,\r
+ "__trunc__ returned non-Integral (type %.200s)");\r
+ }\r
+ PyErr_Clear(); /* It's not an error if o.__trunc__ doesn't exist. */\r
+\r
+ if (PyString_Check(o))\r
+ return int_from_string(PyString_AS_STRING(o),\r
+ PyString_GET_SIZE(o));\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(o))\r
+ return PyInt_FromUnicode(PyUnicode_AS_UNICODE(o),\r
+ PyUnicode_GET_SIZE(o),\r
+ 10);\r
+#endif\r
+ if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))\r
+ return int_from_string((char*)buffer, buffer_len);\r
+\r
+ return type_error("int() argument must be a string or a "\r
+ "number, not '%.200s'", o);\r
+}\r
+\r
+/* Add a check for embedded NULL-bytes in the argument. */\r
+static PyObject *\r
+long_from_string(const char *s, Py_ssize_t len)\r
+{\r
+ char *end;\r
+ PyObject *x;\r
+\r
+ x = PyLong_FromString((char*)s, &end, 10);\r
+ if (x == NULL)\r
+ return NULL;\r
+ if (end != s + len) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "null byte in argument for long()");\r
+ Py_DECREF(x);\r
+ return NULL;\r
+ }\r
+ return x;\r
+}\r
+\r
+PyObject *\r
+PyNumber_Long(PyObject *o)\r
+{\r
+ PyNumberMethods *m;\r
+ static PyObject *trunc_name = NULL;\r
+ PyObject *trunc_func;\r
+ const char *buffer;\r
+ Py_ssize_t buffer_len;\r
+\r
+ if (trunc_name == NULL) {\r
+ trunc_name = PyString_InternFromString("__trunc__");\r
+ if (trunc_name == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+ m = o->ob_type->tp_as_number;\r
+ if (m && m->nb_long) { /* This should include subclasses of long */\r
+ /* Classic classes always take this branch. */\r
+ PyObject *res = m->nb_long(o);\r
+ if (res == NULL)\r
+ return NULL;\r
+ if (PyInt_Check(res)) {\r
+ long value = PyInt_AS_LONG(res);\r
+ Py_DECREF(res);\r
+ return PyLong_FromLong(value);\r
+ }\r
+ else if (!PyLong_Check(res)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__long__ returned non-long (type %.200s)",\r
+ res->ob_type->tp_name);\r
+ Py_DECREF(res);\r
+ return NULL;\r
+ }\r
+ return res;\r
+ }\r
+ if (PyLong_Check(o)) /* A long subclass without nb_long */\r
+ return _PyLong_Copy((PyLongObject *)o);\r
+ trunc_func = PyObject_GetAttr(o, trunc_name);\r
+ if (trunc_func) {\r
+ PyObject *truncated = PyEval_CallObject(trunc_func, NULL);\r
+ PyObject *int_instance;\r
+ Py_DECREF(trunc_func);\r
+ /* __trunc__ is specified to return an Integral type,\r
+ but long() needs to return a long. */\r
+ int_instance = _PyNumber_ConvertIntegralToInt(\r
+ truncated,\r
+ "__trunc__ returned non-Integral (type %.200s)");\r
+ if (int_instance && PyInt_Check(int_instance)) {\r
+ /* Make sure that long() returns a long instance. */\r
+ long value = PyInt_AS_LONG(int_instance);\r
+ Py_DECREF(int_instance);\r
+ return PyLong_FromLong(value);\r
+ }\r
+ return int_instance;\r
+ }\r
+ PyErr_Clear(); /* It's not an error if o.__trunc__ doesn't exist. */\r
+\r
+ if (PyString_Check(o))\r
+ /* need to do extra error checking that PyLong_FromString()\r
+ * doesn't do. In particular long('9.5') must raise an\r
+ * exception, not truncate the float.\r
+ */\r
+ return long_from_string(PyString_AS_STRING(o),\r
+ PyString_GET_SIZE(o));\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(o))\r
+ /* The above check is done in PyLong_FromUnicode(). */\r
+ return PyLong_FromUnicode(PyUnicode_AS_UNICODE(o),\r
+ PyUnicode_GET_SIZE(o),\r
+ 10);\r
+#endif\r
+ if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))\r
+ return long_from_string(buffer, buffer_len);\r
+\r
+ return type_error("long() argument must be a string or a "\r
+ "number, not '%.200s'", o);\r
+}\r
+\r
+PyObject *\r
+PyNumber_Float(PyObject *o)\r
+{\r
+ PyNumberMethods *m;\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+ m = o->ob_type->tp_as_number;\r
+ if (m && m->nb_float) { /* This should include subclasses of float */\r
+ PyObject *res = m->nb_float(o);\r
+ if (res && !PyFloat_Check(res)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__float__ returned non-float (type %.200s)",\r
+ res->ob_type->tp_name);\r
+ Py_DECREF(res);\r
+ return NULL;\r
+ }\r
+ return res;\r
+ }\r
+ if (PyFloat_Check(o)) { /* A float subclass with nb_float == NULL */\r
+ PyFloatObject *po = (PyFloatObject *)o;\r
+ return PyFloat_FromDouble(po->ob_fval);\r
+ }\r
+ return PyFloat_FromString(o, NULL);\r
+}\r
+\r
+PyObject *\r
+PyNumber_ToBase(PyObject *n, int base)\r
+{\r
+ PyObject *res = NULL;\r
+ PyObject *index = PyNumber_Index(n);\r
+\r
+ if (!index)\r
+ return NULL;\r
+ if (PyLong_Check(index))\r
+ res = _PyLong_Format(index, base, 0, 1);\r
+ else if (PyInt_Check(index))\r
+ res = _PyInt_Format((PyIntObject*)index, base, 1);\r
+ else\r
+ /* It should not be possible to get here, as\r
+ PyNumber_Index already has a check for the same\r
+ condition */\r
+ PyErr_SetString(PyExc_ValueError, "PyNumber_ToBase: index not "\r
+ "int or long");\r
+ Py_DECREF(index);\r
+ return res;\r
+}\r
+\r
+\r
+/* Operations on sequences */\r
+\r
+int\r
+PySequence_Check(PyObject *s)\r
+{\r
+ if (s == NULL)\r
+ return 0;\r
+ if (PyInstance_Check(s))\r
+ return PyObject_HasAttrString(s, "__getitem__");\r
+ if (PyDict_Check(s))\r
+ return 0;\r
+ return s->ob_type->tp_as_sequence &&\r
+ s->ob_type->tp_as_sequence->sq_item != NULL;\r
+}\r
+\r
+Py_ssize_t\r
+PySequence_Size(PyObject *s)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (s == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+\r
+ m = s->ob_type->tp_as_sequence;\r
+ if (m && m->sq_length)\r
+ return m->sq_length(s);\r
+\r
+ type_error("object of type '%.200s' has no len()", s);\r
+ return -1;\r
+}\r
+\r
+#undef PySequence_Length\r
+Py_ssize_t\r
+PySequence_Length(PyObject *s)\r
+{\r
+ return PySequence_Size(s);\r
+}\r
+#define PySequence_Length PySequence_Size\r
+\r
+PyObject *\r
+PySequence_Concat(PyObject *s, PyObject *o)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (s == NULL || o == NULL)\r
+ return null_error();\r
+\r
+ m = s->ob_type->tp_as_sequence;\r
+ if (m && m->sq_concat)\r
+ return m->sq_concat(s, o);\r
+\r
+ /* Instances of user classes defining an __add__() method only\r
+ have an nb_add slot, not an sq_concat slot. So we fall back\r
+ to nb_add if both arguments appear to be sequences. */\r
+ if (PySequence_Check(s) && PySequence_Check(o)) {\r
+ PyObject *result = binary_op1(s, o, NB_SLOT(nb_add));\r
+ if (result != Py_NotImplemented)\r
+ return result;\r
+ Py_DECREF(result);\r
+ }\r
+ return type_error("'%.200s' object can't be concatenated", s);\r
+}\r
+\r
+PyObject *\r
+PySequence_Repeat(PyObject *o, Py_ssize_t count)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+\r
+ m = o->ob_type->tp_as_sequence;\r
+ if (m && m->sq_repeat)\r
+ return m->sq_repeat(o, count);\r
+\r
+ /* Instances of user classes defining a __mul__() method only\r
+ have an nb_multiply slot, not an sq_repeat slot. so we fall back\r
+ to nb_multiply if o appears to be a sequence. */\r
+ if (PySequence_Check(o)) {\r
+ PyObject *n, *result;\r
+ n = PyInt_FromSsize_t(count);\r
+ if (n == NULL)\r
+ return NULL;\r
+ result = binary_op1(o, n, NB_SLOT(nb_multiply));\r
+ Py_DECREF(n);\r
+ if (result != Py_NotImplemented)\r
+ return result;\r
+ Py_DECREF(result);\r
+ }\r
+ return type_error("'%.200s' object can't be repeated", o);\r
+}\r
+\r
+PyObject *\r
+PySequence_InPlaceConcat(PyObject *s, PyObject *o)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (s == NULL || o == NULL)\r
+ return null_error();\r
+\r
+ m = s->ob_type->tp_as_sequence;\r
+ if (m && HASINPLACE(s) && m->sq_inplace_concat)\r
+ return m->sq_inplace_concat(s, o);\r
+ if (m && m->sq_concat)\r
+ return m->sq_concat(s, o);\r
+\r
+ if (PySequence_Check(s) && PySequence_Check(o)) {\r
+ PyObject *result = binary_iop1(s, o, NB_SLOT(nb_inplace_add),\r
+ NB_SLOT(nb_add));\r
+ if (result != Py_NotImplemented)\r
+ return result;\r
+ Py_DECREF(result);\r
+ }\r
+ return type_error("'%.200s' object can't be concatenated", s);\r
+}\r
+\r
+PyObject *\r
+PySequence_InPlaceRepeat(PyObject *o, Py_ssize_t count)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (o == NULL)\r
+ return null_error();\r
+\r
+ m = o->ob_type->tp_as_sequence;\r
+ if (m && HASINPLACE(o) && m->sq_inplace_repeat)\r
+ return m->sq_inplace_repeat(o, count);\r
+ if (m && m->sq_repeat)\r
+ return m->sq_repeat(o, count);\r
+\r
+ if (PySequence_Check(o)) {\r
+ PyObject *n, *result;\r
+ n = PyInt_FromSsize_t(count);\r
+ if (n == NULL)\r
+ return NULL;\r
+ result = binary_iop1(o, n, NB_SLOT(nb_inplace_multiply),\r
+ NB_SLOT(nb_multiply));\r
+ Py_DECREF(n);\r
+ if (result != Py_NotImplemented)\r
+ return result;\r
+ Py_DECREF(result);\r
+ }\r
+ return type_error("'%.200s' object can't be repeated", o);\r
+}\r
+\r
+PyObject *\r
+PySequence_GetItem(PyObject *s, Py_ssize_t i)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (s == NULL)\r
+ return null_error();\r
+\r
+ m = s->ob_type->tp_as_sequence;\r
+ if (m && m->sq_item) {\r
+ if (i < 0) {\r
+ if (m->sq_length) {\r
+ Py_ssize_t l = (*m->sq_length)(s);\r
+ if (l < 0)\r
+ return NULL;\r
+ i += l;\r
+ }\r
+ }\r
+ return m->sq_item(s, i);\r
+ }\r
+\r
+ return type_error("'%.200s' object does not support indexing", s);\r
+}\r
+\r
+PyObject *\r
+PySequence_GetSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2)\r
+{\r
+ PySequenceMethods *m;\r
+ PyMappingMethods *mp;\r
+\r
+ if (!s) return null_error();\r
+\r
+ m = s->ob_type->tp_as_sequence;\r
+ if (m && m->sq_slice) {\r
+ if (i1 < 0 || i2 < 0) {\r
+ if (m->sq_length) {\r
+ Py_ssize_t l = (*m->sq_length)(s);\r
+ if (l < 0)\r
+ return NULL;\r
+ if (i1 < 0)\r
+ i1 += l;\r
+ if (i2 < 0)\r
+ i2 += l;\r
+ }\r
+ }\r
+ return m->sq_slice(s, i1, i2);\r
+ } else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_subscript) {\r
+ PyObject *res;\r
+ PyObject *slice = _PySlice_FromIndices(i1, i2);\r
+ if (!slice)\r
+ return NULL;\r
+ res = mp->mp_subscript(s, slice);\r
+ Py_DECREF(slice);\r
+ return res;\r
+ }\r
+\r
+ return type_error("'%.200s' object is unsliceable", s);\r
+}\r
+\r
+int\r
+PySequence_SetItem(PyObject *s, Py_ssize_t i, PyObject *o)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (s == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+\r
+ m = s->ob_type->tp_as_sequence;\r
+ if (m && m->sq_ass_item) {\r
+ if (i < 0) {\r
+ if (m->sq_length) {\r
+ Py_ssize_t l = (*m->sq_length)(s);\r
+ if (l < 0)\r
+ return -1;\r
+ i += l;\r
+ }\r
+ }\r
+ return m->sq_ass_item(s, i, o);\r
+ }\r
+\r
+ type_error("'%.200s' object does not support item assignment", s);\r
+ return -1;\r
+}\r
+\r
+int\r
+PySequence_DelItem(PyObject *s, Py_ssize_t i)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (s == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+\r
+ m = s->ob_type->tp_as_sequence;\r
+ if (m && m->sq_ass_item) {\r
+ if (i < 0) {\r
+ if (m->sq_length) {\r
+ Py_ssize_t l = (*m->sq_length)(s);\r
+ if (l < 0)\r
+ return -1;\r
+ i += l;\r
+ }\r
+ }\r
+ return m->sq_ass_item(s, i, (PyObject *)NULL);\r
+ }\r
+\r
+ type_error("'%.200s' object doesn't support item deletion", s);\r
+ return -1;\r
+}\r
+\r
+int\r
+PySequence_SetSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2, PyObject *o)\r
+{\r
+ PySequenceMethods *m;\r
+ PyMappingMethods *mp;\r
+\r
+ if (s == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+\r
+ m = s->ob_type->tp_as_sequence;\r
+ if (m && m->sq_ass_slice) {\r
+ if (i1 < 0 || i2 < 0) {\r
+ if (m->sq_length) {\r
+ Py_ssize_t l = (*m->sq_length)(s);\r
+ if (l < 0)\r
+ return -1;\r
+ if (i1 < 0)\r
+ i1 += l;\r
+ if (i2 < 0)\r
+ i2 += l;\r
+ }\r
+ }\r
+ return m->sq_ass_slice(s, i1, i2, o);\r
+ } else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_ass_subscript) {\r
+ int res;\r
+ PyObject *slice = _PySlice_FromIndices(i1, i2);\r
+ if (!slice)\r
+ return -1;\r
+ res = mp->mp_ass_subscript(s, slice, o);\r
+ Py_DECREF(slice);\r
+ return res;\r
+ }\r
+\r
+ type_error("'%.200s' object doesn't support slice assignment", s);\r
+ return -1;\r
+}\r
+\r
+int\r
+PySequence_DelSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2)\r
+{\r
+ PySequenceMethods *m;\r
+\r
+ if (s == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+\r
+ m = s->ob_type->tp_as_sequence;\r
+ if (m && m->sq_ass_slice) {\r
+ if (i1 < 0 || i2 < 0) {\r
+ if (m->sq_length) {\r
+ Py_ssize_t l = (*m->sq_length)(s);\r
+ if (l < 0)\r
+ return -1;\r
+ if (i1 < 0)\r
+ i1 += l;\r
+ if (i2 < 0)\r
+ i2 += l;\r
+ }\r
+ }\r
+ return m->sq_ass_slice(s, i1, i2, (PyObject *)NULL);\r
+ }\r
+ type_error("'%.200s' object doesn't support slice deletion", s);\r
+ return -1;\r
+}\r
+\r
+PyObject *\r
+PySequence_Tuple(PyObject *v)\r
+{\r
+ PyObject *it; /* iter(v) */\r
+ Py_ssize_t n; /* guess for result tuple size */\r
+ PyObject *result = NULL;\r
+ Py_ssize_t j;\r
+\r
+ if (v == NULL)\r
+ return null_error();\r
+\r
+ /* Special-case the common tuple and list cases, for efficiency. */\r
+ if (PyTuple_CheckExact(v)) {\r
+ /* Note that we can't know whether it's safe to return\r
+ a tuple *subclass* instance as-is, hence the restriction\r
+ to exact tuples here. In contrast, lists always make\r
+ a copy, so there's no need for exactness below. */\r
+ Py_INCREF(v);\r
+ return v;\r
+ }\r
+ if (PyList_Check(v))\r
+ return PyList_AsTuple(v);\r
+\r
+ /* Get iterator. */\r
+ it = PyObject_GetIter(v);\r
+ if (it == NULL)\r
+ return NULL;\r
+\r
+ /* Guess result size and allocate space. */\r
+ n = _PyObject_LengthHint(v, 10);\r
+ if (n == -1)\r
+ goto Fail;\r
+ result = PyTuple_New(n);\r
+ if (result == NULL)\r
+ goto Fail;\r
+\r
+ /* Fill the tuple. */\r
+ for (j = 0; ; ++j) {\r
+ PyObject *item = PyIter_Next(it);\r
+ if (item == NULL) {\r
+ if (PyErr_Occurred())\r
+ goto Fail;\r
+ break;\r
+ }\r
+ if (j >= n) {\r
+ Py_ssize_t oldn = n;\r
+ /* The over-allocation strategy can grow a bit faster\r
+ than for lists because unlike lists the\r
+ over-allocation isn't permanent -- we reclaim\r
+ the excess before the end of this routine.\r
+ So, grow by ten and then add 25%.\r
+ */\r
+ n += 10;\r
+ n += n >> 2;\r
+ if (n < oldn) {\r
+ /* Check for overflow */\r
+ PyErr_NoMemory();\r
+ Py_DECREF(item);\r
+ goto Fail;\r
+ }\r
+ if (_PyTuple_Resize(&result, n) != 0) {\r
+ Py_DECREF(item);\r
+ goto Fail;\r
+ }\r
+ }\r
+ PyTuple_SET_ITEM(result, j, item);\r
+ }\r
+\r
+ /* Cut tuple back if guess was too large. */\r
+ if (j < n &&\r
+ _PyTuple_Resize(&result, j) != 0)\r
+ goto Fail;\r
+\r
+ Py_DECREF(it);\r
+ return result;\r
+\r
+Fail:\r
+ Py_XDECREF(result);\r
+ Py_DECREF(it);\r
+ return NULL;\r
+}\r
+\r
+PyObject *\r
+PySequence_List(PyObject *v)\r
+{\r
+ PyObject *result; /* result list */\r
+ PyObject *rv; /* return value from PyList_Extend */\r
+\r
+ if (v == NULL)\r
+ return null_error();\r
+\r
+ result = PyList_New(0);\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ rv = _PyList_Extend((PyListObject *)result, v);\r
+ if (rv == NULL) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ Py_DECREF(rv);\r
+ return result;\r
+}\r
+\r
+PyObject *\r
+PySequence_Fast(PyObject *v, const char *m)\r
+{\r
+ PyObject *it;\r
+\r
+ if (v == NULL)\r
+ return null_error();\r
+\r
+ if (PyList_CheckExact(v) || PyTuple_CheckExact(v)) {\r
+ Py_INCREF(v);\r
+ return v;\r
+ }\r
+\r
+ it = PyObject_GetIter(v);\r
+ if (it == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_TypeError))\r
+ PyErr_SetString(PyExc_TypeError, m);\r
+ return NULL;\r
+ }\r
+\r
+ v = PySequence_List(it);\r
+ Py_DECREF(it);\r
+\r
+ return v;\r
+}\r
+\r
+/* Iterate over seq. Result depends on the operation:\r
+ PY_ITERSEARCH_COUNT: -1 if error, else # of times obj appears in seq.\r
+ PY_ITERSEARCH_INDEX: 0-based index of first occurrence of obj in seq;\r
+ set ValueError and return -1 if none found; also return -1 on error.\r
+ Py_ITERSEARCH_CONTAINS: return 1 if obj in seq, else 0; -1 on error.\r
+*/\r
+Py_ssize_t\r
+_PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation)\r
+{\r
+ Py_ssize_t n;\r
+ int wrapped; /* for PY_ITERSEARCH_INDEX, true iff n wrapped around */\r
+ PyObject *it; /* iter(seq) */\r
+\r
+ if (seq == NULL || obj == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+\r
+ it = PyObject_GetIter(seq);\r
+ if (it == NULL) {\r
+ type_error("argument of type '%.200s' is not iterable", seq);\r
+ return -1;\r
+ }\r
+\r
+ n = wrapped = 0;\r
+ for (;;) {\r
+ int cmp;\r
+ PyObject *item = PyIter_Next(it);\r
+ if (item == NULL) {\r
+ if (PyErr_Occurred())\r
+ goto Fail;\r
+ break;\r
+ }\r
+\r
+ cmp = PyObject_RichCompareBool(obj, item, Py_EQ);\r
+ Py_DECREF(item);\r
+ if (cmp < 0)\r
+ goto Fail;\r
+ if (cmp > 0) {\r
+ switch (operation) {\r
+ case PY_ITERSEARCH_COUNT:\r
+ if (n == PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "count exceeds C integer size");\r
+ goto Fail;\r
+ }\r
+ ++n;\r
+ break;\r
+\r
+ case PY_ITERSEARCH_INDEX:\r
+ if (wrapped) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "index exceeds C integer size");\r
+ goto Fail;\r
+ }\r
+ goto Done;\r
+\r
+ case PY_ITERSEARCH_CONTAINS:\r
+ n = 1;\r
+ goto Done;\r
+\r
+ default:\r
+ assert(!"unknown operation");\r
+ }\r
+ }\r
+\r
+ if (operation == PY_ITERSEARCH_INDEX) {\r
+ if (n == PY_SSIZE_T_MAX)\r
+ wrapped = 1;\r
+ ++n;\r
+ }\r
+ }\r
+\r
+ if (operation != PY_ITERSEARCH_INDEX)\r
+ goto Done;\r
+\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "sequence.index(x): x not in sequence");\r
+ /* fall into failure code */\r
+Fail:\r
+ n = -1;\r
+ /* fall through */\r
+Done:\r
+ Py_DECREF(it);\r
+ return n;\r
+\r
+}\r
+\r
+/* Return # of times o appears in s. */\r
+Py_ssize_t\r
+PySequence_Count(PyObject *s, PyObject *o)\r
+{\r
+ return _PySequence_IterSearch(s, o, PY_ITERSEARCH_COUNT);\r
+}\r
+\r
+/* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.\r
+ * Use sq_contains if possible, else defer to _PySequence_IterSearch().\r
+ */\r
+int\r
+PySequence_Contains(PyObject *seq, PyObject *ob)\r
+{\r
+ Py_ssize_t result;\r
+ if (PyType_HasFeature(seq->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {\r
+ PySequenceMethods *sqm = seq->ob_type->tp_as_sequence;\r
+ if (sqm != NULL && sqm->sq_contains != NULL)\r
+ return (*sqm->sq_contains)(seq, ob);\r
+ }\r
+ result = _PySequence_IterSearch(seq, ob, PY_ITERSEARCH_CONTAINS);\r
+ return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);\r
+}\r
+\r
+/* Backwards compatibility */\r
+#undef PySequence_In\r
+int\r
+PySequence_In(PyObject *w, PyObject *v)\r
+{\r
+ return PySequence_Contains(w, v);\r
+}\r
+\r
+Py_ssize_t\r
+PySequence_Index(PyObject *s, PyObject *o)\r
+{\r
+ return _PySequence_IterSearch(s, o, PY_ITERSEARCH_INDEX);\r
+}\r
+\r
+/* Operations on mappings */\r
+\r
+int\r
+PyMapping_Check(PyObject *o)\r
+{\r
+ if (o && PyInstance_Check(o))\r
+ return PyObject_HasAttrString(o, "__getitem__");\r
+\r
+ return o && o->ob_type->tp_as_mapping &&\r
+ o->ob_type->tp_as_mapping->mp_subscript &&\r
+ !(o->ob_type->tp_as_sequence &&\r
+ o->ob_type->tp_as_sequence->sq_slice);\r
+}\r
+\r
+Py_ssize_t\r
+PyMapping_Size(PyObject *o)\r
+{\r
+ PyMappingMethods *m;\r
+\r
+ if (o == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+\r
+ m = o->ob_type->tp_as_mapping;\r
+ if (m && m->mp_length)\r
+ return m->mp_length(o);\r
+\r
+ type_error("object of type '%.200s' has no len()", o);\r
+ return -1;\r
+}\r
+\r
+#undef PyMapping_Length\r
+Py_ssize_t\r
+PyMapping_Length(PyObject *o)\r
+{\r
+ return PyMapping_Size(o);\r
+}\r
+#define PyMapping_Length PyMapping_Size\r
+\r
+PyObject *\r
+PyMapping_GetItemString(PyObject *o, char *key)\r
+{\r
+ PyObject *okey, *r;\r
+\r
+ if (key == NULL)\r
+ return null_error();\r
+\r
+ okey = PyString_FromString(key);\r
+ if (okey == NULL)\r
+ return NULL;\r
+ r = PyObject_GetItem(o, okey);\r
+ Py_DECREF(okey);\r
+ return r;\r
+}\r
+\r
+int\r
+PyMapping_SetItemString(PyObject *o, char *key, PyObject *value)\r
+{\r
+ PyObject *okey;\r
+ int r;\r
+\r
+ if (key == NULL) {\r
+ null_error();\r
+ return -1;\r
+ }\r
+\r
+ okey = PyString_FromString(key);\r
+ if (okey == NULL)\r
+ return -1;\r
+ r = PyObject_SetItem(o, okey, value);\r
+ Py_DECREF(okey);\r
+ return r;\r
+}\r
+\r
+int\r
+PyMapping_HasKeyString(PyObject *o, char *key)\r
+{\r
+ PyObject *v;\r
+\r
+ v = PyMapping_GetItemString(o, key);\r
+ if (v) {\r
+ Py_DECREF(v);\r
+ return 1;\r
+ }\r
+ PyErr_Clear();\r
+ return 0;\r
+}\r
+\r
+int\r
+PyMapping_HasKey(PyObject *o, PyObject *key)\r
+{\r
+ PyObject *v;\r
+\r
+ v = PyObject_GetItem(o, key);\r
+ if (v) {\r
+ Py_DECREF(v);\r
+ return 1;\r
+ }\r
+ PyErr_Clear();\r
+ return 0;\r
+}\r
+\r
+/* Operations on callable objects */\r
+\r
+/* XXX PyCallable_Check() is in object.c */\r
+\r
+PyObject *\r
+PyObject_CallObject(PyObject *o, PyObject *a)\r
+{\r
+ return PyEval_CallObjectWithKeywords(o, a, NULL);\r
+}\r
+\r
+PyObject *\r
+PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)\r
+{\r
+ ternaryfunc call;\r
+\r
+ if ((call = func->ob_type->tp_call) != NULL) {\r
+ PyObject *result;\r
+ if (Py_EnterRecursiveCall(" while calling a Python object"))\r
+ return NULL;\r
+ result = (*call)(func, arg, kw);\r
+ Py_LeaveRecursiveCall();\r
+ if (result == NULL && !PyErr_Occurred())\r
+ PyErr_SetString(\r
+ PyExc_SystemError,\r
+ "NULL result without error in PyObject_Call");\r
+ return result;\r
+ }\r
+ PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",\r
+ func->ob_type->tp_name);\r
+ return NULL;\r
+}\r
+\r
+static PyObject*\r
+call_function_tail(PyObject *callable, PyObject *args)\r
+{\r
+ PyObject *retval;\r
+\r
+ if (args == NULL)\r
+ return NULL;\r
+\r
+ if (!PyTuple_Check(args)) {\r
+ PyObject *a;\r
+\r
+ a = PyTuple_New(1);\r
+ if (a == NULL) {\r
+ Py_DECREF(args);\r
+ return NULL;\r
+ }\r
+ PyTuple_SET_ITEM(a, 0, args);\r
+ args = a;\r
+ }\r
+ retval = PyObject_Call(callable, args, NULL);\r
+\r
+ Py_DECREF(args);\r
+\r
+ return retval;\r
+}\r
+\r
+PyObject *\r
+PyObject_CallFunction(PyObject *callable, char *format, ...)\r
+{\r
+ va_list va;\r
+ PyObject *args;\r
+\r
+ if (callable == NULL)\r
+ return null_error();\r
+\r
+ if (format && *format) {\r
+ va_start(va, format);\r
+ args = Py_VaBuildValue(format, va);\r
+ va_end(va);\r
+ }\r
+ else\r
+ args = PyTuple_New(0);\r
+\r
+ return call_function_tail(callable, args);\r
+}\r
+\r
+PyObject *\r
+_PyObject_CallFunction_SizeT(PyObject *callable, char *format, ...)\r
+{\r
+ va_list va;\r
+ PyObject *args;\r
+\r
+ if (callable == NULL)\r
+ return null_error();\r
+\r
+ if (format && *format) {\r
+ va_start(va, format);\r
+ args = _Py_VaBuildValue_SizeT(format, va);\r
+ va_end(va);\r
+ }\r
+ else\r
+ args = PyTuple_New(0);\r
+\r
+ return call_function_tail(callable, args);\r
+}\r
+\r
+PyObject *\r
+PyObject_CallMethod(PyObject *o, char *name, char *format, ...)\r
+{\r
+ va_list va;\r
+ PyObject *args;\r
+ PyObject *func = NULL;\r
+ PyObject *retval = NULL;\r
+\r
+ if (o == NULL || name == NULL)\r
+ return null_error();\r
+\r
+ func = PyObject_GetAttrString(o, name);\r
+ if (func == NULL)\r
+ return NULL;\r
+\r
+ if (!PyCallable_Check(func)) {\r
+ type_error("attribute of type '%.200s' is not callable", func);\r
+ goto exit;\r
+ }\r
+\r
+ if (format && *format) {\r
+ va_start(va, format);\r
+ args = Py_VaBuildValue(format, va);\r
+ va_end(va);\r
+ }\r
+ else\r
+ args = PyTuple_New(0);\r
+\r
+ retval = call_function_tail(func, args);\r
+\r
+ exit:\r
+ /* args gets consumed in call_function_tail */\r
+ Py_XDECREF(func);\r
+\r
+ return retval;\r
+}\r
+\r
+PyObject *\r
+_PyObject_CallMethod_SizeT(PyObject *o, char *name, char *format, ...)\r
+{\r
+ va_list va;\r
+ PyObject *args;\r
+ PyObject *func = NULL;\r
+ PyObject *retval = NULL;\r
+\r
+ if (o == NULL || name == NULL)\r
+ return null_error();\r
+\r
+ func = PyObject_GetAttrString(o, name);\r
+ if (func == NULL)\r
+ return NULL;\r
+\r
+ if (!PyCallable_Check(func)) {\r
+ type_error("attribute of type '%.200s' is not callable", func);\r
+ goto exit;\r
+ }\r
+\r
+ if (format && *format) {\r
+ va_start(va, format);\r
+ args = _Py_VaBuildValue_SizeT(format, va);\r
+ va_end(va);\r
+ }\r
+ else\r
+ args = PyTuple_New(0);\r
+\r
+ retval = call_function_tail(func, args);\r
+\r
+ exit:\r
+ /* args gets consumed in call_function_tail */\r
+ Py_XDECREF(func);\r
+\r
+ return retval;\r
+}\r
+\r
+\r
+static PyObject *\r
+objargs_mktuple(va_list va)\r
+{\r
+ int i, n = 0;\r
+ va_list countva;\r
+ PyObject *result, *tmp;\r
+\r
+#ifdef VA_LIST_IS_ARRAY\r
+ memcpy(countva, va, sizeof(va_list));\r
+#else\r
+#ifdef __va_copy\r
+ __va_copy(countva, va);\r
+#else\r
+ countva = va;\r
+#endif\r
+#endif\r
+\r
+ while (((PyObject *)va_arg(countva, PyObject *)) != NULL)\r
+ ++n;\r
+ result = PyTuple_New(n);\r
+ if (result != NULL && n > 0) {\r
+ for (i = 0; i < n; ++i) {\r
+ tmp = (PyObject *)va_arg(va, PyObject *);\r
+ PyTuple_SET_ITEM(result, i, tmp);\r
+ Py_INCREF(tmp);\r
+ }\r
+ }\r
+ return result;\r
+}\r
+\r
+PyObject *\r
+PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)\r
+{\r
+ PyObject *args, *tmp;\r
+ va_list vargs;\r
+\r
+ if (callable == NULL || name == NULL)\r
+ return null_error();\r
+\r
+ callable = PyObject_GetAttr(callable, name);\r
+ if (callable == NULL)\r
+ return NULL;\r
+\r
+ /* count the args */\r
+ va_start(vargs, name);\r
+ args = objargs_mktuple(vargs);\r
+ va_end(vargs);\r
+ if (args == NULL) {\r
+ Py_DECREF(callable);\r
+ return NULL;\r
+ }\r
+ tmp = PyObject_Call(callable, args, NULL);\r
+ Py_DECREF(args);\r
+ Py_DECREF(callable);\r
+\r
+ return tmp;\r
+}\r
+\r
+PyObject *\r
+PyObject_CallFunctionObjArgs(PyObject *callable, ...)\r
+{\r
+ PyObject *args, *tmp;\r
+ va_list vargs;\r
+\r
+ if (callable == NULL)\r
+ return null_error();\r
+\r
+ /* count the args */\r
+ va_start(vargs, callable);\r
+ args = objargs_mktuple(vargs);\r
+ va_end(vargs);\r
+ if (args == NULL)\r
+ return NULL;\r
+ tmp = PyObject_Call(callable, args, NULL);\r
+ Py_DECREF(args);\r
+\r
+ return tmp;\r
+}\r
+\r
+\r
+/* isinstance(), issubclass() */\r
+\r
+/* abstract_get_bases() has logically 4 return states, with a sort of 0th\r
+ * state that will almost never happen.\r
+ *\r
+ * 0. creating the __bases__ static string could get a MemoryError\r
+ * 1. getattr(cls, '__bases__') could raise an AttributeError\r
+ * 2. getattr(cls, '__bases__') could raise some other exception\r
+ * 3. getattr(cls, '__bases__') could return a tuple\r
+ * 4. getattr(cls, '__bases__') could return something other than a tuple\r
+ *\r
+ * Only state #3 is a non-error state and only it returns a non-NULL object\r
+ * (it returns the retrieved tuple).\r
+ *\r
+ * Any raised AttributeErrors are masked by clearing the exception and\r
+ * returning NULL. If an object other than a tuple comes out of __bases__,\r
+ * then again, the return value is NULL. So yes, these two situations\r
+ * produce exactly the same results: NULL is returned and no error is set.\r
+ *\r
+ * If some exception other than AttributeError is raised, then NULL is also\r
+ * returned, but the exception is not cleared. That's because we want the\r
+ * exception to be propagated along.\r
+ *\r
+ * Callers are expected to test for PyErr_Occurred() when the return value\r
+ * is NULL to decide whether a valid exception should be propagated or not.\r
+ * When there's no exception to propagate, it's customary for the caller to\r
+ * set a TypeError.\r
+ */\r
+static PyObject *\r
+abstract_get_bases(PyObject *cls)\r
+{\r
+ static PyObject *__bases__ = NULL;\r
+ PyObject *bases;\r
+\r
+ if (__bases__ == NULL) {\r
+ __bases__ = PyString_InternFromString("__bases__");\r
+ if (__bases__ == NULL)\r
+ return NULL;\r
+ }\r
+ bases = PyObject_GetAttr(cls, __bases__);\r
+ if (bases == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ PyErr_Clear();\r
+ return NULL;\r
+ }\r
+ if (!PyTuple_Check(bases)) {\r
+ Py_DECREF(bases);\r
+ return NULL;\r
+ }\r
+ return bases;\r
+}\r
+\r
+\r
+static int\r
+abstract_issubclass(PyObject *derived, PyObject *cls)\r
+{\r
+ PyObject *bases = NULL;\r
+ Py_ssize_t i, n;\r
+ int r = 0;\r
+\r
+ while (1) {\r
+ if (derived == cls)\r
+ return 1;\r
+ bases = abstract_get_bases(derived);\r
+ if (bases == NULL) {\r
+ if (PyErr_Occurred())\r
+ return -1;\r
+ return 0;\r
+ }\r
+ n = PyTuple_GET_SIZE(bases);\r
+ if (n == 0) {\r
+ Py_DECREF(bases);\r
+ return 0;\r
+ }\r
+ /* Avoid recursivity in the single inheritance case */\r
+ if (n == 1) {\r
+ derived = PyTuple_GET_ITEM(bases, 0);\r
+ Py_DECREF(bases);\r
+ continue;\r
+ }\r
+ for (i = 0; i < n; i++) {\r
+ r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls);\r
+ if (r != 0)\r
+ break;\r
+ }\r
+ Py_DECREF(bases);\r
+ return r;\r
+ }\r
+}\r
+\r
+static int\r
+check_class(PyObject *cls, const char *error)\r
+{\r
+ PyObject *bases = abstract_get_bases(cls);\r
+ if (bases == NULL) {\r
+ /* Do not mask errors. */\r
+ if (!PyErr_Occurred())\r
+ PyErr_SetString(PyExc_TypeError, error);\r
+ return 0;\r
+ }\r
+ Py_DECREF(bases);\r
+ return -1;\r
+}\r
+\r
+static int\r
+recursive_isinstance(PyObject *inst, PyObject *cls)\r
+{\r
+ PyObject *icls;\r
+ static PyObject *__class__ = NULL;\r
+ int retval = 0;\r
+\r
+ if (__class__ == NULL) {\r
+ __class__ = PyString_InternFromString("__class__");\r
+ if (__class__ == NULL)\r
+ return -1;\r
+ }\r
+\r
+ if (PyClass_Check(cls) && PyInstance_Check(inst)) {\r
+ PyObject *inclass =\r
+ (PyObject*)((PyInstanceObject*)inst)->in_class;\r
+ retval = PyClass_IsSubclass(inclass, cls);\r
+ }\r
+ else if (PyType_Check(cls)) {\r
+ retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);\r
+ if (retval == 0) {\r
+ PyObject *c = PyObject_GetAttr(inst, __class__);\r
+ if (c == NULL) {\r
+ PyErr_Clear();\r
+ }\r
+ else {\r
+ if (c != (PyObject *)(inst->ob_type) &&\r
+ PyType_Check(c))\r
+ retval = PyType_IsSubtype(\r
+ (PyTypeObject *)c,\r
+ (PyTypeObject *)cls);\r
+ Py_DECREF(c);\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ if (!check_class(cls,\r
+ "isinstance() arg 2 must be a class, type,"\r
+ " or tuple of classes and types"))\r
+ return -1;\r
+ icls = PyObject_GetAttr(inst, __class__);\r
+ if (icls == NULL) {\r
+ PyErr_Clear();\r
+ retval = 0;\r
+ }\r
+ else {\r
+ retval = abstract_issubclass(icls, cls);\r
+ Py_DECREF(icls);\r
+ }\r
+ }\r
+\r
+ return retval;\r
+}\r
+\r
+int\r
+PyObject_IsInstance(PyObject *inst, PyObject *cls)\r
+{\r
+ static PyObject *name = NULL;\r
+\r
+ /* Quick test for an exact match */\r
+ if (Py_TYPE(inst) == (PyTypeObject *)cls)\r
+ return 1;\r
+\r
+ if (PyTuple_Check(cls)) {\r
+ Py_ssize_t i;\r
+ Py_ssize_t n;\r
+ int r = 0;\r
+\r
+ if (Py_EnterRecursiveCall(" in __instancecheck__"))\r
+ return -1;\r
+ n = PyTuple_GET_SIZE(cls);\r
+ for (i = 0; i < n; ++i) {\r
+ PyObject *item = PyTuple_GET_ITEM(cls, i);\r
+ r = PyObject_IsInstance(inst, item);\r
+ if (r != 0)\r
+ /* either found it, or got an error */\r
+ break;\r
+ }\r
+ Py_LeaveRecursiveCall();\r
+ return r;\r
+ }\r
+\r
+ if (!(PyClass_Check(cls) || PyInstance_Check(cls))) {\r
+ PyObject *checker;\r
+ checker = _PyObject_LookupSpecial(cls, "__instancecheck__", &name);\r
+ if (checker != NULL) {\r
+ PyObject *res;\r
+ int ok = -1;\r
+ if (Py_EnterRecursiveCall(" in __instancecheck__")) {\r
+ Py_DECREF(checker);\r
+ return ok;\r
+ }\r
+ res = PyObject_CallFunctionObjArgs(checker, inst, NULL);\r
+ Py_LeaveRecursiveCall();\r
+ Py_DECREF(checker);\r
+ if (res != NULL) {\r
+ ok = PyObject_IsTrue(res);\r
+ Py_DECREF(res);\r
+ }\r
+ return ok;\r
+ }\r
+ else if (PyErr_Occurred())\r
+ return -1;\r
+ }\r
+ return recursive_isinstance(inst, cls);\r
+}\r
+\r
+static int\r
+recursive_issubclass(PyObject *derived, PyObject *cls)\r
+{\r
+ int retval;\r
+\r
+ if (PyType_Check(cls) && PyType_Check(derived)) {\r
+ /* Fast path (non-recursive) */\r
+ return PyType_IsSubtype(\r
+ (PyTypeObject *)derived, (PyTypeObject *)cls);\r
+ }\r
+ if (!PyClass_Check(derived) || !PyClass_Check(cls)) {\r
+ if (!check_class(derived,\r
+ "issubclass() arg 1 must be a class"))\r
+ return -1;\r
+\r
+ if (!check_class(cls,\r
+ "issubclass() arg 2 must be a class"\r
+ " or tuple of classes"))\r
+ return -1;\r
+ retval = abstract_issubclass(derived, cls);\r
+ }\r
+ else {\r
+ /* shortcut */\r
+ if (!(retval = (derived == cls)))\r
+ retval = PyClass_IsSubclass(derived, cls);\r
+ }\r
+\r
+ return retval;\r
+}\r
+\r
+int\r
+PyObject_IsSubclass(PyObject *derived, PyObject *cls)\r
+{\r
+ static PyObject *name = NULL;\r
+\r
+ if (PyTuple_Check(cls)) {\r
+ Py_ssize_t i;\r
+ Py_ssize_t n;\r
+ int r = 0;\r
+\r
+ if (Py_EnterRecursiveCall(" in __subclasscheck__"))\r
+ return -1;\r
+ n = PyTuple_GET_SIZE(cls);\r
+ for (i = 0; i < n; ++i) {\r
+ PyObject *item = PyTuple_GET_ITEM(cls, i);\r
+ r = PyObject_IsSubclass(derived, item);\r
+ if (r != 0)\r
+ /* either found it, or got an error */\r
+ break;\r
+ }\r
+ Py_LeaveRecursiveCall();\r
+ return r;\r
+ }\r
+ if (!(PyClass_Check(cls) || PyInstance_Check(cls))) {\r
+ PyObject *checker;\r
+ checker = _PyObject_LookupSpecial(cls, "__subclasscheck__", &name);\r
+ if (checker != NULL) {\r
+ PyObject *res;\r
+ int ok = -1;\r
+ if (Py_EnterRecursiveCall(" in __subclasscheck__")) {\r
+ Py_DECREF(checker);\r
+ return ok;\r
+ }\r
+ res = PyObject_CallFunctionObjArgs(checker, derived, NULL);\r
+ Py_LeaveRecursiveCall();\r
+ Py_DECREF(checker);\r
+ if (res != NULL) {\r
+ ok = PyObject_IsTrue(res);\r
+ Py_DECREF(res);\r
+ }\r
+ return ok;\r
+ }\r
+ else if (PyErr_Occurred()) {\r
+ return -1;\r
+ }\r
+ }\r
+ return recursive_issubclass(derived, cls);\r
+}\r
+\r
+int\r
+_PyObject_RealIsInstance(PyObject *inst, PyObject *cls)\r
+{\r
+ return recursive_isinstance(inst, cls);\r
+}\r
+\r
+int\r
+_PyObject_RealIsSubclass(PyObject *derived, PyObject *cls)\r
+{\r
+ return recursive_issubclass(derived, cls);\r
+}\r
+\r
+\r
+PyObject *\r
+PyObject_GetIter(PyObject *o)\r
+{\r
+ PyTypeObject *t = o->ob_type;\r
+ getiterfunc f = NULL;\r
+ if (PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER))\r
+ f = t->tp_iter;\r
+ if (f == NULL) {\r
+ if (PySequence_Check(o))\r
+ return PySeqIter_New(o);\r
+ return type_error("'%.200s' object is not iterable", o);\r
+ }\r
+ else {\r
+ PyObject *res = (*f)(o);\r
+ if (res != NULL && !PyIter_Check(res)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "iter() returned non-iterator "\r
+ "of type '%.100s'",\r
+ res->ob_type->tp_name);\r
+ Py_DECREF(res);\r
+ res = NULL;\r
+ }\r
+ return res;\r
+ }\r
+}\r
+\r
+/* Return next item.\r
+ * If an error occurs, return NULL. PyErr_Occurred() will be true.\r
+ * If the iteration terminates normally, return NULL and clear the\r
+ * PyExc_StopIteration exception (if it was set). PyErr_Occurred()\r
+ * will be false.\r
+ * Else return the next object. PyErr_Occurred() will be false.\r
+ */\r
+PyObject *\r
+PyIter_Next(PyObject *iter)\r
+{\r
+ PyObject *result;\r
+ result = (*iter->ob_type->tp_iternext)(iter);\r
+ if (result == NULL &&\r
+ PyErr_Occurred() &&\r
+ PyErr_ExceptionMatches(PyExc_StopIteration))\r
+ PyErr_Clear();\r
+ return result;\r
+}\r
--- /dev/null
+/* Boolean type, a subtype of int */\r
+\r
+#include "Python.h"\r
+\r
+/* We need to define bool_print to override int_print */\r
+\r
+static int\r
+bool_print(PyBoolObject *self, FILE *fp, int flags)\r
+{\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fputs(self->ob_ival == 0 ? "False" : "True", fp);\r
+ Py_END_ALLOW_THREADS\r
+ return 0;\r
+}\r
+\r
+/* We define bool_repr to return "False" or "True" */\r
+\r
+static PyObject *false_str = NULL;\r
+static PyObject *true_str = NULL;\r
+\r
+static PyObject *\r
+bool_repr(PyBoolObject *self)\r
+{\r
+ PyObject *s;\r
+\r
+ if (self->ob_ival)\r
+ s = true_str ? true_str :\r
+ (true_str = PyString_InternFromString("True"));\r
+ else\r
+ s = false_str ? false_str :\r
+ (false_str = PyString_InternFromString("False"));\r
+ Py_XINCREF(s);\r
+ return s;\r
+}\r
+\r
+/* Function to return a bool from a C long */\r
+\r
+PyObject *PyBool_FromLong(long ok)\r
+{\r
+ PyObject *result;\r
+\r
+ if (ok)\r
+ result = Py_True;\r
+ else\r
+ result = Py_False;\r
+ Py_INCREF(result);\r
+ return result;\r
+}\r
+\r
+/* We define bool_new to always return either Py_True or Py_False */\r
+\r
+static PyObject *\r
+bool_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ static char *kwlist[] = {"x", 0};\r
+ PyObject *x = Py_False;\r
+ long ok;\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:bool", kwlist, &x))\r
+ return NULL;\r
+ ok = PyObject_IsTrue(x);\r
+ if (ok < 0)\r
+ return NULL;\r
+ return PyBool_FromLong(ok);\r
+}\r
+\r
+/* Arithmetic operations redefined to return bool if both args are bool. */\r
+\r
+static PyObject *\r
+bool_and(PyObject *a, PyObject *b)\r
+{\r
+ if (!PyBool_Check(a) || !PyBool_Check(b))\r
+ return PyInt_Type.tp_as_number->nb_and(a, b);\r
+ return PyBool_FromLong(\r
+ ((PyBoolObject *)a)->ob_ival & ((PyBoolObject *)b)->ob_ival);\r
+}\r
+\r
+static PyObject *\r
+bool_or(PyObject *a, PyObject *b)\r
+{\r
+ if (!PyBool_Check(a) || !PyBool_Check(b))\r
+ return PyInt_Type.tp_as_number->nb_or(a, b);\r
+ return PyBool_FromLong(\r
+ ((PyBoolObject *)a)->ob_ival | ((PyBoolObject *)b)->ob_ival);\r
+}\r
+\r
+static PyObject *\r
+bool_xor(PyObject *a, PyObject *b)\r
+{\r
+ if (!PyBool_Check(a) || !PyBool_Check(b))\r
+ return PyInt_Type.tp_as_number->nb_xor(a, b);\r
+ return PyBool_FromLong(\r
+ ((PyBoolObject *)a)->ob_ival ^ ((PyBoolObject *)b)->ob_ival);\r
+}\r
+\r
+/* Doc string */\r
+\r
+PyDoc_STRVAR(bool_doc,\r
+"bool(x) -> bool\n\\r
+\n\\r
+Returns True when the argument x is true, False otherwise.\n\\r
+The builtins True and False are the only two instances of the class bool.\n\\r
+The class bool is a subclass of the class int, and cannot be subclassed.");\r
+\r
+/* Arithmetic methods -- only so we can override &, |, ^. */\r
+\r
+static PyNumberMethods bool_as_number = {\r
+ 0, /* nb_add */\r
+ 0, /* nb_subtract */\r
+ 0, /* nb_multiply */\r
+ 0, /* nb_divide */\r
+ 0, /* nb_remainder */\r
+ 0, /* nb_divmod */\r
+ 0, /* nb_power */\r
+ 0, /* nb_negative */\r
+ 0, /* nb_positive */\r
+ 0, /* nb_absolute */\r
+ 0, /* nb_nonzero */\r
+ 0, /* nb_invert */\r
+ 0, /* nb_lshift */\r
+ 0, /* nb_rshift */\r
+ bool_and, /* nb_and */\r
+ bool_xor, /* nb_xor */\r
+ bool_or, /* nb_or */\r
+ 0, /* nb_coerce */\r
+ 0, /* nb_int */\r
+ 0, /* nb_long */\r
+ 0, /* nb_float */\r
+ 0, /* nb_oct */\r
+ 0, /* nb_hex */\r
+ 0, /* nb_inplace_add */\r
+ 0, /* nb_inplace_subtract */\r
+ 0, /* nb_inplace_multiply */\r
+ 0, /* nb_inplace_divide */\r
+ 0, /* nb_inplace_remainder */\r
+ 0, /* nb_inplace_power */\r
+ 0, /* nb_inplace_lshift */\r
+ 0, /* nb_inplace_rshift */\r
+ 0, /* nb_inplace_and */\r
+ 0, /* nb_inplace_xor */\r
+ 0, /* nb_inplace_or */\r
+ 0, /* nb_floor_divide */\r
+ 0, /* nb_true_divide */\r
+ 0, /* nb_inplace_floor_divide */\r
+ 0, /* nb_inplace_true_divide */\r
+};\r
+\r
+/* The type object for bool. Note that this cannot be subclassed! */\r
+\r
+PyTypeObject PyBool_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "bool",\r
+ sizeof(PyIntObject),\r
+ 0,\r
+ 0, /* tp_dealloc */\r
+ (printfunc)bool_print, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)bool_repr, /* tp_repr */\r
+ &bool_as_number, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ (reprfunc)bool_repr, /* tp_str */\r
+ 0, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */\r
+ bool_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ &PyInt_Type, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ bool_new, /* tp_new */\r
+};\r
+\r
+/* The objects representing bool values False and True */\r
+\r
+/* Named Zero for link-level compatibility */\r
+PyIntObject _Py_ZeroStruct = {\r
+ PyObject_HEAD_INIT(&PyBool_Type)\r
+ 0\r
+};\r
+\r
+PyIntObject _Py_TrueStruct = {\r
+ PyObject_HEAD_INIT(&PyBool_Type)\r
+ 1\r
+};\r
--- /dev/null
+\r
+/* Buffer object implementation */\r
+\r
+#include "Python.h"\r
+\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyObject *b_base;\r
+ void *b_ptr;\r
+ Py_ssize_t b_size;\r
+ Py_ssize_t b_offset;\r
+ int b_readonly;\r
+ long b_hash;\r
+} PyBufferObject;\r
+\r
+\r
+enum buffer_t {\r
+ READ_BUFFER,\r
+ WRITE_BUFFER,\r
+ CHAR_BUFFER,\r
+ ANY_BUFFER\r
+};\r
+\r
+static int\r
+get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,\r
+ enum buffer_t buffer_type)\r
+{\r
+ if (self->b_base == NULL) {\r
+ assert (ptr != NULL);\r
+ *ptr = self->b_ptr;\r
+ *size = self->b_size;\r
+ }\r
+ else {\r
+ Py_ssize_t count, offset;\r
+ readbufferproc proc = 0;\r
+ PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;\r
+ if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "single-segment buffer object expected");\r
+ return 0;\r
+ }\r
+ if ((buffer_type == READ_BUFFER) ||\r
+ ((buffer_type == ANY_BUFFER) && self->b_readonly))\r
+ proc = bp->bf_getreadbuffer;\r
+ else if ((buffer_type == WRITE_BUFFER) ||\r
+ (buffer_type == ANY_BUFFER))\r
+ proc = (readbufferproc)bp->bf_getwritebuffer;\r
+ else if (buffer_type == CHAR_BUFFER) {\r
+ if (!PyType_HasFeature(self->ob_type,\r
+ Py_TPFLAGS_HAVE_GETCHARBUFFER)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");\r
+ return 0;\r
+ }\r
+ proc = (readbufferproc)bp->bf_getcharbuffer;\r
+ }\r
+ if (!proc) {\r
+ char *buffer_type_name;\r
+ switch (buffer_type) {\r
+ case READ_BUFFER:\r
+ buffer_type_name = "read";\r
+ break;\r
+ case WRITE_BUFFER:\r
+ buffer_type_name = "write";\r
+ break;\r
+ case CHAR_BUFFER:\r
+ buffer_type_name = "char";\r
+ break;\r
+ default:\r
+ buffer_type_name = "no";\r
+ break;\r
+ }\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s buffer type not available",\r
+ buffer_type_name);\r
+ return 0;\r
+ }\r
+ if ((count = (*proc)(self->b_base, 0, ptr)) < 0)\r
+ return 0;\r
+ /* apply constraints to the start/end */\r
+ if (self->b_offset > count)\r
+ offset = count;\r
+ else\r
+ offset = self->b_offset;\r
+ *(char **)ptr = *(char **)ptr + offset;\r
+ if (self->b_size == Py_END_OF_BUFFER)\r
+ *size = count;\r
+ else\r
+ *size = self->b_size;\r
+ if (*size > count - offset)\r
+ *size = count - offset;\r
+ }\r
+ return 1;\r
+}\r
+\r
+\r
+static PyObject *\r
+buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,\r
+ int readonly)\r
+{\r
+ PyBufferObject * b;\r
+\r
+ if (size < 0 && size != Py_END_OF_BUFFER) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "size must be zero or positive");\r
+ return NULL;\r
+ }\r
+ if (offset < 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "offset must be zero or positive");\r
+ return NULL;\r
+ }\r
+\r
+ b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);\r
+ if ( b == NULL )\r
+ return NULL;\r
+\r
+ Py_XINCREF(base);\r
+ b->b_base = base;\r
+ b->b_ptr = ptr;\r
+ b->b_size = size;\r
+ b->b_offset = offset;\r
+ b->b_readonly = readonly;\r
+ b->b_hash = -1;\r
+\r
+ return (PyObject *) b;\r
+}\r
+\r
+static PyObject *\r
+buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)\r
+{\r
+ if (offset < 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "offset must be zero or positive");\r
+ return NULL;\r
+ }\r
+ if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {\r
+ /* another buffer, refer to the base object */\r
+ PyBufferObject *b = (PyBufferObject *)base;\r
+ if (b->b_size != Py_END_OF_BUFFER) {\r
+ Py_ssize_t base_size = b->b_size - offset;\r
+ if (base_size < 0)\r
+ base_size = 0;\r
+ if (size == Py_END_OF_BUFFER || size > base_size)\r
+ size = base_size;\r
+ }\r
+ offset += b->b_offset;\r
+ base = b->b_base;\r
+ }\r
+ return buffer_from_memory(base, size, offset, NULL, readonly);\r
+}\r
+\r
+\r
+PyObject *\r
+PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)\r
+{\r
+ PyBufferProcs *pb = base->ob_type->tp_as_buffer;\r
+\r
+ if ( pb == NULL ||\r
+ pb->bf_getreadbuffer == NULL ||\r
+ pb->bf_getsegcount == NULL )\r
+ {\r
+ PyErr_SetString(PyExc_TypeError, "buffer object expected");\r
+ return NULL;\r
+ }\r
+\r
+ return buffer_from_object(base, size, offset, 1);\r
+}\r
+\r
+PyObject *\r
+PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)\r
+{\r
+ PyBufferProcs *pb = base->ob_type->tp_as_buffer;\r
+\r
+ if ( pb == NULL ||\r
+ pb->bf_getwritebuffer == NULL ||\r
+ pb->bf_getsegcount == NULL )\r
+ {\r
+ PyErr_SetString(PyExc_TypeError, "buffer object expected");\r
+ return NULL;\r
+ }\r
+\r
+ return buffer_from_object(base, size, offset, 0);\r
+}\r
+\r
+PyObject *\r
+PyBuffer_FromMemory(void *ptr, Py_ssize_t size)\r
+{\r
+ return buffer_from_memory(NULL, size, 0, ptr, 1);\r
+}\r
+\r
+PyObject *\r
+PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)\r
+{\r
+ return buffer_from_memory(NULL, size, 0, ptr, 0);\r
+}\r
+\r
+PyObject *\r
+PyBuffer_New(Py_ssize_t size)\r
+{\r
+ PyObject *o;\r
+ PyBufferObject * b;\r
+\r
+ if (size < 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "size must be zero or positive");\r
+ return NULL;\r
+ }\r
+ if (sizeof(*b) > PY_SSIZE_T_MAX - size) {\r
+ /* unlikely */\r
+ return PyErr_NoMemory();\r
+ }\r
+ /* Inline PyObject_New */\r
+ o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);\r
+ if ( o == NULL )\r
+ return PyErr_NoMemory();\r
+ b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);\r
+\r
+ b->b_base = NULL;\r
+ b->b_ptr = (void *)(b + 1);\r
+ b->b_size = size;\r
+ b->b_offset = 0;\r
+ b->b_readonly = 0;\r
+ b->b_hash = -1;\r
+\r
+ return o;\r
+}\r
+\r
+/* Methods */\r
+\r
+static PyObject *\r
+buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)\r
+{\r
+ PyObject *ob;\r
+ Py_ssize_t offset = 0;\r
+ Py_ssize_t size = Py_END_OF_BUFFER;\r
+\r
+ if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)\r
+ return NULL;\r
+\r
+ if (!_PyArg_NoKeywords("buffer()", kw))\r
+ return NULL;\r
+\r
+ if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))\r
+ return NULL;\r
+ return PyBuffer_FromObject(ob, offset, size);\r
+}\r
+\r
+PyDoc_STRVAR(buffer_doc,\r
+"buffer(object [, offset[, size]])\n\\r
+\n\\r
+Create a new buffer object which references the given object.\n\\r
+The buffer will reference a slice of the target object from the\n\\r
+start of the object (or at the specified offset). The slice will\n\\r
+extend to the end of the target object (or with the specified size).");\r
+\r
+\r
+static void\r
+buffer_dealloc(PyBufferObject *self)\r
+{\r
+ Py_XDECREF(self->b_base);\r
+ PyObject_DEL(self);\r
+}\r
+\r
+static int\r
+buffer_compare(PyBufferObject *self, PyBufferObject *other)\r
+{\r
+ void *p1, *p2;\r
+ Py_ssize_t len_self, len_other, min_len;\r
+ int cmp;\r
+\r
+ if (!get_buf(self, &p1, &len_self, ANY_BUFFER))\r
+ return -1;\r
+ if (!get_buf(other, &p2, &len_other, ANY_BUFFER))\r
+ return -1;\r
+ min_len = (len_self < len_other) ? len_self : len_other;\r
+ if (min_len > 0) {\r
+ cmp = memcmp(p1, p2, min_len);\r
+ if (cmp != 0)\r
+ return cmp < 0 ? -1 : 1;\r
+ }\r
+ return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;\r
+}\r
+\r
+static PyObject *\r
+buffer_repr(PyBufferObject *self)\r
+{\r
+ const char *status = self->b_readonly ? "read-only" : "read-write";\r
+\r
+ if ( self->b_base == NULL )\r
+ return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",\r
+ status,\r
+ self->b_ptr,\r
+ self->b_size,\r
+ self);\r
+ else\r
+ return PyString_FromFormat(\r
+ "<%s buffer for %p, size %zd, offset %zd at %p>",\r
+ status,\r
+ self->b_base,\r
+ self->b_size,\r
+ self->b_offset,\r
+ self);\r
+}\r
+\r
+static long\r
+buffer_hash(PyBufferObject *self)\r
+{\r
+ void *ptr;\r
+ Py_ssize_t size;\r
+ register Py_ssize_t len;\r
+ register unsigned char *p;\r
+ register long x;\r
+\r
+ if ( self->b_hash != -1 )\r
+ return self->b_hash;\r
+\r
+ /* XXX potential bugs here, a readonly buffer does not imply that the\r
+ * underlying memory is immutable. b_readonly is a necessary but not\r
+ * sufficient condition for a buffer to be hashable. Perhaps it would\r
+ * be better to only allow hashing if the underlying object is known to\r
+ * be immutable (e.g. PyString_Check() is true). Another idea would\r
+ * be to call tp_hash on the underlying object and see if it raises\r
+ * an error. */\r
+ if ( !self->b_readonly )\r
+ {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "writable buffers are not hashable");\r
+ return -1;\r
+ }\r
+\r
+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))\r
+ return -1;\r
+ p = (unsigned char *) ptr;\r
+ len = size;\r
+ /*\r
+ We make the hash of the empty buffer be 0, rather than using\r
+ (prefix ^ suffix), since this slightly obfuscates the hash secret\r
+ */\r
+ if (len == 0) {\r
+ self->b_hash = 0;\r
+ return 0;\r
+ }\r
+ x = _Py_HashSecret.prefix;\r
+ x ^= *p << 7;\r
+ while (--len >= 0)\r
+ x = (1000003*x) ^ *p++;\r
+ x ^= size;\r
+ x ^= _Py_HashSecret.suffix;\r
+ if (x == -1)\r
+ x = -2;\r
+ self->b_hash = x;\r
+ return x;\r
+}\r
+\r
+static PyObject *\r
+buffer_str(PyBufferObject *self)\r
+{\r
+ void *ptr;\r
+ Py_ssize_t size;\r
+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))\r
+ return NULL;\r
+ return PyString_FromStringAndSize((const char *)ptr, size);\r
+}\r
+\r
+/* Sequence methods */\r
+\r
+static Py_ssize_t\r
+buffer_length(PyBufferObject *self)\r
+{\r
+ void *ptr;\r
+ Py_ssize_t size;\r
+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))\r
+ return -1;\r
+ return size;\r
+}\r
+\r
+static PyObject *\r
+buffer_concat(PyBufferObject *self, PyObject *other)\r
+{\r
+ PyBufferProcs *pb = other->ob_type->tp_as_buffer;\r
+ void *ptr1, *ptr2;\r
+ char *p;\r
+ PyObject *ob;\r
+ Py_ssize_t size, count;\r
+\r
+ if ( pb == NULL ||\r
+ pb->bf_getreadbuffer == NULL ||\r
+ pb->bf_getsegcount == NULL )\r
+ {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ if ( (*pb->bf_getsegcount)(other, NULL) != 1 )\r
+ {\r
+ /* ### use a different exception type/message? */\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "single-segment buffer object expected");\r
+ return NULL;\r
+ }\r
+\r
+ if (!get_buf(self, &ptr1, &size, ANY_BUFFER))\r
+ return NULL;\r
+\r
+ /* optimize special case */\r
+ if ( size == 0 )\r
+ {\r
+ Py_INCREF(other);\r
+ return other;\r
+ }\r
+\r
+ if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )\r
+ return NULL;\r
+\r
+ assert(count <= PY_SIZE_MAX - size);\r
+\r
+ ob = PyString_FromStringAndSize(NULL, size + count);\r
+ if ( ob == NULL )\r
+ return NULL;\r
+ p = PyString_AS_STRING(ob);\r
+ memcpy(p, ptr1, size);\r
+ memcpy(p + size, ptr2, count);\r
+\r
+ /* there is an extra byte in the string object, so this is safe */\r
+ p[size + count] = '\0';\r
+\r
+ return ob;\r
+}\r
+\r
+static PyObject *\r
+buffer_repeat(PyBufferObject *self, Py_ssize_t count)\r
+{\r
+ PyObject *ob;\r
+ register char *p;\r
+ void *ptr;\r
+ Py_ssize_t size;\r
+\r
+ if ( count < 0 )\r
+ count = 0;\r
+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))\r
+ return NULL;\r
+ if (count > PY_SSIZE_T_MAX / size) {\r
+ PyErr_SetString(PyExc_MemoryError, "result too large");\r
+ return NULL;\r
+ }\r
+ ob = PyString_FromStringAndSize(NULL, size * count);\r
+ if ( ob == NULL )\r
+ return NULL;\r
+\r
+ p = PyString_AS_STRING(ob);\r
+ while ( count-- )\r
+ {\r
+ memcpy(p, ptr, size);\r
+ p += size;\r
+ }\r
+\r
+ /* there is an extra byte in the string object, so this is safe */\r
+ *p = '\0';\r
+\r
+ return ob;\r
+}\r
+\r
+static PyObject *\r
+buffer_item(PyBufferObject *self, Py_ssize_t idx)\r
+{\r
+ void *ptr;\r
+ Py_ssize_t size;\r
+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))\r
+ return NULL;\r
+ if ( idx < 0 || idx >= size ) {\r
+ PyErr_SetString(PyExc_IndexError, "buffer index out of range");\r
+ return NULL;\r
+ }\r
+ return PyString_FromStringAndSize((char *)ptr + idx, 1);\r
+}\r
+\r
+static PyObject *\r
+buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)\r
+{\r
+ void *ptr;\r
+ Py_ssize_t size;\r
+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))\r
+ return NULL;\r
+ if ( left < 0 )\r
+ left = 0;\r
+ if ( right < 0 )\r
+ right = 0;\r
+ if ( right > size )\r
+ right = size;\r
+ if ( right < left )\r
+ right = left;\r
+ return PyString_FromStringAndSize((char *)ptr + left,\r
+ right - left);\r
+}\r
+\r
+static PyObject *\r
+buffer_subscript(PyBufferObject *self, PyObject *item)\r
+{\r
+ void *p;\r
+ Py_ssize_t size;\r
+\r
+ if (!get_buf(self, &p, &size, ANY_BUFFER))\r
+ return NULL;\r
+ if (PyIndex_Check(item)) {\r
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ if (i < 0)\r
+ i += size;\r
+ return buffer_item(self, i);\r
+ }\r
+ else if (PySlice_Check(item)) {\r
+ Py_ssize_t start, stop, step, slicelength, cur, i;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject*)item, size,\r
+ &start, &stop, &step, &slicelength) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ if (slicelength <= 0)\r
+ return PyString_FromStringAndSize("", 0);\r
+ else if (step == 1)\r
+ return PyString_FromStringAndSize((char *)p + start,\r
+ stop - start);\r
+ else {\r
+ PyObject *result;\r
+ char *source_buf = (char *)p;\r
+ char *result_buf = (char *)PyMem_Malloc(slicelength);\r
+\r
+ if (result_buf == NULL)\r
+ return PyErr_NoMemory();\r
+\r
+ for (cur = start, i = 0; i < slicelength;\r
+ cur += step, i++) {\r
+ result_buf[i] = source_buf[cur];\r
+ }\r
+\r
+ result = PyString_FromStringAndSize(result_buf,\r
+ slicelength);\r
+ PyMem_Free(result_buf);\r
+ return result;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "sequence index must be integer");\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static int\r
+buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)\r
+{\r
+ PyBufferProcs *pb;\r
+ void *ptr1, *ptr2;\r
+ Py_ssize_t size;\r
+ Py_ssize_t count;\r
+\r
+ if ( self->b_readonly ) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "buffer is read-only");\r
+ return -1;\r
+ }\r
+\r
+ if (!get_buf(self, &ptr1, &size, ANY_BUFFER))\r
+ return -1;\r
+\r
+ if (idx < 0 || idx >= size) {\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "buffer assignment index out of range");\r
+ return -1;\r
+ }\r
+\r
+ pb = other ? other->ob_type->tp_as_buffer : NULL;\r
+ if ( pb == NULL ||\r
+ pb->bf_getreadbuffer == NULL ||\r
+ pb->bf_getsegcount == NULL )\r
+ {\r
+ PyErr_BadArgument();\r
+ return -1;\r
+ }\r
+ if ( (*pb->bf_getsegcount)(other, NULL) != 1 )\r
+ {\r
+ /* ### use a different exception type/message? */\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "single-segment buffer object expected");\r
+ return -1;\r
+ }\r
+\r
+ if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )\r
+ return -1;\r
+ if ( count != 1 ) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "right operand must be a single byte");\r
+ return -1;\r
+ }\r
+\r
+ ((char *)ptr1)[idx] = *(char *)ptr2;\r
+ return 0;\r
+}\r
+\r
+static int\r
+buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)\r
+{\r
+ PyBufferProcs *pb;\r
+ void *ptr1, *ptr2;\r
+ Py_ssize_t size;\r
+ Py_ssize_t slice_len;\r
+ Py_ssize_t count;\r
+\r
+ if ( self->b_readonly ) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "buffer is read-only");\r
+ return -1;\r
+ }\r
+\r
+ pb = other ? other->ob_type->tp_as_buffer : NULL;\r
+ if ( pb == NULL ||\r
+ pb->bf_getreadbuffer == NULL ||\r
+ pb->bf_getsegcount == NULL )\r
+ {\r
+ PyErr_BadArgument();\r
+ return -1;\r
+ }\r
+ if ( (*pb->bf_getsegcount)(other, NULL) != 1 )\r
+ {\r
+ /* ### use a different exception type/message? */\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "single-segment buffer object expected");\r
+ return -1;\r
+ }\r
+ if (!get_buf(self, &ptr1, &size, ANY_BUFFER))\r
+ return -1;\r
+ if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )\r
+ return -1;\r
+\r
+ if ( left < 0 )\r
+ left = 0;\r
+ else if ( left > size )\r
+ left = size;\r
+ if ( right < left )\r
+ right = left;\r
+ else if ( right > size )\r
+ right = size;\r
+ slice_len = right - left;\r
+\r
+ if ( count != slice_len ) {\r
+ PyErr_SetString(\r
+ PyExc_TypeError,\r
+ "right operand length must match slice length");\r
+ return -1;\r
+ }\r
+\r
+ if ( slice_len )\r
+ memcpy((char *)ptr1 + left, ptr2, slice_len);\r
+\r
+ return 0;\r
+}\r
+\r
+static int\r
+buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)\r
+{\r
+ PyBufferProcs *pb;\r
+ void *ptr1, *ptr2;\r
+ Py_ssize_t selfsize;\r
+ Py_ssize_t othersize;\r
+\r
+ if ( self->b_readonly ) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "buffer is read-only");\r
+ return -1;\r
+ }\r
+\r
+ pb = value ? value->ob_type->tp_as_buffer : NULL;\r
+ if ( pb == NULL ||\r
+ pb->bf_getreadbuffer == NULL ||\r
+ pb->bf_getsegcount == NULL )\r
+ {\r
+ PyErr_BadArgument();\r
+ return -1;\r
+ }\r
+ if ( (*pb->bf_getsegcount)(value, NULL) != 1 )\r
+ {\r
+ /* ### use a different exception type/message? */\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "single-segment buffer object expected");\r
+ return -1;\r
+ }\r
+ if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))\r
+ return -1;\r
+ if (PyIndex_Check(item)) {\r
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return -1;\r
+ if (i < 0)\r
+ i += selfsize;\r
+ return buffer_ass_item(self, i, value);\r
+ }\r
+ else if (PySlice_Check(item)) {\r
+ Py_ssize_t start, stop, step, slicelength;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,\r
+ &start, &stop, &step, &slicelength) < 0)\r
+ return -1;\r
+\r
+ if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)\r
+ return -1;\r
+\r
+ if (othersize != slicelength) {\r
+ PyErr_SetString(\r
+ PyExc_TypeError,\r
+ "right operand length must match slice length");\r
+ return -1;\r
+ }\r
+\r
+ if (slicelength == 0)\r
+ return 0;\r
+ else if (step == 1) {\r
+ memcpy((char *)ptr1 + start, ptr2, slicelength);\r
+ return 0;\r
+ }\r
+ else {\r
+ Py_ssize_t cur, i;\r
+\r
+ for (cur = start, i = 0; i < slicelength;\r
+ cur += step, i++) {\r
+ ((char *)ptr1)[cur] = ((char *)ptr2)[i];\r
+ }\r
+\r
+ return 0;\r
+ }\r
+ } else {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "buffer indices must be integers");\r
+ return -1;\r
+ }\r
+}\r
+\r
+/* Buffer methods */\r
+\r
+static Py_ssize_t\r
+buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)\r
+{\r
+ Py_ssize_t size;\r
+ if ( idx != 0 ) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent buffer segment");\r
+ return -1;\r
+ }\r
+ if (!get_buf(self, pp, &size, READ_BUFFER))\r
+ return -1;\r
+ return size;\r
+}\r
+\r
+static Py_ssize_t\r
+buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)\r
+{\r
+ Py_ssize_t size;\r
+\r
+ if ( self->b_readonly )\r
+ {\r
+ PyErr_SetString(PyExc_TypeError, "buffer is read-only");\r
+ return -1;\r
+ }\r
+\r
+ if ( idx != 0 ) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent buffer segment");\r
+ return -1;\r
+ }\r
+ if (!get_buf(self, pp, &size, WRITE_BUFFER))\r
+ return -1;\r
+ return size;\r
+}\r
+\r
+static Py_ssize_t\r
+buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)\r
+{\r
+ void *ptr;\r
+ Py_ssize_t size;\r
+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))\r
+ return -1;\r
+ if (lenp)\r
+ *lenp = size;\r
+ return 1;\r
+}\r
+\r
+static Py_ssize_t\r
+buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)\r
+{\r
+ void *ptr;\r
+ Py_ssize_t size;\r
+ if ( idx != 0 ) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent buffer segment");\r
+ return -1;\r
+ }\r
+ if (!get_buf(self, &ptr, &size, CHAR_BUFFER))\r
+ return -1;\r
+ *pp = (const char *)ptr;\r
+ return size;\r
+}\r
+\r
+static int buffer_getbuffer(PyBufferObject *self, Py_buffer *buf, int flags)\r
+{\r
+ void *ptr;\r
+ Py_ssize_t size;\r
+ if (!get_buf(self, &ptr, &size, ANY_BUFFER))\r
+ return -1;\r
+ return PyBuffer_FillInfo(buf, (PyObject*)self, ptr, size,\r
+ self->b_readonly, flags);\r
+}\r
+\r
+static PySequenceMethods buffer_as_sequence = {\r
+ (lenfunc)buffer_length, /*sq_length*/\r
+ (binaryfunc)buffer_concat, /*sq_concat*/\r
+ (ssizeargfunc)buffer_repeat, /*sq_repeat*/\r
+ (ssizeargfunc)buffer_item, /*sq_item*/\r
+ (ssizessizeargfunc)buffer_slice, /*sq_slice*/\r
+ (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/\r
+ (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/\r
+};\r
+\r
+static PyMappingMethods buffer_as_mapping = {\r
+ (lenfunc)buffer_length,\r
+ (binaryfunc)buffer_subscript,\r
+ (objobjargproc)buffer_ass_subscript,\r
+};\r
+\r
+static PyBufferProcs buffer_as_buffer = {\r
+ (readbufferproc)buffer_getreadbuf,\r
+ (writebufferproc)buffer_getwritebuf,\r
+ (segcountproc)buffer_getsegcount,\r
+ (charbufferproc)buffer_getcharbuf,\r
+ (getbufferproc)buffer_getbuffer,\r
+};\r
+\r
+PyTypeObject PyBuffer_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "buffer",\r
+ sizeof(PyBufferObject),\r
+ 0,\r
+ (destructor)buffer_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)buffer_compare, /* tp_compare */\r
+ (reprfunc)buffer_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &buffer_as_sequence, /* tp_as_sequence */\r
+ &buffer_as_mapping, /* tp_as_mapping */\r
+ (hashfunc)buffer_hash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ (reprfunc)buffer_str, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ &buffer_as_buffer, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */\r
+ buffer_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ buffer_new, /* tp_new */\r
+};\r
--- /dev/null
+/* PyBytes (bytearray) implementation */\r
+\r
+#define PY_SSIZE_T_CLEAN\r
+#include "Python.h"\r
+#include "structmember.h"\r
+#include "bytes_methods.h"\r
+\r
+char _PyByteArray_empty_string[] = "";\r
+\r
+void\r
+PyByteArray_Fini(void)\r
+{\r
+}\r
+\r
+int\r
+PyByteArray_Init(void)\r
+{\r
+ return 1;\r
+}\r
+\r
+/* end nullbytes support */\r
+\r
+/* Helpers */\r
+\r
+static int\r
+_getbytevalue(PyObject* arg, int *value)\r
+{\r
+ long face_value;\r
+\r
+ if (PyBytes_CheckExact(arg)) {\r
+ if (Py_SIZE(arg) != 1) {\r
+ PyErr_SetString(PyExc_ValueError, "string must be of size 1");\r
+ return 0;\r
+ }\r
+ *value = Py_CHARMASK(((PyBytesObject*)arg)->ob_sval[0]);\r
+ return 1;\r
+ }\r
+ else if (PyInt_Check(arg) || PyLong_Check(arg)) {\r
+ face_value = PyLong_AsLong(arg);\r
+ }\r
+ else {\r
+ PyObject *index = PyNumber_Index(arg);\r
+ if (index == NULL) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "an integer or string of size 1 is required");\r
+ return 0;\r
+ }\r
+ face_value = PyLong_AsLong(index);\r
+ Py_DECREF(index);\r
+ }\r
+\r
+ if (face_value < 0 || face_value >= 256) {\r
+ /* this includes the OverflowError in case the long is too large */\r
+ PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");\r
+ return 0;\r
+ }\r
+\r
+ *value = face_value;\r
+ return 1;\r
+}\r
+\r
+static Py_ssize_t\r
+bytearray_buffer_getreadbuf(PyByteArrayObject *self, Py_ssize_t index, const void **ptr)\r
+{\r
+ if ( index != 0 ) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent bytes segment");\r
+ return -1;\r
+ }\r
+ *ptr = (void *)PyByteArray_AS_STRING(self);\r
+ return Py_SIZE(self);\r
+}\r
+\r
+static Py_ssize_t\r
+bytearray_buffer_getwritebuf(PyByteArrayObject *self, Py_ssize_t index, const void **ptr)\r
+{\r
+ if ( index != 0 ) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent bytes segment");\r
+ return -1;\r
+ }\r
+ *ptr = (void *)PyByteArray_AS_STRING(self);\r
+ return Py_SIZE(self);\r
+}\r
+\r
+static Py_ssize_t\r
+bytearray_buffer_getsegcount(PyByteArrayObject *self, Py_ssize_t *lenp)\r
+{\r
+ if ( lenp )\r
+ *lenp = Py_SIZE(self);\r
+ return 1;\r
+}\r
+\r
+static Py_ssize_t\r
+bytearray_buffer_getcharbuf(PyByteArrayObject *self, Py_ssize_t index, const char **ptr)\r
+{\r
+ if ( index != 0 ) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent bytes segment");\r
+ return -1;\r
+ }\r
+ *ptr = PyByteArray_AS_STRING(self);\r
+ return Py_SIZE(self);\r
+}\r
+\r
+static int\r
+bytearray_getbuffer(PyByteArrayObject *obj, Py_buffer *view, int flags)\r
+{\r
+ int ret;\r
+ void *ptr;\r
+ if (view == NULL) {\r
+ obj->ob_exports++;\r
+ return 0;\r
+ }\r
+ ptr = (void *) PyByteArray_AS_STRING(obj);\r
+ ret = PyBuffer_FillInfo(view, (PyObject*)obj, ptr, Py_SIZE(obj), 0, flags);\r
+ if (ret >= 0) {\r
+ obj->ob_exports++;\r
+ }\r
+ return ret;\r
+}\r
+\r
+static void\r
+bytearray_releasebuffer(PyByteArrayObject *obj, Py_buffer *view)\r
+{\r
+ obj->ob_exports--;\r
+}\r
+\r
+static Py_ssize_t\r
+_getbuffer(PyObject *obj, Py_buffer *view)\r
+{\r
+ PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer;\r
+\r
+ if (buffer == NULL || buffer->bf_getbuffer == NULL)\r
+ {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "Type %.100s doesn't support the buffer API",\r
+ Py_TYPE(obj)->tp_name);\r
+ return -1;\r
+ }\r
+\r
+ if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)\r
+ return -1;\r
+ return view->len;\r
+}\r
+\r
+static int\r
+_canresize(PyByteArrayObject *self)\r
+{\r
+ if (self->ob_exports > 0) {\r
+ PyErr_SetString(PyExc_BufferError,\r
+ "Existing exports of data: object cannot be re-sized");\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+/* Direct API functions */\r
+\r
+PyObject *\r
+PyByteArray_FromObject(PyObject *input)\r
+{\r
+ return PyObject_CallFunctionObjArgs((PyObject *)&PyByteArray_Type,\r
+ input, NULL);\r
+}\r
+\r
+PyObject *\r
+PyByteArray_FromStringAndSize(const char *bytes, Py_ssize_t size)\r
+{\r
+ PyByteArrayObject *new;\r
+ Py_ssize_t alloc;\r
+\r
+ if (size < 0) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "Negative size passed to PyByteArray_FromStringAndSize");\r
+ return NULL;\r
+ }\r
+\r
+ new = PyObject_New(PyByteArrayObject, &PyByteArray_Type);\r
+ if (new == NULL)\r
+ return NULL;\r
+\r
+ if (size == 0) {\r
+ new->ob_bytes = NULL;\r
+ alloc = 0;\r
+ }\r
+ else {\r
+ alloc = size + 1;\r
+ new->ob_bytes = PyMem_Malloc(alloc);\r
+ if (new->ob_bytes == NULL) {\r
+ Py_DECREF(new);\r
+ return PyErr_NoMemory();\r
+ }\r
+ if (bytes != NULL && size > 0)\r
+ memcpy(new->ob_bytes, bytes, size);\r
+ new->ob_bytes[size] = '\0'; /* Trailing null byte */\r
+ }\r
+ Py_SIZE(new) = size;\r
+ new->ob_alloc = alloc;\r
+ new->ob_exports = 0;\r
+\r
+ return (PyObject *)new;\r
+}\r
+\r
+Py_ssize_t\r
+PyByteArray_Size(PyObject *self)\r
+{\r
+ assert(self != NULL);\r
+ assert(PyByteArray_Check(self));\r
+\r
+ return PyByteArray_GET_SIZE(self);\r
+}\r
+\r
+char *\r
+PyByteArray_AsString(PyObject *self)\r
+{\r
+ assert(self != NULL);\r
+ assert(PyByteArray_Check(self));\r
+\r
+ return PyByteArray_AS_STRING(self);\r
+}\r
+\r
+int\r
+PyByteArray_Resize(PyObject *self, Py_ssize_t size)\r
+{\r
+ void *sval;\r
+ Py_ssize_t alloc = ((PyByteArrayObject *)self)->ob_alloc;\r
+\r
+ assert(self != NULL);\r
+ assert(PyByteArray_Check(self));\r
+ assert(size >= 0);\r
+\r
+ if (size == Py_SIZE(self)) {\r
+ return 0;\r
+ }\r
+ if (!_canresize((PyByteArrayObject *)self)) {\r
+ return -1;\r
+ }\r
+\r
+ if (size < alloc / 2) {\r
+ /* Major downsize; resize down to exact size */\r
+ alloc = size + 1;\r
+ }\r
+ else if (size < alloc) {\r
+ /* Within allocated size; quick exit */\r
+ Py_SIZE(self) = size;\r
+ ((PyByteArrayObject *)self)->ob_bytes[size] = '\0'; /* Trailing null */\r
+ return 0;\r
+ }\r
+ else if (size <= alloc * 1.125) {\r
+ /* Moderate upsize; overallocate similar to list_resize() */\r
+ alloc = size + (size >> 3) + (size < 9 ? 3 : 6);\r
+ }\r
+ else {\r
+ /* Major upsize; resize up to exact size */\r
+ alloc = size + 1;\r
+ }\r
+\r
+ sval = PyMem_Realloc(((PyByteArrayObject *)self)->ob_bytes, alloc);\r
+ if (sval == NULL) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+\r
+ ((PyByteArrayObject *)self)->ob_bytes = sval;\r
+ Py_SIZE(self) = size;\r
+ ((PyByteArrayObject *)self)->ob_alloc = alloc;\r
+ ((PyByteArrayObject *)self)->ob_bytes[size] = '\0'; /* Trailing null byte */\r
+\r
+ return 0;\r
+}\r
+\r
+PyObject *\r
+PyByteArray_Concat(PyObject *a, PyObject *b)\r
+{\r
+ Py_ssize_t size;\r
+ Py_buffer va, vb;\r
+ PyByteArrayObject *result = NULL;\r
+\r
+ va.len = -1;\r
+ vb.len = -1;\r
+ if (_getbuffer(a, &va) < 0 ||\r
+ _getbuffer(b, &vb) < 0) {\r
+ PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",\r
+ Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);\r
+ goto done;\r
+ }\r
+\r
+ size = va.len + vb.len;\r
+ if (size < 0) {\r
+ PyErr_NoMemory();\r
+ goto done;\r
+ }\r
+\r
+ result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, size);\r
+ if (result != NULL) {\r
+ memcpy(result->ob_bytes, va.buf, va.len);\r
+ memcpy(result->ob_bytes + va.len, vb.buf, vb.len);\r
+ }\r
+\r
+ done:\r
+ if (va.len != -1)\r
+ PyBuffer_Release(&va);\r
+ if (vb.len != -1)\r
+ PyBuffer_Release(&vb);\r
+ return (PyObject *)result;\r
+}\r
+\r
+/* Functions stuffed into the type object */\r
+\r
+static Py_ssize_t\r
+bytearray_length(PyByteArrayObject *self)\r
+{\r
+ return Py_SIZE(self);\r
+}\r
+\r
+static PyObject *\r
+bytearray_iconcat(PyByteArrayObject *self, PyObject *other)\r
+{\r
+ Py_ssize_t mysize;\r
+ Py_ssize_t size;\r
+ Py_buffer vo;\r
+\r
+ if (_getbuffer(other, &vo) < 0) {\r
+ PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",\r
+ Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name);\r
+ return NULL;\r
+ }\r
+\r
+ mysize = Py_SIZE(self);\r
+ size = mysize + vo.len;\r
+ if (size < 0) {\r
+ PyBuffer_Release(&vo);\r
+ return PyErr_NoMemory();\r
+ }\r
+ if (size < self->ob_alloc) {\r
+ Py_SIZE(self) = size;\r
+ self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */\r
+ }\r
+ else if (PyByteArray_Resize((PyObject *)self, size) < 0) {\r
+ PyBuffer_Release(&vo);\r
+ return NULL;\r
+ }\r
+ memcpy(self->ob_bytes + mysize, vo.buf, vo.len);\r
+ PyBuffer_Release(&vo);\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+}\r
+\r
+static PyObject *\r
+bytearray_repeat(PyByteArrayObject *self, Py_ssize_t count)\r
+{\r
+ PyByteArrayObject *result;\r
+ Py_ssize_t mysize;\r
+ Py_ssize_t size;\r
+\r
+ if (count < 0)\r
+ count = 0;\r
+ mysize = Py_SIZE(self);\r
+ size = mysize * count;\r
+ if (count != 0 && size / count != mysize)\r
+ return PyErr_NoMemory();\r
+ result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size);\r
+ if (result != NULL && size != 0) {\r
+ if (mysize == 1)\r
+ memset(result->ob_bytes, self->ob_bytes[0], size);\r
+ else {\r
+ Py_ssize_t i;\r
+ for (i = 0; i < count; i++)\r
+ memcpy(result->ob_bytes + i*mysize, self->ob_bytes, mysize);\r
+ }\r
+ }\r
+ return (PyObject *)result;\r
+}\r
+\r
+static PyObject *\r
+bytearray_irepeat(PyByteArrayObject *self, Py_ssize_t count)\r
+{\r
+ Py_ssize_t mysize;\r
+ Py_ssize_t size;\r
+\r
+ if (count < 0)\r
+ count = 0;\r
+ mysize = Py_SIZE(self);\r
+ size = mysize * count;\r
+ if (count != 0 && size / count != mysize)\r
+ return PyErr_NoMemory();\r
+ if (size < self->ob_alloc) {\r
+ Py_SIZE(self) = size;\r
+ self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */\r
+ }\r
+ else if (PyByteArray_Resize((PyObject *)self, size) < 0)\r
+ return NULL;\r
+\r
+ if (mysize == 1)\r
+ memset(self->ob_bytes, self->ob_bytes[0], size);\r
+ else {\r
+ Py_ssize_t i;\r
+ for (i = 1; i < count; i++)\r
+ memcpy(self->ob_bytes + i*mysize, self->ob_bytes, mysize);\r
+ }\r
+\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+}\r
+\r
+static PyObject *\r
+bytearray_getitem(PyByteArrayObject *self, Py_ssize_t i)\r
+{\r
+ if (i < 0)\r
+ i += Py_SIZE(self);\r
+ if (i < 0 || i >= Py_SIZE(self)) {\r
+ PyErr_SetString(PyExc_IndexError, "bytearray index out of range");\r
+ return NULL;\r
+ }\r
+ return PyInt_FromLong((unsigned char)(self->ob_bytes[i]));\r
+}\r
+\r
+static PyObject *\r
+bytearray_subscript(PyByteArrayObject *self, PyObject *index)\r
+{\r
+ if (PyIndex_Check(index)) {\r
+ Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);\r
+\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+\r
+ if (i < 0)\r
+ i += PyByteArray_GET_SIZE(self);\r
+\r
+ if (i < 0 || i >= Py_SIZE(self)) {\r
+ PyErr_SetString(PyExc_IndexError, "bytearray index out of range");\r
+ return NULL;\r
+ }\r
+ return PyInt_FromLong((unsigned char)(self->ob_bytes[i]));\r
+ }\r
+ else if (PySlice_Check(index)) {\r
+ Py_ssize_t start, stop, step, slicelength, cur, i;\r
+ if (PySlice_GetIndicesEx((PySliceObject *)index,\r
+ PyByteArray_GET_SIZE(self),\r
+ &start, &stop, &step, &slicelength) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ if (slicelength <= 0)\r
+ return PyByteArray_FromStringAndSize("", 0);\r
+ else if (step == 1) {\r
+ return PyByteArray_FromStringAndSize(self->ob_bytes + start,\r
+ slicelength);\r
+ }\r
+ else {\r
+ char *source_buf = PyByteArray_AS_STRING(self);\r
+ char *result_buf = (char *)PyMem_Malloc(slicelength);\r
+ PyObject *result;\r
+\r
+ if (result_buf == NULL)\r
+ return PyErr_NoMemory();\r
+\r
+ for (cur = start, i = 0; i < slicelength;\r
+ cur += step, i++) {\r
+ result_buf[i] = source_buf[cur];\r
+ }\r
+ result = PyByteArray_FromStringAndSize(result_buf, slicelength);\r
+ PyMem_Free(result_buf);\r
+ return result;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_TypeError, "bytearray indices must be integers");\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static int\r
+bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,\r
+ PyObject *values)\r
+{\r
+ Py_ssize_t avail, needed;\r
+ void *bytes;\r
+ Py_buffer vbytes;\r
+ int res = 0;\r
+\r
+ vbytes.len = -1;\r
+ if (values == (PyObject *)self) {\r
+ /* Make a copy and call this function recursively */\r
+ int err;\r
+ values = PyByteArray_FromObject(values);\r
+ if (values == NULL)\r
+ return -1;\r
+ err = bytearray_setslice(self, lo, hi, values);\r
+ Py_DECREF(values);\r
+ return err;\r
+ }\r
+ if (values == NULL) {\r
+ /* del b[lo:hi] */\r
+ bytes = NULL;\r
+ needed = 0;\r
+ }\r
+ else {\r
+ if (_getbuffer(values, &vbytes) < 0) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can't set bytearray slice from %.100s",\r
+ Py_TYPE(values)->tp_name);\r
+ return -1;\r
+ }\r
+ needed = vbytes.len;\r
+ bytes = vbytes.buf;\r
+ }\r
+\r
+ if (lo < 0)\r
+ lo = 0;\r
+ if (hi < lo)\r
+ hi = lo;\r
+ if (hi > Py_SIZE(self))\r
+ hi = Py_SIZE(self);\r
+\r
+ avail = hi - lo;\r
+ if (avail < 0)\r
+ lo = hi = avail = 0;\r
+\r
+ if (avail != needed) {\r
+ if (avail > needed) {\r
+ if (!_canresize(self)) {\r
+ res = -1;\r
+ goto finish;\r
+ }\r
+ /*\r
+ 0 lo hi old_size\r
+ | |<----avail----->|<-----tomove------>|\r
+ | |<-needed->|<-----tomove------>|\r
+ 0 lo new_hi new_size\r
+ */\r
+ memmove(self->ob_bytes + lo + needed, self->ob_bytes + hi,\r
+ Py_SIZE(self) - hi);\r
+ }\r
+ /* XXX(nnorwitz): need to verify this can't overflow! */\r
+ if (PyByteArray_Resize((PyObject *)self,\r
+ Py_SIZE(self) + needed - avail) < 0) {\r
+ res = -1;\r
+ goto finish;\r
+ }\r
+ if (avail < needed) {\r
+ /*\r
+ 0 lo hi old_size\r
+ | |<-avail->|<-----tomove------>|\r
+ | |<----needed---->|<-----tomove------>|\r
+ 0 lo new_hi new_size\r
+ */\r
+ memmove(self->ob_bytes + lo + needed, self->ob_bytes + hi,\r
+ Py_SIZE(self) - lo - needed);\r
+ }\r
+ }\r
+\r
+ if (needed > 0)\r
+ memcpy(self->ob_bytes + lo, bytes, needed);\r
+\r
+\r
+ finish:\r
+ if (vbytes.len != -1)\r
+ PyBuffer_Release(&vbytes);\r
+ return res;\r
+}\r
+\r
+static int\r
+bytearray_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value)\r
+{\r
+ int ival;\r
+\r
+ if (i < 0)\r
+ i += Py_SIZE(self);\r
+\r
+ if (i < 0 || i >= Py_SIZE(self)) {\r
+ PyErr_SetString(PyExc_IndexError, "bytearray index out of range");\r
+ return -1;\r
+ }\r
+\r
+ if (value == NULL)\r
+ return bytearray_setslice(self, i, i+1, NULL);\r
+\r
+ if (!_getbytevalue(value, &ival))\r
+ return -1;\r
+\r
+ self->ob_bytes[i] = ival;\r
+ return 0;\r
+}\r
+\r
+static int\r
+bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *values)\r
+{\r
+ Py_ssize_t start, stop, step, slicelen, needed;\r
+ char *bytes;\r
+\r
+ if (PyIndex_Check(index)) {\r
+ Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);\r
+\r
+ if (i == -1 && PyErr_Occurred())\r
+ return -1;\r
+\r
+ if (i < 0)\r
+ i += PyByteArray_GET_SIZE(self);\r
+\r
+ if (i < 0 || i >= Py_SIZE(self)) {\r
+ PyErr_SetString(PyExc_IndexError, "bytearray index out of range");\r
+ return -1;\r
+ }\r
+\r
+ if (values == NULL) {\r
+ /* Fall through to slice assignment */\r
+ start = i;\r
+ stop = i + 1;\r
+ step = 1;\r
+ slicelen = 1;\r
+ }\r
+ else {\r
+ int ival;\r
+ if (!_getbytevalue(values, &ival))\r
+ return -1;\r
+ self->ob_bytes[i] = (char)ival;\r
+ return 0;\r
+ }\r
+ }\r
+ else if (PySlice_Check(index)) {\r
+ if (PySlice_GetIndicesEx((PySliceObject *)index,\r
+ PyByteArray_GET_SIZE(self),\r
+ &start, &stop, &step, &slicelen) < 0) {\r
+ return -1;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_TypeError, "bytearray indices must be integer");\r
+ return -1;\r
+ }\r
+\r
+ if (values == NULL) {\r
+ bytes = NULL;\r
+ needed = 0;\r
+ }\r
+ else if (values == (PyObject *)self || !PyByteArray_Check(values)) {\r
+ int err;\r
+ if (PyNumber_Check(values) || PyUnicode_Check(values)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "can assign only bytes, buffers, or iterables "\r
+ "of ints in range(0, 256)");\r
+ return -1;\r
+ }\r
+ /* Make a copy and call this function recursively */\r
+ values = PyByteArray_FromObject(values);\r
+ if (values == NULL)\r
+ return -1;\r
+ err = bytearray_ass_subscript(self, index, values);\r
+ Py_DECREF(values);\r
+ return err;\r
+ }\r
+ else {\r
+ assert(PyByteArray_Check(values));\r
+ bytes = ((PyByteArrayObject *)values)->ob_bytes;\r
+ needed = Py_SIZE(values);\r
+ }\r
+ /* Make sure b[5:2] = ... inserts before 5, not before 2. */\r
+ if ((step < 0 && start < stop) ||\r
+ (step > 0 && start > stop))\r
+ stop = start;\r
+ if (step == 1) {\r
+ if (slicelen != needed) {\r
+ if (!_canresize(self))\r
+ return -1;\r
+ if (slicelen > needed) {\r
+ /*\r
+ 0 start stop old_size\r
+ | |<---slicelen--->|<-----tomove------>|\r
+ | |<-needed->|<-----tomove------>|\r
+ 0 lo new_hi new_size\r
+ */\r
+ memmove(self->ob_bytes + start + needed, self->ob_bytes + stop,\r
+ Py_SIZE(self) - stop);\r
+ }\r
+ if (PyByteArray_Resize((PyObject *)self,\r
+ Py_SIZE(self) + needed - slicelen) < 0)\r
+ return -1;\r
+ if (slicelen < needed) {\r
+ /*\r
+ 0 lo hi old_size\r
+ | |<-avail->|<-----tomove------>|\r
+ | |<----needed---->|<-----tomove------>|\r
+ 0 lo new_hi new_size\r
+ */\r
+ memmove(self->ob_bytes + start + needed, self->ob_bytes + stop,\r
+ Py_SIZE(self) - start - needed);\r
+ }\r
+ }\r
+\r
+ if (needed > 0)\r
+ memcpy(self->ob_bytes + start, bytes, needed);\r
+\r
+ return 0;\r
+ }\r
+ else {\r
+ if (needed == 0) {\r
+ /* Delete slice */\r
+ size_t cur;\r
+ Py_ssize_t i;\r
+\r
+ if (!_canresize(self))\r
+ return -1;\r
+ if (step < 0) {\r
+ stop = start + 1;\r
+ start = stop + step * (slicelen - 1) - 1;\r
+ step = -step;\r
+ }\r
+ for (cur = start, i = 0;\r
+ i < slicelen; cur += step, i++) {\r
+ Py_ssize_t lim = step - 1;\r
+\r
+ if (cur + step >= (size_t)PyByteArray_GET_SIZE(self))\r
+ lim = PyByteArray_GET_SIZE(self) - cur - 1;\r
+\r
+ memmove(self->ob_bytes + cur - i,\r
+ self->ob_bytes + cur + 1, lim);\r
+ }\r
+ /* Move the tail of the bytes, in one chunk */\r
+ cur = start + slicelen*step;\r
+ if (cur < (size_t)PyByteArray_GET_SIZE(self)) {\r
+ memmove(self->ob_bytes + cur - slicelen,\r
+ self->ob_bytes + cur,\r
+ PyByteArray_GET_SIZE(self) - cur);\r
+ }\r
+ if (PyByteArray_Resize((PyObject *)self,\r
+ PyByteArray_GET_SIZE(self) - slicelen) < 0)\r
+ return -1;\r
+\r
+ return 0;\r
+ }\r
+ else {\r
+ /* Assign slice */\r
+ Py_ssize_t cur, i;\r
+\r
+ if (needed != slicelen) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "attempt to assign bytes of size %zd "\r
+ "to extended slice of size %zd",\r
+ needed, slicelen);\r
+ return -1;\r
+ }\r
+ for (cur = start, i = 0; i < slicelen; cur += step, i++)\r
+ self->ob_bytes[cur] = bytes[i];\r
+ return 0;\r
+ }\r
+ }\r
+}\r
+\r
+static int\r
+bytearray_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ static char *kwlist[] = {"source", "encoding", "errors", 0};\r
+ PyObject *arg = NULL;\r
+ const char *encoding = NULL;\r
+ const char *errors = NULL;\r
+ Py_ssize_t count;\r
+ PyObject *it;\r
+ PyObject *(*iternext)(PyObject *);\r
+\r
+ if (Py_SIZE(self) != 0) {\r
+ /* Empty previous contents (yes, do this first of all!) */\r
+ if (PyByteArray_Resize((PyObject *)self, 0) < 0)\r
+ return -1;\r
+ }\r
+\r
+ /* Parse arguments */\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:bytearray", kwlist,\r
+ &arg, &encoding, &errors))\r
+ return -1;\r
+\r
+ /* Make a quick exit if no first argument */\r
+ if (arg == NULL) {\r
+ if (encoding != NULL || errors != NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "encoding or errors without sequence argument");\r
+ return -1;\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ if (PyBytes_Check(arg)) {\r
+ PyObject *new, *encoded;\r
+ if (encoding != NULL) {\r
+ encoded = PyCodec_Encode(arg, encoding, errors);\r
+ if (encoded == NULL)\r
+ return -1;\r
+ assert(PyBytes_Check(encoded));\r
+ }\r
+ else {\r
+ encoded = arg;\r
+ Py_INCREF(arg);\r
+ }\r
+ new = bytearray_iconcat(self, arg);\r
+ Py_DECREF(encoded);\r
+ if (new == NULL)\r
+ return -1;\r
+ Py_DECREF(new);\r
+ return 0;\r
+ }\r
+\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(arg)) {\r
+ /* Encode via the codec registry */\r
+ PyObject *encoded, *new;\r
+ if (encoding == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "unicode argument without an encoding");\r
+ return -1;\r
+ }\r
+ encoded = PyCodec_Encode(arg, encoding, errors);\r
+ if (encoded == NULL)\r
+ return -1;\r
+ assert(PyBytes_Check(encoded));\r
+ new = bytearray_iconcat(self, encoded);\r
+ Py_DECREF(encoded);\r
+ if (new == NULL)\r
+ return -1;\r
+ Py_DECREF(new);\r
+ return 0;\r
+ }\r
+#endif\r
+\r
+ /* If it's not unicode, there can't be encoding or errors */\r
+ if (encoding != NULL || errors != NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "encoding or errors without a string argument");\r
+ return -1;\r
+ }\r
+\r
+ /* Is it an int? */\r
+ count = PyNumber_AsSsize_t(arg, PyExc_OverflowError);\r
+ if (count == -1 && PyErr_Occurred()) {\r
+ if (PyErr_ExceptionMatches(PyExc_OverflowError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ }\r
+ else if (count < 0) {\r
+ PyErr_SetString(PyExc_ValueError, "negative count");\r
+ return -1;\r
+ }\r
+ else {\r
+ if (count > 0) {\r
+ if (PyByteArray_Resize((PyObject *)self, count))\r
+ return -1;\r
+ memset(self->ob_bytes, 0, count);\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ /* Use the buffer API */\r
+ if (PyObject_CheckBuffer(arg)) {\r
+ Py_ssize_t size;\r
+ Py_buffer view;\r
+ if (PyObject_GetBuffer(arg, &view, PyBUF_FULL_RO) < 0)\r
+ return -1;\r
+ size = view.len;\r
+ if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;\r
+ if (PyBuffer_ToContiguous(self->ob_bytes, &view, size, 'C') < 0)\r
+ goto fail;\r
+ PyBuffer_Release(&view);\r
+ return 0;\r
+ fail:\r
+ PyBuffer_Release(&view);\r
+ return -1;\r
+ }\r
+\r
+ /* XXX Optimize this if the arguments is a list, tuple */\r
+\r
+ /* Get the iterator */\r
+ it = PyObject_GetIter(arg);\r
+ if (it == NULL)\r
+ return -1;\r
+ iternext = *Py_TYPE(it)->tp_iternext;\r
+\r
+ /* Run the iterator to exhaustion */\r
+ for (;;) {\r
+ PyObject *item;\r
+ int rc, value;\r
+\r
+ /* Get the next item */\r
+ item = iternext(it);\r
+ if (item == NULL) {\r
+ if (PyErr_Occurred()) {\r
+ if (!PyErr_ExceptionMatches(PyExc_StopIteration))\r
+ goto error;\r
+ PyErr_Clear();\r
+ }\r
+ break;\r
+ }\r
+\r
+ /* Interpret it as an int (__index__) */\r
+ rc = _getbytevalue(item, &value);\r
+ Py_DECREF(item);\r
+ if (!rc)\r
+ goto error;\r
+\r
+ /* Append the byte */\r
+ if (Py_SIZE(self) < self->ob_alloc)\r
+ Py_SIZE(self)++;\r
+ else if (PyByteArray_Resize((PyObject *)self, Py_SIZE(self)+1) < 0)\r
+ goto error;\r
+ self->ob_bytes[Py_SIZE(self)-1] = value;\r
+ }\r
+\r
+ /* Clean up and return success */\r
+ Py_DECREF(it);\r
+ return 0;\r
+\r
+ error:\r
+ /* Error handling when it != NULL */\r
+ Py_DECREF(it);\r
+ return -1;\r
+}\r
+\r
+/* Mostly copied from string_repr, but without the\r
+ "smart quote" functionality. */\r
+static PyObject *\r
+bytearray_repr(PyByteArrayObject *self)\r
+{\r
+ static const char *hexdigits = "0123456789abcdef";\r
+ const char *quote_prefix = "bytearray(b";\r
+ const char *quote_postfix = ")";\r
+ Py_ssize_t length = Py_SIZE(self);\r
+ /* 14 == strlen(quote_prefix) + 2 + strlen(quote_postfix) */\r
+ size_t newsize;\r
+ PyObject *v;\r
+ if (length > (PY_SSIZE_T_MAX - 14) / 4) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "bytearray object is too large to make repr");\r
+ return NULL;\r
+ }\r
+ newsize = 14 + 4 * length;\r
+ v = PyString_FromStringAndSize(NULL, newsize);\r
+ if (v == NULL) {\r
+ return NULL;\r
+ }\r
+ else {\r
+ register Py_ssize_t i;\r
+ register char c;\r
+ register char *p;\r
+ int quote;\r
+\r
+ /* Figure out which quote to use; single is preferred */\r
+ quote = '\'';\r
+ {\r
+ char *test, *start;\r
+ start = PyByteArray_AS_STRING(self);\r
+ for (test = start; test < start+length; ++test) {\r
+ if (*test == '"') {\r
+ quote = '\''; /* back to single */\r
+ goto decided;\r
+ }\r
+ else if (*test == '\'')\r
+ quote = '"';\r
+ }\r
+ decided:\r
+ ;\r
+ }\r
+\r
+ p = PyString_AS_STRING(v);\r
+ while (*quote_prefix)\r
+ *p++ = *quote_prefix++;\r
+ *p++ = quote;\r
+\r
+ for (i = 0; i < length; i++) {\r
+ /* There's at least enough room for a hex escape\r
+ and a closing quote. */\r
+ assert(newsize - (p - PyString_AS_STRING(v)) >= 5);\r
+ c = self->ob_bytes[i];\r
+ if (c == '\'' || c == '\\')\r
+ *p++ = '\\', *p++ = c;\r
+ else if (c == '\t')\r
+ *p++ = '\\', *p++ = 't';\r
+ else if (c == '\n')\r
+ *p++ = '\\', *p++ = 'n';\r
+ else if (c == '\r')\r
+ *p++ = '\\', *p++ = 'r';\r
+ else if (c == 0)\r
+ *p++ = '\\', *p++ = 'x', *p++ = '0', *p++ = '0';\r
+ else if (c < ' ' || c >= 0x7f) {\r
+ *p++ = '\\';\r
+ *p++ = 'x';\r
+ *p++ = hexdigits[(c & 0xf0) >> 4];\r
+ *p++ = hexdigits[c & 0xf];\r
+ }\r
+ else\r
+ *p++ = c;\r
+ }\r
+ assert(newsize - (p - PyString_AS_STRING(v)) >= 1);\r
+ *p++ = quote;\r
+ while (*quote_postfix) {\r
+ *p++ = *quote_postfix++;\r
+ }\r
+ *p = '\0';\r
+ /* v is cleared on error */\r
+ (void)_PyString_Resize(&v, (p - PyString_AS_STRING(v)));\r
+ return v;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+bytearray_str(PyObject *op)\r
+{\r
+#if 0\r
+ if (Py_BytesWarningFlag) {\r
+ if (PyErr_WarnEx(PyExc_BytesWarning,\r
+ "str() on a bytearray instance", 1))\r
+ return NULL;\r
+ }\r
+ return bytearray_repr((PyByteArrayObject*)op);\r
+#endif\r
+ return PyBytes_FromStringAndSize(((PyByteArrayObject*)op)->ob_bytes, Py_SIZE(op));\r
+}\r
+\r
+static PyObject *\r
+bytearray_richcompare(PyObject *self, PyObject *other, int op)\r
+{\r
+ Py_ssize_t self_size, other_size;\r
+ Py_buffer self_bytes, other_bytes;\r
+ PyObject *res;\r
+ Py_ssize_t minsize;\r
+ int cmp;\r
+\r
+ /* Bytes can be compared to anything that supports the (binary)\r
+ buffer API. Except that a comparison with Unicode is always an\r
+ error, even if the comparison is for equality. */\r
+#ifdef Py_USING_UNICODE\r
+ if (PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type) ||\r
+ PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type)) {\r
+ if (Py_BytesWarningFlag && op == Py_EQ) {\r
+ if (PyErr_WarnEx(PyExc_BytesWarning,\r
+ "Comparison between bytearray and string", 1))\r
+ return NULL;\r
+ }\r
+\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+#endif\r
+\r
+ self_size = _getbuffer(self, &self_bytes);\r
+ if (self_size < 0) {\r
+ PyErr_Clear();\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+\r
+ other_size = _getbuffer(other, &other_bytes);\r
+ if (other_size < 0) {\r
+ PyErr_Clear();\r
+ PyBuffer_Release(&self_bytes);\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+\r
+ if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {\r
+ /* Shortcut: if the lengths differ, the objects differ */\r
+ cmp = (op == Py_NE);\r
+ }\r
+ else {\r
+ minsize = self_size;\r
+ if (other_size < minsize)\r
+ minsize = other_size;\r
+\r
+ cmp = memcmp(self_bytes.buf, other_bytes.buf, minsize);\r
+ /* In ISO C, memcmp() guarantees to use unsigned bytes! */\r
+\r
+ if (cmp == 0) {\r
+ if (self_size < other_size)\r
+ cmp = -1;\r
+ else if (self_size > other_size)\r
+ cmp = 1;\r
+ }\r
+\r
+ switch (op) {\r
+ case Py_LT: cmp = cmp < 0; break;\r
+ case Py_LE: cmp = cmp <= 0; break;\r
+ case Py_EQ: cmp = cmp == 0; break;\r
+ case Py_NE: cmp = cmp != 0; break;\r
+ case Py_GT: cmp = cmp > 0; break;\r
+ case Py_GE: cmp = cmp >= 0; break;\r
+ }\r
+ }\r
+\r
+ res = cmp ? Py_True : Py_False;\r
+ PyBuffer_Release(&self_bytes);\r
+ PyBuffer_Release(&other_bytes);\r
+ Py_INCREF(res);\r
+ return res;\r
+}\r
+\r
+static void\r
+bytearray_dealloc(PyByteArrayObject *self)\r
+{\r
+ if (self->ob_exports > 0) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "deallocated bytearray object has exported buffers");\r
+ PyErr_Print();\r
+ }\r
+ if (self->ob_bytes != 0) {\r
+ PyMem_Free(self->ob_bytes);\r
+ }\r
+ Py_TYPE(self)->tp_free((PyObject *)self);\r
+}\r
+\r
+\r
+/* -------------------------------------------------------------------- */\r
+/* Methods */\r
+\r
+#define STRINGLIB_CHAR char\r
+#define STRINGLIB_LEN PyByteArray_GET_SIZE\r
+#define STRINGLIB_STR PyByteArray_AS_STRING\r
+#define STRINGLIB_NEW PyByteArray_FromStringAndSize\r
+#define STRINGLIB_ISSPACE Py_ISSPACE\r
+#define STRINGLIB_ISLINEBREAK(x) ((x == '\n') || (x == '\r'))\r
+#define STRINGLIB_CHECK_EXACT PyByteArray_CheckExact\r
+#define STRINGLIB_MUTABLE 1\r
+\r
+#include "stringlib/fastsearch.h"\r
+#include "stringlib/count.h"\r
+#include "stringlib/find.h"\r
+#include "stringlib/partition.h"\r
+#include "stringlib/split.h"\r
+#include "stringlib/ctype.h"\r
+#include "stringlib/transmogrify.h"\r
+\r
+\r
+/* The following Py_LOCAL_INLINE and Py_LOCAL functions\r
+were copied from the old char* style string object. */\r
+\r
+/* helper macro to fixup start/end slice values */\r
+#define ADJUST_INDICES(start, end, len) \\r
+ if (end > len) \\r
+ end = len; \\r
+ else if (end < 0) { \\r
+ end += len; \\r
+ if (end < 0) \\r
+ end = 0; \\r
+ } \\r
+ if (start < 0) { \\r
+ start += len; \\r
+ if (start < 0) \\r
+ start = 0; \\r
+ }\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+bytearray_find_internal(PyByteArrayObject *self, PyObject *args, int dir)\r
+{\r
+ PyObject *subobj;\r
+ Py_buffer subbuf;\r
+ Py_ssize_t start=0, end=PY_SSIZE_T_MAX;\r
+ Py_ssize_t res;\r
+\r
+ if (!stringlib_parse_args_finds("find/rfind/index/rindex",\r
+ args, &subobj, &start, &end))\r
+ return -2;\r
+ if (_getbuffer(subobj, &subbuf) < 0)\r
+ return -2;\r
+ if (dir > 0)\r
+ res = stringlib_find_slice(\r
+ PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),\r
+ subbuf.buf, subbuf.len, start, end);\r
+ else\r
+ res = stringlib_rfind_slice(\r
+ PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),\r
+ subbuf.buf, subbuf.len, start, end);\r
+ PyBuffer_Release(&subbuf);\r
+ return res;\r
+}\r
+\r
+PyDoc_STRVAR(find__doc__,\r
+"B.find(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Return the lowest index in B where subsection sub is found,\n\\r
+such that sub is contained within B[start,end]. Optional\n\\r
+arguments start and end are interpreted as in slice notation.\n\\r
+\n\\r
+Return -1 on failure.");\r
+\r
+static PyObject *\r
+bytearray_find(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t result = bytearray_find_internal(self, args, +1);\r
+ if (result == -2)\r
+ return NULL;\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+PyDoc_STRVAR(count__doc__,\r
+"B.count(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Return the number of non-overlapping occurrences of subsection sub in\n\\r
+bytes B[start:end]. Optional arguments start and end are interpreted\n\\r
+as in slice notation.");\r
+\r
+static PyObject *\r
+bytearray_count(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ PyObject *sub_obj;\r
+ const char *str = PyByteArray_AS_STRING(self);\r
+ Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;\r
+ Py_buffer vsub;\r
+ PyObject *count_obj;\r
+\r
+ if (!stringlib_parse_args_finds("count", args, &sub_obj, &start, &end))\r
+ return NULL;\r
+\r
+ if (_getbuffer(sub_obj, &vsub) < 0)\r
+ return NULL;\r
+\r
+ ADJUST_INDICES(start, end, PyByteArray_GET_SIZE(self));\r
+\r
+ count_obj = PyInt_FromSsize_t(\r
+ stringlib_count(str + start, end - start, vsub.buf, vsub.len, PY_SSIZE_T_MAX)\r
+ );\r
+ PyBuffer_Release(&vsub);\r
+ return count_obj;\r
+}\r
+\r
+\r
+PyDoc_STRVAR(index__doc__,\r
+"B.index(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Like B.find() but raise ValueError when the subsection is not found.");\r
+\r
+static PyObject *\r
+bytearray_index(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t result = bytearray_find_internal(self, args, +1);\r
+ if (result == -2)\r
+ return NULL;\r
+ if (result == -1) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "subsection not found");\r
+ return NULL;\r
+ }\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(rfind__doc__,\r
+"B.rfind(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Return the highest index in B where subsection sub is found,\n\\r
+such that sub is contained within B[start,end]. Optional\n\\r
+arguments start and end are interpreted as in slice notation.\n\\r
+\n\\r
+Return -1 on failure.");\r
+\r
+static PyObject *\r
+bytearray_rfind(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t result = bytearray_find_internal(self, args, -1);\r
+ if (result == -2)\r
+ return NULL;\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(rindex__doc__,\r
+"B.rindex(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Like B.rfind() but raise ValueError when the subsection is not found.");\r
+\r
+static PyObject *\r
+bytearray_rindex(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t result = bytearray_find_internal(self, args, -1);\r
+ if (result == -2)\r
+ return NULL;\r
+ if (result == -1) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "subsection not found");\r
+ return NULL;\r
+ }\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+\r
+static int\r
+bytearray_contains(PyObject *self, PyObject *arg)\r
+{\r
+ Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError);\r
+ if (ival == -1 && PyErr_Occurred()) {\r
+ Py_buffer varg;\r
+ int pos;\r
+ PyErr_Clear();\r
+ if (_getbuffer(arg, &varg) < 0)\r
+ return -1;\r
+ pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),\r
+ varg.buf, varg.len, 0);\r
+ PyBuffer_Release(&varg);\r
+ return pos >= 0;\r
+ }\r
+ if (ival < 0 || ival >= 256) {\r
+ PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");\r
+ return -1;\r
+ }\r
+\r
+ return memchr(PyByteArray_AS_STRING(self), ival, Py_SIZE(self)) != NULL;\r
+}\r
+\r
+\r
+/* Matches the end (direction >= 0) or start (direction < 0) of self\r
+ * against substr, using the start and end arguments. Returns\r
+ * -1 on error, 0 if not found and 1 if found.\r
+ */\r
+Py_LOCAL(int)\r
+_bytearray_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start,\r
+ Py_ssize_t end, int direction)\r
+{\r
+ Py_ssize_t len = PyByteArray_GET_SIZE(self);\r
+ const char* str;\r
+ Py_buffer vsubstr;\r
+ int rv = 0;\r
+\r
+ str = PyByteArray_AS_STRING(self);\r
+\r
+ if (_getbuffer(substr, &vsubstr) < 0)\r
+ return -1;\r
+\r
+ ADJUST_INDICES(start, end, len);\r
+\r
+ if (direction < 0) {\r
+ /* startswith */\r
+ if (start+vsubstr.len > len) {\r
+ goto done;\r
+ }\r
+ } else {\r
+ /* endswith */\r
+ if (end-start < vsubstr.len || start > len) {\r
+ goto done;\r
+ }\r
+\r
+ if (end-vsubstr.len > start)\r
+ start = end - vsubstr.len;\r
+ }\r
+ if (end-start >= vsubstr.len)\r
+ rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len);\r
+\r
+done:\r
+ PyBuffer_Release(&vsubstr);\r
+ return rv;\r
+}\r
+\r
+\r
+PyDoc_STRVAR(startswith__doc__,\r
+"B.startswith(prefix [,start [,end]]) -> bool\n\\r
+\n\\r
+Return True if B starts with the specified prefix, False otherwise.\n\\r
+With optional start, test B beginning at that position.\n\\r
+With optional end, stop comparing B at that position.\n\\r
+prefix can also be a tuple of strings to try.");\r
+\r
+static PyObject *\r
+bytearray_startswith(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t start = 0;\r
+ Py_ssize_t end = PY_SSIZE_T_MAX;\r
+ PyObject *subobj;\r
+ int result;\r
+\r
+ if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))\r
+ return NULL;\r
+ if (PyTuple_Check(subobj)) {\r
+ Py_ssize_t i;\r
+ for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {\r
+ result = _bytearray_tailmatch(self,\r
+ PyTuple_GET_ITEM(subobj, i),\r
+ start, end, -1);\r
+ if (result == -1)\r
+ return NULL;\r
+ else if (result) {\r
+ Py_RETURN_TRUE;\r
+ }\r
+ }\r
+ Py_RETURN_FALSE;\r
+ }\r
+ result = _bytearray_tailmatch(self, subobj, start, end, -1);\r
+ if (result == -1)\r
+ return NULL;\r
+ else\r
+ return PyBool_FromLong(result);\r
+}\r
+\r
+PyDoc_STRVAR(endswith__doc__,\r
+"B.endswith(suffix [,start [,end]]) -> bool\n\\r
+\n\\r
+Return True if B ends with the specified suffix, False otherwise.\n\\r
+With optional start, test B beginning at that position.\n\\r
+With optional end, stop comparing B at that position.\n\\r
+suffix can also be a tuple of strings to try.");\r
+\r
+static PyObject *\r
+bytearray_endswith(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t start = 0;\r
+ Py_ssize_t end = PY_SSIZE_T_MAX;\r
+ PyObject *subobj;\r
+ int result;\r
+\r
+ if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))\r
+ return NULL;\r
+ if (PyTuple_Check(subobj)) {\r
+ Py_ssize_t i;\r
+ for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {\r
+ result = _bytearray_tailmatch(self,\r
+ PyTuple_GET_ITEM(subobj, i),\r
+ start, end, +1);\r
+ if (result == -1)\r
+ return NULL;\r
+ else if (result) {\r
+ Py_RETURN_TRUE;\r
+ }\r
+ }\r
+ Py_RETURN_FALSE;\r
+ }\r
+ result = _bytearray_tailmatch(self, subobj, start, end, +1);\r
+ if (result == -1)\r
+ return NULL;\r
+ else\r
+ return PyBool_FromLong(result);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(translate__doc__,\r
+"B.translate(table[, deletechars]) -> bytearray\n\\r
+\n\\r
+Return a copy of B, where all characters occurring in the\n\\r
+optional argument deletechars are removed, and the remaining\n\\r
+characters have been mapped through the given translation\n\\r
+table, which must be a bytes object of length 256.");\r
+\r
+static PyObject *\r
+bytearray_translate(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ register char *input, *output;\r
+ register const char *table;\r
+ register Py_ssize_t i, c;\r
+ PyObject *input_obj = (PyObject*)self;\r
+ const char *output_start;\r
+ Py_ssize_t inlen;\r
+ PyObject *result = NULL;\r
+ int trans_table[256];\r
+ PyObject *tableobj = NULL, *delobj = NULL;\r
+ Py_buffer vtable, vdel;\r
+\r
+ if (!PyArg_UnpackTuple(args, "translate", 1, 2,\r
+ &tableobj, &delobj))\r
+ return NULL;\r
+\r
+ if (tableobj == Py_None) {\r
+ table = NULL;\r
+ tableobj = NULL;\r
+ } else if (_getbuffer(tableobj, &vtable) < 0) {\r
+ return NULL;\r
+ } else {\r
+ if (vtable.len != 256) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "translation table must be 256 characters long");\r
+ PyBuffer_Release(&vtable);\r
+ return NULL;\r
+ }\r
+ table = (const char*)vtable.buf;\r
+ }\r
+\r
+ if (delobj != NULL) {\r
+ if (_getbuffer(delobj, &vdel) < 0) {\r
+ if (tableobj != NULL)\r
+ PyBuffer_Release(&vtable);\r
+ return NULL;\r
+ }\r
+ }\r
+ else {\r
+ vdel.buf = NULL;\r
+ vdel.len = 0;\r
+ }\r
+\r
+ inlen = PyByteArray_GET_SIZE(input_obj);\r
+ result = PyByteArray_FromStringAndSize((char *)NULL, inlen);\r
+ if (result == NULL)\r
+ goto done;\r
+ output_start = output = PyByteArray_AsString(result);\r
+ input = PyByteArray_AS_STRING(input_obj);\r
+\r
+ if (vdel.len == 0 && table != NULL) {\r
+ /* If no deletions are required, use faster code */\r
+ for (i = inlen; --i >= 0; ) {\r
+ c = Py_CHARMASK(*input++);\r
+ *output++ = table[c];\r
+ }\r
+ goto done;\r
+ }\r
+\r
+ if (table == NULL) {\r
+ for (i = 0; i < 256; i++)\r
+ trans_table[i] = Py_CHARMASK(i);\r
+ } else {\r
+ for (i = 0; i < 256; i++)\r
+ trans_table[i] = Py_CHARMASK(table[i]);\r
+ }\r
+\r
+ for (i = 0; i < vdel.len; i++)\r
+ trans_table[(int) Py_CHARMASK( ((unsigned char*)vdel.buf)[i] )] = -1;\r
+\r
+ for (i = inlen; --i >= 0; ) {\r
+ c = Py_CHARMASK(*input++);\r
+ if (trans_table[c] != -1)\r
+ if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c)\r
+ continue;\r
+ }\r
+ /* Fix the size of the resulting string */\r
+ if (inlen > 0)\r
+ PyByteArray_Resize(result, output - output_start);\r
+\r
+done:\r
+ if (tableobj != NULL)\r
+ PyBuffer_Release(&vtable);\r
+ if (delobj != NULL)\r
+ PyBuffer_Release(&vdel);\r
+ return result;\r
+}\r
+\r
+\r
+/* find and count characters and substrings */\r
+\r
+#define findchar(target, target_len, c) \\r
+ ((char *)memchr((const void *)(target), c, target_len))\r
+\r
+\r
+/* Bytes ops must return a string, create a copy */\r
+Py_LOCAL(PyByteArrayObject *)\r
+return_self(PyByteArrayObject *self)\r
+{\r
+ return (PyByteArrayObject *)PyByteArray_FromStringAndSize(\r
+ PyByteArray_AS_STRING(self),\r
+ PyByteArray_GET_SIZE(self));\r
+}\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+countchar(const char *target, Py_ssize_t target_len, char c, Py_ssize_t maxcount)\r
+{\r
+ Py_ssize_t count=0;\r
+ const char *start=target;\r
+ const char *end=target+target_len;\r
+\r
+ while ( (start=findchar(start, end-start, c)) != NULL ) {\r
+ count++;\r
+ if (count >= maxcount)\r
+ break;\r
+ start += 1;\r
+ }\r
+ return count;\r
+}\r
+\r
+\r
+/* Algorithms for different cases of string replacement */\r
+\r
+/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */\r
+Py_LOCAL(PyByteArrayObject *)\r
+replace_interleave(PyByteArrayObject *self,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count, i, product;\r
+ PyByteArrayObject *result;\r
+\r
+ self_len = PyByteArray_GET_SIZE(self);\r
+\r
+ /* 1 at the end plus 1 after every character */\r
+ count = self_len+1;\r
+ if (maxcount < count)\r
+ count = maxcount;\r
+\r
+ /* Check for overflow */\r
+ /* result_len = count * to_len + self_len; */\r
+ product = count * to_len;\r
+ if (product / to_len != count) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "replace string is too long");\r
+ return NULL;\r
+ }\r
+ result_len = product + self_len;\r
+ if (result_len < 0) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "replace string is too long");\r
+ return NULL;\r
+ }\r
+\r
+ if (! (result = (PyByteArrayObject *)\r
+ PyByteArray_FromStringAndSize(NULL, result_len)) )\r
+ return NULL;\r
+\r
+ self_s = PyByteArray_AS_STRING(self);\r
+ result_s = PyByteArray_AS_STRING(result);\r
+\r
+ /* TODO: special case single character, which doesn't need memcpy */\r
+\r
+ /* Lay the first one down (guaranteed this will occur) */\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ count -= 1;\r
+\r
+ for (i=0; i<count; i++) {\r
+ *result_s++ = *self_s++;\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ }\r
+\r
+ /* Copy the rest of the original string */\r
+ Py_MEMCPY(result_s, self_s, self_len-i);\r
+\r
+ return result;\r
+}\r
+\r
+/* Special case for deleting a single character */\r
+/* len(self)>=1, len(from)==1, to="", maxcount>=1 */\r
+Py_LOCAL(PyByteArrayObject *)\r
+replace_delete_single_character(PyByteArrayObject *self,\r
+ char from_c, Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s;\r
+ char *start, *next, *end;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count;\r
+ PyByteArrayObject *result;\r
+\r
+ self_len = PyByteArray_GET_SIZE(self);\r
+ self_s = PyByteArray_AS_STRING(self);\r
+\r
+ count = countchar(self_s, self_len, from_c, maxcount);\r
+ if (count == 0) {\r
+ return return_self(self);\r
+ }\r
+\r
+ result_len = self_len - count; /* from_len == 1 */\r
+ assert(result_len>=0);\r
+\r
+ if ( (result = (PyByteArrayObject *)\r
+ PyByteArray_FromStringAndSize(NULL, result_len)) == NULL)\r
+ return NULL;\r
+ result_s = PyByteArray_AS_STRING(result);\r
+\r
+ start = self_s;\r
+ end = self_s + self_len;\r
+ while (count-- > 0) {\r
+ next = findchar(start, end-start, from_c);\r
+ if (next == NULL)\r
+ break;\r
+ Py_MEMCPY(result_s, start, next-start);\r
+ result_s += (next-start);\r
+ start = next+1;\r
+ }\r
+ Py_MEMCPY(result_s, start, end-start);\r
+\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */\r
+\r
+Py_LOCAL(PyByteArrayObject *)\r
+replace_delete_substring(PyByteArrayObject *self,\r
+ const char *from_s, Py_ssize_t from_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s;\r
+ char *start, *next, *end;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count, offset;\r
+ PyByteArrayObject *result;\r
+\r
+ self_len = PyByteArray_GET_SIZE(self);\r
+ self_s = PyByteArray_AS_STRING(self);\r
+\r
+ count = stringlib_count(self_s, self_len,\r
+ from_s, from_len,\r
+ maxcount);\r
+\r
+ if (count == 0) {\r
+ /* no matches */\r
+ return return_self(self);\r
+ }\r
+\r
+ result_len = self_len - (count * from_len);\r
+ assert (result_len>=0);\r
+\r
+ if ( (result = (PyByteArrayObject *)\r
+ PyByteArray_FromStringAndSize(NULL, result_len)) == NULL )\r
+ return NULL;\r
+\r
+ result_s = PyByteArray_AS_STRING(result);\r
+\r
+ start = self_s;\r
+ end = self_s + self_len;\r
+ while (count-- > 0) {\r
+ offset = stringlib_find(start, end-start,\r
+ from_s, from_len,\r
+ 0);\r
+ if (offset == -1)\r
+ break;\r
+ next = start + offset;\r
+\r
+ Py_MEMCPY(result_s, start, next-start);\r
+\r
+ result_s += (next-start);\r
+ start = next+from_len;\r
+ }\r
+ Py_MEMCPY(result_s, start, end-start);\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */\r
+Py_LOCAL(PyByteArrayObject *)\r
+replace_single_character_in_place(PyByteArrayObject *self,\r
+ char from_c, char to_c,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s, *start, *end, *next;\r
+ Py_ssize_t self_len;\r
+ PyByteArrayObject *result;\r
+\r
+ /* The result string will be the same size */\r
+ self_s = PyByteArray_AS_STRING(self);\r
+ self_len = PyByteArray_GET_SIZE(self);\r
+\r
+ next = findchar(self_s, self_len, from_c);\r
+\r
+ if (next == NULL) {\r
+ /* No matches; return the original bytes */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* Need to make a new bytes */\r
+ result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, self_len);\r
+ if (result == NULL)\r
+ return NULL;\r
+ result_s = PyByteArray_AS_STRING(result);\r
+ Py_MEMCPY(result_s, self_s, self_len);\r
+\r
+ /* change everything in-place, starting with this one */\r
+ start = result_s + (next-self_s);\r
+ *start = to_c;\r
+ start++;\r
+ end = result_s + self_len;\r
+\r
+ while (--maxcount > 0) {\r
+ next = findchar(start, end-start, from_c);\r
+ if (next == NULL)\r
+ break;\r
+ *next = to_c;\r
+ start = next+1;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */\r
+Py_LOCAL(PyByteArrayObject *)\r
+replace_substring_in_place(PyByteArrayObject *self,\r
+ const char *from_s, Py_ssize_t from_len,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *result_s, *start, *end;\r
+ char *self_s;\r
+ Py_ssize_t self_len, offset;\r
+ PyByteArrayObject *result;\r
+\r
+ /* The result bytes will be the same size */\r
+\r
+ self_s = PyByteArray_AS_STRING(self);\r
+ self_len = PyByteArray_GET_SIZE(self);\r
+\r
+ offset = stringlib_find(self_s, self_len,\r
+ from_s, from_len,\r
+ 0);\r
+ if (offset == -1) {\r
+ /* No matches; return the original bytes */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* Need to make a new bytes */\r
+ result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, self_len);\r
+ if (result == NULL)\r
+ return NULL;\r
+ result_s = PyByteArray_AS_STRING(result);\r
+ Py_MEMCPY(result_s, self_s, self_len);\r
+\r
+ /* change everything in-place, starting with this one */\r
+ start = result_s + offset;\r
+ Py_MEMCPY(start, to_s, from_len);\r
+ start += from_len;\r
+ end = result_s + self_len;\r
+\r
+ while ( --maxcount > 0) {\r
+ offset = stringlib_find(start, end-start,\r
+ from_s, from_len,\r
+ 0);\r
+ if (offset==-1)\r
+ break;\r
+ Py_MEMCPY(start+offset, to_s, from_len);\r
+ start += offset+from_len;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */\r
+Py_LOCAL(PyByteArrayObject *)\r
+replace_single_character(PyByteArrayObject *self,\r
+ char from_c,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s;\r
+ char *start, *next, *end;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count, product;\r
+ PyByteArrayObject *result;\r
+\r
+ self_s = PyByteArray_AS_STRING(self);\r
+ self_len = PyByteArray_GET_SIZE(self);\r
+\r
+ count = countchar(self_s, self_len, from_c, maxcount);\r
+ if (count == 0) {\r
+ /* no matches, return unchanged */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* use the difference between current and new, hence the "-1" */\r
+ /* result_len = self_len + count * (to_len-1) */\r
+ product = count * (to_len-1);\r
+ if (product / (to_len-1) != count) {\r
+ PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");\r
+ return NULL;\r
+ }\r
+ result_len = self_len + product;\r
+ if (result_len < 0) {\r
+ PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");\r
+ return NULL;\r
+ }\r
+\r
+ if ( (result = (PyByteArrayObject *)\r
+ PyByteArray_FromStringAndSize(NULL, result_len)) == NULL)\r
+ return NULL;\r
+ result_s = PyByteArray_AS_STRING(result);\r
+\r
+ start = self_s;\r
+ end = self_s + self_len;\r
+ while (count-- > 0) {\r
+ next = findchar(start, end-start, from_c);\r
+ if (next == NULL)\r
+ break;\r
+\r
+ if (next == start) {\r
+ /* replace with the 'to' */\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ start += 1;\r
+ } else {\r
+ /* copy the unchanged old then the 'to' */\r
+ Py_MEMCPY(result_s, start, next-start);\r
+ result_s += (next-start);\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ start = next+1;\r
+ }\r
+ }\r
+ /* Copy the remainder of the remaining bytes */\r
+ Py_MEMCPY(result_s, start, end-start);\r
+\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */\r
+Py_LOCAL(PyByteArrayObject *)\r
+replace_substring(PyByteArrayObject *self,\r
+ const char *from_s, Py_ssize_t from_len,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s;\r
+ char *start, *next, *end;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count, offset, product;\r
+ PyByteArrayObject *result;\r
+\r
+ self_s = PyByteArray_AS_STRING(self);\r
+ self_len = PyByteArray_GET_SIZE(self);\r
+\r
+ count = stringlib_count(self_s, self_len,\r
+ from_s, from_len,\r
+ maxcount);\r
+\r
+ if (count == 0) {\r
+ /* no matches, return unchanged */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* Check for overflow */\r
+ /* result_len = self_len + count * (to_len-from_len) */\r
+ product = count * (to_len-from_len);\r
+ if (product / (to_len-from_len) != count) {\r
+ PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");\r
+ return NULL;\r
+ }\r
+ result_len = self_len + product;\r
+ if (result_len < 0) {\r
+ PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");\r
+ return NULL;\r
+ }\r
+\r
+ if ( (result = (PyByteArrayObject *)\r
+ PyByteArray_FromStringAndSize(NULL, result_len)) == NULL)\r
+ return NULL;\r
+ result_s = PyByteArray_AS_STRING(result);\r
+\r
+ start = self_s;\r
+ end = self_s + self_len;\r
+ while (count-- > 0) {\r
+ offset = stringlib_find(start, end-start,\r
+ from_s, from_len,\r
+ 0);\r
+ if (offset == -1)\r
+ break;\r
+ next = start+offset;\r
+ if (next == start) {\r
+ /* replace with the 'to' */\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ start += from_len;\r
+ } else {\r
+ /* copy the unchanged old then the 'to' */\r
+ Py_MEMCPY(result_s, start, next-start);\r
+ result_s += (next-start);\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ start = next+from_len;\r
+ }\r
+ }\r
+ /* Copy the remainder of the remaining bytes */\r
+ Py_MEMCPY(result_s, start, end-start);\r
+\r
+ return result;\r
+}\r
+\r
+\r
+Py_LOCAL(PyByteArrayObject *)\r
+replace(PyByteArrayObject *self,\r
+ const char *from_s, Py_ssize_t from_len,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ if (maxcount < 0) {\r
+ maxcount = PY_SSIZE_T_MAX;\r
+ } else if (maxcount == 0 || PyByteArray_GET_SIZE(self) == 0) {\r
+ /* nothing to do; return the original bytes */\r
+ return return_self(self);\r
+ }\r
+\r
+ if (maxcount == 0 ||\r
+ (from_len == 0 && to_len == 0)) {\r
+ /* nothing to do; return the original bytes */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* Handle zero-length special cases */\r
+\r
+ if (from_len == 0) {\r
+ /* insert the 'to' bytes everywhere. */\r
+ /* >>> "Python".replace("", ".") */\r
+ /* '.P.y.t.h.o.n.' */\r
+ return replace_interleave(self, to_s, to_len, maxcount);\r
+ }\r
+\r
+ /* Except for "".replace("", "A") == "A" there is no way beyond this */\r
+ /* point for an empty self bytes to generate a non-empty bytes */\r
+ /* Special case so the remaining code always gets a non-empty bytes */\r
+ if (PyByteArray_GET_SIZE(self) == 0) {\r
+ return return_self(self);\r
+ }\r
+\r
+ if (to_len == 0) {\r
+ /* delete all occurances of 'from' bytes */\r
+ if (from_len == 1) {\r
+ return replace_delete_single_character(\r
+ self, from_s[0], maxcount);\r
+ } else {\r
+ return replace_delete_substring(self, from_s, from_len, maxcount);\r
+ }\r
+ }\r
+\r
+ /* Handle special case where both bytes have the same length */\r
+\r
+ if (from_len == to_len) {\r
+ if (from_len == 1) {\r
+ return replace_single_character_in_place(\r
+ self,\r
+ from_s[0],\r
+ to_s[0],\r
+ maxcount);\r
+ } else {\r
+ return replace_substring_in_place(\r
+ self, from_s, from_len, to_s, to_len, maxcount);\r
+ }\r
+ }\r
+\r
+ /* Otherwise use the more generic algorithms */\r
+ if (from_len == 1) {\r
+ return replace_single_character(self, from_s[0],\r
+ to_s, to_len, maxcount);\r
+ } else {\r
+ /* len('from')>=2, len('to')>=1 */\r
+ return replace_substring(self, from_s, from_len, to_s, to_len, maxcount);\r
+ }\r
+}\r
+\r
+\r
+PyDoc_STRVAR(replace__doc__,\r
+"B.replace(old, new[, count]) -> bytes\n\\r
+\n\\r
+Return a copy of B with all occurrences of subsection\n\\r
+old replaced by new. If the optional argument count is\n\\r
+given, only the first count occurrences are replaced.");\r
+\r
+static PyObject *\r
+bytearray_replace(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t count = -1;\r
+ PyObject *from, *to, *res;\r
+ Py_buffer vfrom, vto;\r
+\r
+ if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))\r
+ return NULL;\r
+\r
+ if (_getbuffer(from, &vfrom) < 0)\r
+ return NULL;\r
+ if (_getbuffer(to, &vto) < 0) {\r
+ PyBuffer_Release(&vfrom);\r
+ return NULL;\r
+ }\r
+\r
+ res = (PyObject *)replace((PyByteArrayObject *) self,\r
+ vfrom.buf, vfrom.len,\r
+ vto.buf, vto.len, count);\r
+\r
+ PyBuffer_Release(&vfrom);\r
+ PyBuffer_Release(&vto);\r
+ return res;\r
+}\r
+\r
+PyDoc_STRVAR(split__doc__,\r
+"B.split([sep[, maxsplit]]) -> list of bytearray\n\\r
+\n\\r
+Return a list of the sections in B, using sep as the delimiter.\n\\r
+If sep is not given, B is split on ASCII whitespace characters\n\\r
+(space, tab, return, newline, formfeed, vertical tab).\n\\r
+If maxsplit is given, at most maxsplit splits are done.");\r
+\r
+static PyObject *\r
+bytearray_split(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t len = PyByteArray_GET_SIZE(self), n;\r
+ Py_ssize_t maxsplit = -1;\r
+ const char *s = PyByteArray_AS_STRING(self), *sub;\r
+ PyObject *list, *subobj = Py_None;\r
+ Py_buffer vsub;\r
+\r
+ if (!PyArg_ParseTuple(args, "|On:split", &subobj, &maxsplit))\r
+ return NULL;\r
+ if (maxsplit < 0)\r
+ maxsplit = PY_SSIZE_T_MAX;\r
+\r
+ if (subobj == Py_None)\r
+ return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);\r
+\r
+ if (_getbuffer(subobj, &vsub) < 0)\r
+ return NULL;\r
+ sub = vsub.buf;\r
+ n = vsub.len;\r
+\r
+ list = stringlib_split(\r
+ (PyObject*) self, s, len, sub, n, maxsplit\r
+ );\r
+ PyBuffer_Release(&vsub);\r
+ return list;\r
+}\r
+\r
+PyDoc_STRVAR(partition__doc__,\r
+"B.partition(sep) -> (head, sep, tail)\n\\r
+\n\\r
+Searches for the separator sep in B, and returns the part before it,\n\\r
+the separator itself, and the part after it. If the separator is not\n\\r
+found, returns B and two empty bytearray objects.");\r
+\r
+static PyObject *\r
+bytearray_partition(PyByteArrayObject *self, PyObject *sep_obj)\r
+{\r
+ PyObject *bytesep, *result;\r
+\r
+ bytesep = PyByteArray_FromObject(sep_obj);\r
+ if (! bytesep)\r
+ return NULL;\r
+\r
+ result = stringlib_partition(\r
+ (PyObject*) self,\r
+ PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),\r
+ bytesep,\r
+ PyByteArray_AS_STRING(bytesep), PyByteArray_GET_SIZE(bytesep)\r
+ );\r
+\r
+ Py_DECREF(bytesep);\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(rpartition__doc__,\r
+"B.rpartition(sep) -> (head, sep, tail)\n\\r
+\n\\r
+Searches for the separator sep in B, starting at the end of B,\n\\r
+and returns the part before it, the separator itself, and the\n\\r
+part after it. If the separator is not found, returns two empty\n\\r
+bytearray objects and B.");\r
+\r
+static PyObject *\r
+bytearray_rpartition(PyByteArrayObject *self, PyObject *sep_obj)\r
+{\r
+ PyObject *bytesep, *result;\r
+\r
+ bytesep = PyByteArray_FromObject(sep_obj);\r
+ if (! bytesep)\r
+ return NULL;\r
+\r
+ result = stringlib_rpartition(\r
+ (PyObject*) self,\r
+ PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),\r
+ bytesep,\r
+ PyByteArray_AS_STRING(bytesep), PyByteArray_GET_SIZE(bytesep)\r
+ );\r
+\r
+ Py_DECREF(bytesep);\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(rsplit__doc__,\r
+"B.rsplit(sep[, maxsplit]) -> list of bytearray\n\\r
+\n\\r
+Return a list of the sections in B, using sep as the delimiter,\n\\r
+starting at the end of B and working to the front.\n\\r
+If sep is not given, B is split on ASCII whitespace characters\n\\r
+(space, tab, return, newline, formfeed, vertical tab).\n\\r
+If maxsplit is given, at most maxsplit splits are done.");\r
+\r
+static PyObject *\r
+bytearray_rsplit(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t len = PyByteArray_GET_SIZE(self), n;\r
+ Py_ssize_t maxsplit = -1;\r
+ const char *s = PyByteArray_AS_STRING(self), *sub;\r
+ PyObject *list, *subobj = Py_None;\r
+ Py_buffer vsub;\r
+\r
+ if (!PyArg_ParseTuple(args, "|On:rsplit", &subobj, &maxsplit))\r
+ return NULL;\r
+ if (maxsplit < 0)\r
+ maxsplit = PY_SSIZE_T_MAX;\r
+\r
+ if (subobj == Py_None)\r
+ return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);\r
+\r
+ if (_getbuffer(subobj, &vsub) < 0)\r
+ return NULL;\r
+ sub = vsub.buf;\r
+ n = vsub.len;\r
+\r
+ list = stringlib_rsplit(\r
+ (PyObject*) self, s, len, sub, n, maxsplit\r
+ );\r
+ PyBuffer_Release(&vsub);\r
+ return list;\r
+}\r
+\r
+PyDoc_STRVAR(reverse__doc__,\r
+"B.reverse() -> None\n\\r
+\n\\r
+Reverse the order of the values in B in place.");\r
+static PyObject *\r
+bytearray_reverse(PyByteArrayObject *self, PyObject *unused)\r
+{\r
+ char swap, *head, *tail;\r
+ Py_ssize_t i, j, n = Py_SIZE(self);\r
+\r
+ j = n / 2;\r
+ head = self->ob_bytes;\r
+ tail = head + n - 1;\r
+ for (i = 0; i < j; i++) {\r
+ swap = *head;\r
+ *head++ = *tail;\r
+ *tail-- = swap;\r
+ }\r
+\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(insert__doc__,\r
+"B.insert(index, int) -> None\n\\r
+\n\\r
+Insert a single item into the bytearray before the given index.");\r
+static PyObject *\r
+bytearray_insert(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ PyObject *value;\r
+ int ival;\r
+ Py_ssize_t where, n = Py_SIZE(self);\r
+\r
+ if (!PyArg_ParseTuple(args, "nO:insert", &where, &value))\r
+ return NULL;\r
+\r
+ if (n == PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "cannot add more objects to bytearray");\r
+ return NULL;\r
+ }\r
+ if (!_getbytevalue(value, &ival))\r
+ return NULL;\r
+ if (PyByteArray_Resize((PyObject *)self, n + 1) < 0)\r
+ return NULL;\r
+\r
+ if (where < 0) {\r
+ where += n;\r
+ if (where < 0)\r
+ where = 0;\r
+ }\r
+ if (where > n)\r
+ where = n;\r
+ memmove(self->ob_bytes + where + 1, self->ob_bytes + where, n - where);\r
+ self->ob_bytes[where] = ival;\r
+\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(append__doc__,\r
+"B.append(int) -> None\n\\r
+\n\\r
+Append a single item to the end of B.");\r
+static PyObject *\r
+bytearray_append(PyByteArrayObject *self, PyObject *arg)\r
+{\r
+ int value;\r
+ Py_ssize_t n = Py_SIZE(self);\r
+\r
+ if (! _getbytevalue(arg, &value))\r
+ return NULL;\r
+ if (n == PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "cannot add more objects to bytearray");\r
+ return NULL;\r
+ }\r
+ if (PyByteArray_Resize((PyObject *)self, n + 1) < 0)\r
+ return NULL;\r
+\r
+ self->ob_bytes[n] = value;\r
+\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(extend__doc__,\r
+"B.extend(iterable int) -> None\n\\r
+\n\\r
+Append all the elements from the iterator or sequence to the\n\\r
+end of B.");\r
+static PyObject *\r
+bytearray_extend(PyByteArrayObject *self, PyObject *arg)\r
+{\r
+ PyObject *it, *item, *bytearray_obj;\r
+ Py_ssize_t buf_size = 0, len = 0;\r
+ int value;\r
+ char *buf;\r
+\r
+ /* bytearray_setslice code only accepts something supporting PEP 3118. */\r
+ if (PyObject_CheckBuffer(arg)) {\r
+ if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), arg) == -1)\r
+ return NULL;\r
+\r
+ Py_RETURN_NONE;\r
+ }\r
+\r
+ it = PyObject_GetIter(arg);\r
+ if (it == NULL)\r
+ return NULL;\r
+\r
+ /* Try to determine the length of the argument. 32 is arbitrary. */\r
+ buf_size = _PyObject_LengthHint(arg, 32);\r
+ if (buf_size == -1) {\r
+ Py_DECREF(it);\r
+ return NULL;\r
+ }\r
+\r
+ bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size);\r
+ if (bytearray_obj == NULL) {\r
+ Py_DECREF(it);\r
+ return NULL;\r
+ }\r
+ buf = PyByteArray_AS_STRING(bytearray_obj);\r
+\r
+ while ((item = PyIter_Next(it)) != NULL) {\r
+ if (! _getbytevalue(item, &value)) {\r
+ Py_DECREF(item);\r
+ Py_DECREF(it);\r
+ Py_DECREF(bytearray_obj);\r
+ return NULL;\r
+ }\r
+ buf[len++] = value;\r
+ Py_DECREF(item);\r
+\r
+ if (len >= buf_size) {\r
+ buf_size = len + (len >> 1) + 1;\r
+ if (PyByteArray_Resize((PyObject *)bytearray_obj, buf_size) < 0) {\r
+ Py_DECREF(it);\r
+ Py_DECREF(bytearray_obj);\r
+ return NULL;\r
+ }\r
+ /* Recompute the `buf' pointer, since the resizing operation may\r
+ have invalidated it. */\r
+ buf = PyByteArray_AS_STRING(bytearray_obj);\r
+ }\r
+ }\r
+ Py_DECREF(it);\r
+\r
+ /* Resize down to exact size. */\r
+ if (PyByteArray_Resize((PyObject *)bytearray_obj, len) < 0) {\r
+ Py_DECREF(bytearray_obj);\r
+ return NULL;\r
+ }\r
+\r
+ if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) {\r
+ Py_DECREF(bytearray_obj);\r
+ return NULL;\r
+ }\r
+ Py_DECREF(bytearray_obj);\r
+\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(pop__doc__,\r
+"B.pop([index]) -> int\n\\r
+\n\\r
+Remove and return a single item from B. If no index\n\\r
+argument is given, will pop the last value.");\r
+static PyObject *\r
+bytearray_pop(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ int value;\r
+ Py_ssize_t where = -1, n = Py_SIZE(self);\r
+\r
+ if (!PyArg_ParseTuple(args, "|n:pop", &where))\r
+ return NULL;\r
+\r
+ if (n == 0) {\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "pop from empty bytearray");\r
+ return NULL;\r
+ }\r
+ if (where < 0)\r
+ where += Py_SIZE(self);\r
+ if (where < 0 || where >= Py_SIZE(self)) {\r
+ PyErr_SetString(PyExc_IndexError, "pop index out of range");\r
+ return NULL;\r
+ }\r
+ if (!_canresize(self))\r
+ return NULL;\r
+\r
+ value = self->ob_bytes[where];\r
+ memmove(self->ob_bytes + where, self->ob_bytes + where + 1, n - where);\r
+ if (PyByteArray_Resize((PyObject *)self, n - 1) < 0)\r
+ return NULL;\r
+\r
+ return PyInt_FromLong((unsigned char)value);\r
+}\r
+\r
+PyDoc_STRVAR(remove__doc__,\r
+"B.remove(int) -> None\n\\r
+\n\\r
+Remove the first occurance of a value in B.");\r
+static PyObject *\r
+bytearray_remove(PyByteArrayObject *self, PyObject *arg)\r
+{\r
+ int value;\r
+ Py_ssize_t where, n = Py_SIZE(self);\r
+\r
+ if (! _getbytevalue(arg, &value))\r
+ return NULL;\r
+\r
+ for (where = 0; where < n; where++) {\r
+ if (self->ob_bytes[where] == value)\r
+ break;\r
+ }\r
+ if (where == n) {\r
+ PyErr_SetString(PyExc_ValueError, "value not found in bytearray");\r
+ return NULL;\r
+ }\r
+ if (!_canresize(self))\r
+ return NULL;\r
+\r
+ memmove(self->ob_bytes + where, self->ob_bytes + where + 1, n - where);\r
+ if (PyByteArray_Resize((PyObject *)self, n - 1) < 0)\r
+ return NULL;\r
+\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+/* XXX These two helpers could be optimized if argsize == 1 */\r
+\r
+static Py_ssize_t\r
+lstrip_helper(unsigned char *myptr, Py_ssize_t mysize,\r
+ void *argptr, Py_ssize_t argsize)\r
+{\r
+ Py_ssize_t i = 0;\r
+ while (i < mysize && memchr(argptr, myptr[i], argsize))\r
+ i++;\r
+ return i;\r
+}\r
+\r
+static Py_ssize_t\r
+rstrip_helper(unsigned char *myptr, Py_ssize_t mysize,\r
+ void *argptr, Py_ssize_t argsize)\r
+{\r
+ Py_ssize_t i = mysize - 1;\r
+ while (i >= 0 && memchr(argptr, myptr[i], argsize))\r
+ i--;\r
+ return i + 1;\r
+}\r
+\r
+PyDoc_STRVAR(strip__doc__,\r
+"B.strip([bytes]) -> bytearray\n\\r
+\n\\r
+Strip leading and trailing bytes contained in the argument.\n\\r
+If the argument is omitted, strip ASCII whitespace.");\r
+static PyObject *\r
+bytearray_strip(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t left, right, mysize, argsize;\r
+ void *myptr, *argptr;\r
+ PyObject *arg = Py_None;\r
+ Py_buffer varg;\r
+ if (!PyArg_ParseTuple(args, "|O:strip", &arg))\r
+ return NULL;\r
+ if (arg == Py_None) {\r
+ argptr = "\t\n\r\f\v ";\r
+ argsize = 6;\r
+ }\r
+ else {\r
+ if (_getbuffer(arg, &varg) < 0)\r
+ return NULL;\r
+ argptr = varg.buf;\r
+ argsize = varg.len;\r
+ }\r
+ myptr = self->ob_bytes;\r
+ mysize = Py_SIZE(self);\r
+ left = lstrip_helper(myptr, mysize, argptr, argsize);\r
+ if (left == mysize)\r
+ right = left;\r
+ else\r
+ right = rstrip_helper(myptr, mysize, argptr, argsize);\r
+ if (arg != Py_None)\r
+ PyBuffer_Release(&varg);\r
+ return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);\r
+}\r
+\r
+PyDoc_STRVAR(lstrip__doc__,\r
+"B.lstrip([bytes]) -> bytearray\n\\r
+\n\\r
+Strip leading bytes contained in the argument.\n\\r
+If the argument is omitted, strip leading ASCII whitespace.");\r
+static PyObject *\r
+bytearray_lstrip(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t left, right, mysize, argsize;\r
+ void *myptr, *argptr;\r
+ PyObject *arg = Py_None;\r
+ Py_buffer varg;\r
+ if (!PyArg_ParseTuple(args, "|O:lstrip", &arg))\r
+ return NULL;\r
+ if (arg == Py_None) {\r
+ argptr = "\t\n\r\f\v ";\r
+ argsize = 6;\r
+ }\r
+ else {\r
+ if (_getbuffer(arg, &varg) < 0)\r
+ return NULL;\r
+ argptr = varg.buf;\r
+ argsize = varg.len;\r
+ }\r
+ myptr = self->ob_bytes;\r
+ mysize = Py_SIZE(self);\r
+ left = lstrip_helper(myptr, mysize, argptr, argsize);\r
+ right = mysize;\r
+ if (arg != Py_None)\r
+ PyBuffer_Release(&varg);\r
+ return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);\r
+}\r
+\r
+PyDoc_STRVAR(rstrip__doc__,\r
+"B.rstrip([bytes]) -> bytearray\n\\r
+\n\\r
+Strip trailing bytes contained in the argument.\n\\r
+If the argument is omitted, strip trailing ASCII whitespace.");\r
+static PyObject *\r
+bytearray_rstrip(PyByteArrayObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t left, right, mysize, argsize;\r
+ void *myptr, *argptr;\r
+ PyObject *arg = Py_None;\r
+ Py_buffer varg;\r
+ if (!PyArg_ParseTuple(args, "|O:rstrip", &arg))\r
+ return NULL;\r
+ if (arg == Py_None) {\r
+ argptr = "\t\n\r\f\v ";\r
+ argsize = 6;\r
+ }\r
+ else {\r
+ if (_getbuffer(arg, &varg) < 0)\r
+ return NULL;\r
+ argptr = varg.buf;\r
+ argsize = varg.len;\r
+ }\r
+ myptr = self->ob_bytes;\r
+ mysize = Py_SIZE(self);\r
+ left = 0;\r
+ right = rstrip_helper(myptr, mysize, argptr, argsize);\r
+ if (arg != Py_None)\r
+ PyBuffer_Release(&varg);\r
+ return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left);\r
+}\r
+\r
+PyDoc_STRVAR(decode_doc,\r
+"B.decode([encoding[, errors]]) -> unicode object.\n\\r
+\n\\r
+Decodes B using the codec registered for encoding. encoding defaults\n\\r
+to the default encoding. errors may be given to set a different error\n\\r
+handling scheme. Default is 'strict' meaning that encoding errors raise\n\\r
+a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'\n\\r
+as well as any other name registered with codecs.register_error that is\n\\r
+able to handle UnicodeDecodeErrors.");\r
+\r
+static PyObject *\r
+bytearray_decode(PyObject *self, PyObject *args, PyObject *kwargs)\r
+{\r
+ const char *encoding = NULL;\r
+ const char *errors = NULL;\r
+ static char *kwlist[] = {"encoding", "errors", 0};\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", kwlist, &encoding, &errors))\r
+ return NULL;\r
+ if (encoding == NULL) {\r
+#ifdef Py_USING_UNICODE\r
+ encoding = PyUnicode_GetDefaultEncoding();\r
+#else\r
+ PyErr_SetString(PyExc_ValueError, "no encoding specified");\r
+ return NULL;\r
+#endif\r
+ }\r
+ return PyCodec_Decode(self, encoding, errors);\r
+}\r
+\r
+PyDoc_STRVAR(alloc_doc,\r
+"B.__alloc__() -> int\n\\r
+\n\\r
+Returns the number of bytes actually allocated.");\r
+\r
+static PyObject *\r
+bytearray_alloc(PyByteArrayObject *self)\r
+{\r
+ return PyInt_FromSsize_t(self->ob_alloc);\r
+}\r
+\r
+PyDoc_STRVAR(join_doc,\r
+"B.join(iterable_of_bytes) -> bytes\n\\r
+\n\\r
+Concatenates any number of bytearray objects, with B in between each pair.");\r
+\r
+static PyObject *\r
+bytearray_join(PyByteArrayObject *self, PyObject *it)\r
+{\r
+ PyObject *seq;\r
+ Py_ssize_t mysize = Py_SIZE(self);\r
+ Py_ssize_t i;\r
+ Py_ssize_t n;\r
+ PyObject **items;\r
+ Py_ssize_t totalsize = 0;\r
+ PyObject *result;\r
+ char *dest;\r
+\r
+ seq = PySequence_Fast(it, "can only join an iterable");\r
+ if (seq == NULL)\r
+ return NULL;\r
+ n = PySequence_Fast_GET_SIZE(seq);\r
+ items = PySequence_Fast_ITEMS(seq);\r
+\r
+ /* Compute the total size, and check that they are all bytes */\r
+ /* XXX Shouldn't we use _getbuffer() on these items instead? */\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *obj = items[i];\r
+ if (!PyByteArray_Check(obj) && !PyBytes_Check(obj)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can only join an iterable of bytes "\r
+ "(item %ld has type '%.100s')",\r
+ /* XXX %ld isn't right on Win64 */\r
+ (long)i, Py_TYPE(obj)->tp_name);\r
+ goto error;\r
+ }\r
+ if (i > 0)\r
+ totalsize += mysize;\r
+ totalsize += Py_SIZE(obj);\r
+ if (totalsize < 0) {\r
+ PyErr_NoMemory();\r
+ goto error;\r
+ }\r
+ }\r
+\r
+ /* Allocate the result, and copy the bytes */\r
+ result = PyByteArray_FromStringAndSize(NULL, totalsize);\r
+ if (result == NULL)\r
+ goto error;\r
+ dest = PyByteArray_AS_STRING(result);\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *obj = items[i];\r
+ Py_ssize_t size = Py_SIZE(obj);\r
+ char *buf;\r
+ if (PyByteArray_Check(obj))\r
+ buf = PyByteArray_AS_STRING(obj);\r
+ else\r
+ buf = PyBytes_AS_STRING(obj);\r
+ if (i) {\r
+ memcpy(dest, self->ob_bytes, mysize);\r
+ dest += mysize;\r
+ }\r
+ memcpy(dest, buf, size);\r
+ dest += size;\r
+ }\r
+\r
+ /* Done */\r
+ Py_DECREF(seq);\r
+ return result;\r
+\r
+ /* Error handling */\r
+ error:\r
+ Py_DECREF(seq);\r
+ return NULL;\r
+}\r
+\r
+PyDoc_STRVAR(splitlines__doc__,\r
+"B.splitlines(keepends=False) -> list of lines\n\\r
+\n\\r
+Return a list of the lines in B, breaking at line boundaries.\n\\r
+Line breaks are not included in the resulting list unless keepends\n\\r
+is given and true.");\r
+\r
+static PyObject*\r
+bytearray_splitlines(PyObject *self, PyObject *args)\r
+{\r
+ int keepends = 0;\r
+\r
+ if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends))\r
+ return NULL;\r
+\r
+ return stringlib_splitlines(\r
+ (PyObject*) self, PyByteArray_AS_STRING(self),\r
+ PyByteArray_GET_SIZE(self), keepends\r
+ );\r
+}\r
+\r
+PyDoc_STRVAR(fromhex_doc,\r
+"bytearray.fromhex(string) -> bytearray\n\\r
+\n\\r
+Create a bytearray object from a string of hexadecimal numbers.\n\\r
+Spaces between two numbers are accepted.\n\\r
+Example: bytearray.fromhex('B9 01EF') -> bytearray(b'\\xb9\\x01\\xef').");\r
+\r
+static int\r
+hex_digit_to_int(char c)\r
+{\r
+ if (Py_ISDIGIT(c))\r
+ return c - '0';\r
+ else {\r
+ if (Py_ISUPPER(c))\r
+ c = Py_TOLOWER(c);\r
+ if (c >= 'a' && c <= 'f')\r
+ return c - 'a' + 10;\r
+ }\r
+ return -1;\r
+}\r
+\r
+static PyObject *\r
+bytearray_fromhex(PyObject *cls, PyObject *args)\r
+{\r
+ PyObject *newbytes;\r
+ char *buf;\r
+ char *hex;\r
+ Py_ssize_t hexlen, byteslen, i, j;\r
+ int top, bot;\r
+\r
+ if (!PyArg_ParseTuple(args, "s#:fromhex", &hex, &hexlen))\r
+ return NULL;\r
+ byteslen = hexlen/2; /* This overestimates if there are spaces */\r
+ newbytes = PyByteArray_FromStringAndSize(NULL, byteslen);\r
+ if (!newbytes)\r
+ return NULL;\r
+ buf = PyByteArray_AS_STRING(newbytes);\r
+ for (i = j = 0; i < hexlen; i += 2) {\r
+ /* skip over spaces in the input */\r
+ while (hex[i] == ' ')\r
+ i++;\r
+ if (i >= hexlen)\r
+ break;\r
+ top = hex_digit_to_int(hex[i]);\r
+ bot = hex_digit_to_int(hex[i+1]);\r
+ if (top == -1 || bot == -1) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "non-hexadecimal number found in "\r
+ "fromhex() arg at position %zd", i);\r
+ goto error;\r
+ }\r
+ buf[j++] = (top << 4) + bot;\r
+ }\r
+ if (PyByteArray_Resize(newbytes, j) < 0)\r
+ goto error;\r
+ return newbytes;\r
+\r
+ error:\r
+ Py_DECREF(newbytes);\r
+ return NULL;\r
+}\r
+\r
+PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");\r
+\r
+static PyObject *\r
+bytearray_reduce(PyByteArrayObject *self)\r
+{\r
+ PyObject *latin1, *dict;\r
+ if (self->ob_bytes)\r
+#ifdef Py_USING_UNICODE\r
+ latin1 = PyUnicode_DecodeLatin1(self->ob_bytes,\r
+ Py_SIZE(self), NULL);\r
+#else\r
+ latin1 = PyString_FromStringAndSize(self->ob_bytes, Py_SIZE(self));\r
+#endif\r
+ else\r
+#ifdef Py_USING_UNICODE\r
+ latin1 = PyUnicode_FromString("");\r
+#else\r
+ latin1 = PyString_FromString("");\r
+#endif\r
+\r
+ dict = PyObject_GetAttrString((PyObject *)self, "__dict__");\r
+ if (dict == NULL) {\r
+ PyErr_Clear();\r
+ dict = Py_None;\r
+ Py_INCREF(dict);\r
+ }\r
+\r
+ return Py_BuildValue("(O(Ns)N)", Py_TYPE(self), latin1, "latin-1", dict);\r
+}\r
+\r
+PyDoc_STRVAR(sizeof_doc,\r
+"B.__sizeof__() -> int\n\\r
+ \n\\r
+Returns the size of B in memory, in bytes");\r
+static PyObject *\r
+bytearray_sizeof(PyByteArrayObject *self)\r
+{\r
+ Py_ssize_t res;\r
+\r
+ res = sizeof(PyByteArrayObject) + self->ob_alloc * sizeof(char);\r
+ return PyInt_FromSsize_t(res);\r
+}\r
+\r
+static PySequenceMethods bytearray_as_sequence = {\r
+ (lenfunc)bytearray_length, /* sq_length */\r
+ (binaryfunc)PyByteArray_Concat, /* sq_concat */\r
+ (ssizeargfunc)bytearray_repeat, /* sq_repeat */\r
+ (ssizeargfunc)bytearray_getitem, /* sq_item */\r
+ 0, /* sq_slice */\r
+ (ssizeobjargproc)bytearray_setitem, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ (objobjproc)bytearray_contains, /* sq_contains */\r
+ (binaryfunc)bytearray_iconcat, /* sq_inplace_concat */\r
+ (ssizeargfunc)bytearray_irepeat, /* sq_inplace_repeat */\r
+};\r
+\r
+static PyMappingMethods bytearray_as_mapping = {\r
+ (lenfunc)bytearray_length,\r
+ (binaryfunc)bytearray_subscript,\r
+ (objobjargproc)bytearray_ass_subscript,\r
+};\r
+\r
+static PyBufferProcs bytearray_as_buffer = {\r
+ (readbufferproc)bytearray_buffer_getreadbuf,\r
+ (writebufferproc)bytearray_buffer_getwritebuf,\r
+ (segcountproc)bytearray_buffer_getsegcount,\r
+ (charbufferproc)bytearray_buffer_getcharbuf,\r
+ (getbufferproc)bytearray_getbuffer,\r
+ (releasebufferproc)bytearray_releasebuffer,\r
+};\r
+\r
+static PyMethodDef\r
+bytearray_methods[] = {\r
+ {"__alloc__", (PyCFunction)bytearray_alloc, METH_NOARGS, alloc_doc},\r
+ {"__reduce__", (PyCFunction)bytearray_reduce, METH_NOARGS, reduce_doc},\r
+ {"__sizeof__", (PyCFunction)bytearray_sizeof, METH_NOARGS, sizeof_doc},\r
+ {"append", (PyCFunction)bytearray_append, METH_O, append__doc__},\r
+ {"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,\r
+ _Py_capitalize__doc__},\r
+ {"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__},\r
+ {"count", (PyCFunction)bytearray_count, METH_VARARGS, count__doc__},\r
+ {"decode", (PyCFunction)bytearray_decode, METH_VARARGS | METH_KEYWORDS, decode_doc},\r
+ {"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS, endswith__doc__},\r
+ {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS,\r
+ expandtabs__doc__},\r
+ {"extend", (PyCFunction)bytearray_extend, METH_O, extend__doc__},\r
+ {"find", (PyCFunction)bytearray_find, METH_VARARGS, find__doc__},\r
+ {"fromhex", (PyCFunction)bytearray_fromhex, METH_VARARGS|METH_CLASS,\r
+ fromhex_doc},\r
+ {"index", (PyCFunction)bytearray_index, METH_VARARGS, index__doc__},\r
+ {"insert", (PyCFunction)bytearray_insert, METH_VARARGS, insert__doc__},\r
+ {"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,\r
+ _Py_isalnum__doc__},\r
+ {"isalpha", (PyCFunction)stringlib_isalpha, METH_NOARGS,\r
+ _Py_isalpha__doc__},\r
+ {"isdigit", (PyCFunction)stringlib_isdigit, METH_NOARGS,\r
+ _Py_isdigit__doc__},\r
+ {"islower", (PyCFunction)stringlib_islower, METH_NOARGS,\r
+ _Py_islower__doc__},\r
+ {"isspace", (PyCFunction)stringlib_isspace, METH_NOARGS,\r
+ _Py_isspace__doc__},\r
+ {"istitle", (PyCFunction)stringlib_istitle, METH_NOARGS,\r
+ _Py_istitle__doc__},\r
+ {"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,\r
+ _Py_isupper__doc__},\r
+ {"join", (PyCFunction)bytearray_join, METH_O, join_doc},\r
+ {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},\r
+ {"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},\r
+ {"lstrip", (PyCFunction)bytearray_lstrip, METH_VARARGS, lstrip__doc__},\r
+ {"partition", (PyCFunction)bytearray_partition, METH_O, partition__doc__},\r
+ {"pop", (PyCFunction)bytearray_pop, METH_VARARGS, pop__doc__},\r
+ {"remove", (PyCFunction)bytearray_remove, METH_O, remove__doc__},\r
+ {"replace", (PyCFunction)bytearray_replace, METH_VARARGS, replace__doc__},\r
+ {"reverse", (PyCFunction)bytearray_reverse, METH_NOARGS, reverse__doc__},\r
+ {"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, rfind__doc__},\r
+ {"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, rindex__doc__},\r
+ {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__},\r
+ {"rpartition", (PyCFunction)bytearray_rpartition, METH_O, rpartition__doc__},\r
+ {"rsplit", (PyCFunction)bytearray_rsplit, METH_VARARGS, rsplit__doc__},\r
+ {"rstrip", (PyCFunction)bytearray_rstrip, METH_VARARGS, rstrip__doc__},\r
+ {"split", (PyCFunction)bytearray_split, METH_VARARGS, split__doc__},\r
+ {"splitlines", (PyCFunction)bytearray_splitlines, METH_VARARGS,\r
+ splitlines__doc__},\r
+ {"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS ,\r
+ startswith__doc__},\r
+ {"strip", (PyCFunction)bytearray_strip, METH_VARARGS, strip__doc__},\r
+ {"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,\r
+ _Py_swapcase__doc__},\r
+ {"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},\r
+ {"translate", (PyCFunction)bytearray_translate, METH_VARARGS,\r
+ translate__doc__},\r
+ {"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},\r
+ {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__},\r
+ {NULL}\r
+};\r
+\r
+PyDoc_STRVAR(bytearray_doc,\r
+"bytearray(iterable_of_ints) -> bytearray.\n\\r
+bytearray(string, encoding[, errors]) -> bytearray.\n\\r
+bytearray(bytes_or_bytearray) -> mutable copy of bytes_or_bytearray.\n\\r
+bytearray(memory_view) -> bytearray.\n\\r
+\n\\r
+Construct an mutable bytearray object from:\n\\r
+ - an iterable yielding integers in range(256)\n\\r
+ - a text string encoded using the specified encoding\n\\r
+ - a bytes or a bytearray object\n\\r
+ - any object implementing the buffer API.\n\\r
+\n\\r
+bytearray(int) -> bytearray.\n\\r
+\n\\r
+Construct a zero-initialized bytearray of the given length.");\r
+\r
+\r
+static PyObject *bytearray_iter(PyObject *seq);\r
+\r
+PyTypeObject PyByteArray_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "bytearray",\r
+ sizeof(PyByteArrayObject),\r
+ 0,\r
+ (destructor)bytearray_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)bytearray_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &bytearray_as_sequence, /* tp_as_sequence */\r
+ &bytearray_as_mapping, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ bytearray_str, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ &bytearray_as_buffer, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |\r
+ Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */\r
+ bytearray_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ (richcmpfunc)bytearray_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ bytearray_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ bytearray_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ (initproc)bytearray_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ PyType_GenericNew, /* tp_new */\r
+ PyObject_Del, /* tp_free */\r
+};\r
+\r
+/*********************** Bytes Iterator ****************************/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ Py_ssize_t it_index;\r
+ PyByteArrayObject *it_seq; /* Set to NULL when iterator is exhausted */\r
+} bytesiterobject;\r
+\r
+static void\r
+bytearrayiter_dealloc(bytesiterobject *it)\r
+{\r
+ _PyObject_GC_UNTRACK(it);\r
+ Py_XDECREF(it->it_seq);\r
+ PyObject_GC_Del(it);\r
+}\r
+\r
+static int\r
+bytearrayiter_traverse(bytesiterobject *it, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(it->it_seq);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+bytearrayiter_next(bytesiterobject *it)\r
+{\r
+ PyByteArrayObject *seq;\r
+ PyObject *item;\r
+\r
+ assert(it != NULL);\r
+ seq = it->it_seq;\r
+ if (seq == NULL)\r
+ return NULL;\r
+ assert(PyByteArray_Check(seq));\r
+\r
+ if (it->it_index < PyByteArray_GET_SIZE(seq)) {\r
+ item = PyInt_FromLong(\r
+ (unsigned char)seq->ob_bytes[it->it_index]);\r
+ if (item != NULL)\r
+ ++it->it_index;\r
+ return item;\r
+ }\r
+\r
+ Py_DECREF(seq);\r
+ it->it_seq = NULL;\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+bytesarrayiter_length_hint(bytesiterobject *it)\r
+{\r
+ Py_ssize_t len = 0;\r
+ if (it->it_seq)\r
+ len = PyByteArray_GET_SIZE(it->it_seq) - it->it_index;\r
+ return PyInt_FromSsize_t(len);\r
+}\r
+\r
+PyDoc_STRVAR(length_hint_doc,\r
+ "Private method returning an estimate of len(list(it)).");\r
+\r
+static PyMethodDef bytearrayiter_methods[] = {\r
+ {"__length_hint__", (PyCFunction)bytesarrayiter_length_hint, METH_NOARGS,\r
+ length_hint_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyByteArrayIter_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "bytearray_iterator", /* tp_name */\r
+ sizeof(bytesiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)bytearrayiter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)bytearrayiter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)bytearrayiter_next, /* tp_iternext */\r
+ bytearrayiter_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *\r
+bytearray_iter(PyObject *seq)\r
+{\r
+ bytesiterobject *it;\r
+\r
+ if (!PyByteArray_Check(seq)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ it = PyObject_GC_New(bytesiterobject, &PyByteArrayIter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+ it->it_index = 0;\r
+ Py_INCREF(seq);\r
+ it->it_seq = (PyByteArrayObject *)seq;\r
+ _PyObject_GC_TRACK(it);\r
+ return (PyObject *)it;\r
+}\r
--- /dev/null
+#include "Python.h"\r
+#include "bytes_methods.h"\r
+\r
+PyDoc_STRVAR_shared(_Py_isspace__doc__,\r
+"B.isspace() -> bool\n\\r
+\n\\r
+Return True if all characters in B are whitespace\n\\r
+and there is at least one character in B, False otherwise.");\r
+\r
+PyObject*\r
+_Py_bytes_isspace(const char *cptr, Py_ssize_t len)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) cptr;\r
+ register const unsigned char *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (len == 1 && Py_ISSPACE(*p))\r
+ Py_RETURN_TRUE;\r
+\r
+ /* Special case for empty strings */\r
+ if (len == 0)\r
+ Py_RETURN_FALSE;\r
+\r
+ e = p + len;\r
+ for (; p < e; p++) {\r
+ if (!Py_ISSPACE(*p))\r
+ Py_RETURN_FALSE;\r
+ }\r
+ Py_RETURN_TRUE;\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_isalpha__doc__,\r
+"B.isalpha() -> bool\n\\r
+\n\\r
+Return True if all characters in B are alphabetic\n\\r
+and there is at least one character in B, False otherwise.");\r
+\r
+PyObject*\r
+_Py_bytes_isalpha(const char *cptr, Py_ssize_t len)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) cptr;\r
+ register const unsigned char *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (len == 1 && Py_ISALPHA(*p))\r
+ Py_RETURN_TRUE;\r
+\r
+ /* Special case for empty strings */\r
+ if (len == 0)\r
+ Py_RETURN_FALSE;\r
+\r
+ e = p + len;\r
+ for (; p < e; p++) {\r
+ if (!Py_ISALPHA(*p))\r
+ Py_RETURN_FALSE;\r
+ }\r
+ Py_RETURN_TRUE;\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_isalnum__doc__,\r
+"B.isalnum() -> bool\n\\r
+\n\\r
+Return True if all characters in B are alphanumeric\n\\r
+and there is at least one character in B, False otherwise.");\r
+\r
+PyObject*\r
+_Py_bytes_isalnum(const char *cptr, Py_ssize_t len)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) cptr;\r
+ register const unsigned char *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (len == 1 && Py_ISALNUM(*p))\r
+ Py_RETURN_TRUE;\r
+\r
+ /* Special case for empty strings */\r
+ if (len == 0)\r
+ Py_RETURN_FALSE;\r
+\r
+ e = p + len;\r
+ for (; p < e; p++) {\r
+ if (!Py_ISALNUM(*p))\r
+ Py_RETURN_FALSE;\r
+ }\r
+ Py_RETURN_TRUE;\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_isdigit__doc__,\r
+"B.isdigit() -> bool\n\\r
+\n\\r
+Return True if all characters in B are digits\n\\r
+and there is at least one character in B, False otherwise.");\r
+\r
+PyObject*\r
+_Py_bytes_isdigit(const char *cptr, Py_ssize_t len)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) cptr;\r
+ register const unsigned char *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (len == 1 && Py_ISDIGIT(*p))\r
+ Py_RETURN_TRUE;\r
+\r
+ /* Special case for empty strings */\r
+ if (len == 0)\r
+ Py_RETURN_FALSE;\r
+\r
+ e = p + len;\r
+ for (; p < e; p++) {\r
+ if (!Py_ISDIGIT(*p))\r
+ Py_RETURN_FALSE;\r
+ }\r
+ Py_RETURN_TRUE;\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_islower__doc__,\r
+"B.islower() -> bool\n\\r
+\n\\r
+Return True if all cased characters in B are lowercase and there is\n\\r
+at least one cased character in B, False otherwise.");\r
+\r
+PyObject*\r
+_Py_bytes_islower(const char *cptr, Py_ssize_t len)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) cptr;\r
+ register const unsigned char *e;\r
+ int cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (len == 1)\r
+ return PyBool_FromLong(Py_ISLOWER(*p));\r
+\r
+ /* Special case for empty strings */\r
+ if (len == 0)\r
+ Py_RETURN_FALSE;\r
+\r
+ e = p + len;\r
+ cased = 0;\r
+ for (; p < e; p++) {\r
+ if (Py_ISUPPER(*p))\r
+ Py_RETURN_FALSE;\r
+ else if (!cased && Py_ISLOWER(*p))\r
+ cased = 1;\r
+ }\r
+ return PyBool_FromLong(cased);\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_isupper__doc__,\r
+"B.isupper() -> bool\n\\r
+\n\\r
+Return True if all cased characters in B are uppercase and there is\n\\r
+at least one cased character in B, False otherwise.");\r
+\r
+PyObject*\r
+_Py_bytes_isupper(const char *cptr, Py_ssize_t len)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) cptr;\r
+ register const unsigned char *e;\r
+ int cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (len == 1)\r
+ return PyBool_FromLong(Py_ISUPPER(*p));\r
+\r
+ /* Special case for empty strings */\r
+ if (len == 0)\r
+ Py_RETURN_FALSE;\r
+\r
+ e = p + len;\r
+ cased = 0;\r
+ for (; p < e; p++) {\r
+ if (Py_ISLOWER(*p))\r
+ Py_RETURN_FALSE;\r
+ else if (!cased && Py_ISUPPER(*p))\r
+ cased = 1;\r
+ }\r
+ return PyBool_FromLong(cased);\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_istitle__doc__,\r
+"B.istitle() -> bool\n\\r
+\n\\r
+Return True if B is a titlecased string and there is at least one\n\\r
+character in B, i.e. uppercase characters may only follow uncased\n\\r
+characters and lowercase characters only cased ones. Return False\n\\r
+otherwise.");\r
+\r
+PyObject*\r
+_Py_bytes_istitle(const char *cptr, Py_ssize_t len)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) cptr;\r
+ register const unsigned char *e;\r
+ int cased, previous_is_cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (len == 1)\r
+ return PyBool_FromLong(Py_ISUPPER(*p));\r
+\r
+ /* Special case for empty strings */\r
+ if (len == 0)\r
+ Py_RETURN_FALSE;\r
+\r
+ e = p + len;\r
+ cased = 0;\r
+ previous_is_cased = 0;\r
+ for (; p < e; p++) {\r
+ register const unsigned char ch = *p;\r
+\r
+ if (Py_ISUPPER(ch)) {\r
+ if (previous_is_cased)\r
+ Py_RETURN_FALSE;\r
+ previous_is_cased = 1;\r
+ cased = 1;\r
+ }\r
+ else if (Py_ISLOWER(ch)) {\r
+ if (!previous_is_cased)\r
+ Py_RETURN_FALSE;\r
+ previous_is_cased = 1;\r
+ cased = 1;\r
+ }\r
+ else\r
+ previous_is_cased = 0;\r
+ }\r
+ return PyBool_FromLong(cased);\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_lower__doc__,\r
+"B.lower() -> copy of B\n\\r
+\n\\r
+Return a copy of B with all ASCII characters converted to lowercase.");\r
+\r
+void\r
+_Py_bytes_lower(char *result, const char *cptr, Py_ssize_t len)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ /*\r
+ newobj = PyString_FromStringAndSize(NULL, len);\r
+ if (!newobj)\r
+ return NULL;\r
+\r
+ s = PyString_AS_STRING(newobj);\r
+ */\r
+\r
+ Py_MEMCPY(result, cptr, len);\r
+\r
+ for (i = 0; i < len; i++) {\r
+ int c = Py_CHARMASK(result[i]);\r
+ if (Py_ISUPPER(c))\r
+ result[i] = Py_TOLOWER(c);\r
+ }\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_upper__doc__,\r
+"B.upper() -> copy of B\n\\r
+\n\\r
+Return a copy of B with all ASCII characters converted to uppercase.");\r
+\r
+void\r
+_Py_bytes_upper(char *result, const char *cptr, Py_ssize_t len)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ /*\r
+ newobj = PyString_FromStringAndSize(NULL, len);\r
+ if (!newobj)\r
+ return NULL;\r
+\r
+ s = PyString_AS_STRING(newobj);\r
+ */\r
+\r
+ Py_MEMCPY(result, cptr, len);\r
+\r
+ for (i = 0; i < len; i++) {\r
+ int c = Py_CHARMASK(result[i]);\r
+ if (Py_ISLOWER(c))\r
+ result[i] = Py_TOUPPER(c);\r
+ }\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_title__doc__,\r
+"B.title() -> copy of B\n\\r
+\n\\r
+Return a titlecased version of B, i.e. ASCII words start with uppercase\n\\r
+characters, all remaining cased characters have lowercase.");\r
+\r
+void\r
+_Py_bytes_title(char *result, char *s, Py_ssize_t len)\r
+{\r
+ Py_ssize_t i;\r
+ int previous_is_cased = 0;\r
+\r
+ /*\r
+ newobj = PyString_FromStringAndSize(NULL, len);\r
+ if (newobj == NULL)\r
+ return NULL;\r
+ s_new = PyString_AsString(newobj);\r
+ */\r
+ for (i = 0; i < len; i++) {\r
+ int c = Py_CHARMASK(*s++);\r
+ if (Py_ISLOWER(c)) {\r
+ if (!previous_is_cased)\r
+ c = Py_TOUPPER(c);\r
+ previous_is_cased = 1;\r
+ } else if (Py_ISUPPER(c)) {\r
+ if (previous_is_cased)\r
+ c = Py_TOLOWER(c);\r
+ previous_is_cased = 1;\r
+ } else\r
+ previous_is_cased = 0;\r
+ *result++ = c;\r
+ }\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_capitalize__doc__,\r
+"B.capitalize() -> copy of B\n\\r
+\n\\r
+Return a copy of B with only its first character capitalized (ASCII)\n\\r
+and the rest lower-cased.");\r
+\r
+void\r
+_Py_bytes_capitalize(char *result, char *s, Py_ssize_t len)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ /*\r
+ newobj = PyString_FromStringAndSize(NULL, len);\r
+ if (newobj == NULL)\r
+ return NULL;\r
+ s_new = PyString_AsString(newobj);\r
+ */\r
+ if (0 < len) {\r
+ int c = Py_CHARMASK(*s++);\r
+ if (Py_ISLOWER(c))\r
+ *result = Py_TOUPPER(c);\r
+ else\r
+ *result = c;\r
+ result++;\r
+ }\r
+ for (i = 1; i < len; i++) {\r
+ int c = Py_CHARMASK(*s++);\r
+ if (Py_ISUPPER(c))\r
+ *result = Py_TOLOWER(c);\r
+ else\r
+ *result = c;\r
+ result++;\r
+ }\r
+}\r
+\r
+\r
+PyDoc_STRVAR_shared(_Py_swapcase__doc__,\r
+"B.swapcase() -> copy of B\n\\r
+\n\\r
+Return a copy of B with uppercase ASCII characters converted\n\\r
+to lowercase ASCII and vice versa.");\r
+\r
+void\r
+_Py_bytes_swapcase(char *result, char *s, Py_ssize_t len)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ /*\r
+ newobj = PyString_FromStringAndSize(NULL, len);\r
+ if (newobj == NULL)\r
+ return NULL;\r
+ s_new = PyString_AsString(newobj);\r
+ */\r
+ for (i = 0; i < len; i++) {\r
+ int c = Py_CHARMASK(*s++);\r
+ if (Py_ISLOWER(c)) {\r
+ *result = Py_TOUPPER(c);\r
+ }\r
+ else if (Py_ISUPPER(c)) {\r
+ *result = Py_TOLOWER(c);\r
+ }\r
+ else\r
+ *result = c;\r
+ result++;\r
+ }\r
+}\r
+\r
--- /dev/null
+/* Wrap void * pointers to be passed between C modules */\r
+\r
+#include "Python.h"\r
+\r
+/* Internal structure of PyCapsule */\r
+typedef struct {\r
+ PyObject_HEAD\r
+ void *pointer;\r
+ const char *name;\r
+ void *context;\r
+ PyCapsule_Destructor destructor;\r
+} PyCapsule;\r
+\r
+\r
+\r
+static int\r
+_is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)\r
+{\r
+ if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {\r
+ PyErr_SetString(PyExc_ValueError, invalid_capsule);\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+#define is_legal_capsule(capsule, name) \\r
+ (_is_legal_capsule(capsule, \\r
+ name " called with invalid PyCapsule object"))\r
+\r
+\r
+static int\r
+name_matches(const char *name1, const char *name2) {\r
+ /* if either is NULL, */\r
+ if (!name1 || !name2) {\r
+ /* they're only the same if they're both NULL. */\r
+ return name1 == name2;\r
+ }\r
+ return !strcmp(name1, name2);\r
+}\r
+\r
+\r
+\r
+PyObject *\r
+PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)\r
+{\r
+ PyCapsule *capsule;\r
+\r
+ if (!pointer) {\r
+ PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");\r
+ return NULL;\r
+ }\r
+\r
+ capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type);\r
+ if (capsule == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ capsule->pointer = pointer;\r
+ capsule->name = name;\r
+ capsule->context = NULL;\r
+ capsule->destructor = destructor;\r
+\r
+ return (PyObject *)capsule;\r
+}\r
+\r
+\r
+int\r
+PyCapsule_IsValid(PyObject *o, const char *name)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+\r
+ return (capsule != NULL &&\r
+ PyCapsule_CheckExact(capsule) &&\r
+ capsule->pointer != NULL &&\r
+ name_matches(capsule->name, name));\r
+}\r
+\r
+\r
+void *\r
+PyCapsule_GetPointer(PyObject *o, const char *name)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+\r
+ if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {\r
+ return NULL;\r
+ }\r
+\r
+ if (!name_matches(name, capsule->name)) {\r
+ PyErr_SetString(PyExc_ValueError, "PyCapsule_GetPointer called with incorrect name");\r
+ return NULL;\r
+ }\r
+\r
+ return capsule->pointer;\r
+}\r
+\r
+\r
+const char *\r
+PyCapsule_GetName(PyObject *o)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+\r
+ if (!is_legal_capsule(capsule, "PyCapsule_GetName")) {\r
+ return NULL;\r
+ }\r
+ return capsule->name;\r
+}\r
+\r
+\r
+PyCapsule_Destructor\r
+PyCapsule_GetDestructor(PyObject *o)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+\r
+ if (!is_legal_capsule(capsule, "PyCapsule_GetDestructor")) {\r
+ return NULL;\r
+ }\r
+ return capsule->destructor;\r
+}\r
+\r
+\r
+void *\r
+PyCapsule_GetContext(PyObject *o)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+\r
+ if (!is_legal_capsule(capsule, "PyCapsule_GetContext")) {\r
+ return NULL;\r
+ }\r
+ return capsule->context;\r
+}\r
+\r
+\r
+int\r
+PyCapsule_SetPointer(PyObject *o, void *pointer)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+\r
+ if (!pointer) {\r
+ PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer");\r
+ return -1;\r
+ }\r
+\r
+ if (!is_legal_capsule(capsule, "PyCapsule_SetPointer")) {\r
+ return -1;\r
+ }\r
+\r
+ capsule->pointer = pointer;\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyCapsule_SetName(PyObject *o, const char *name)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+\r
+ if (!is_legal_capsule(capsule, "PyCapsule_SetName")) {\r
+ return -1;\r
+ }\r
+\r
+ capsule->name = name;\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+\r
+ if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) {\r
+ return -1;\r
+ }\r
+\r
+ capsule->destructor = destructor;\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyCapsule_SetContext(PyObject *o, void *context)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+\r
+ if (!is_legal_capsule(capsule, "PyCapsule_SetContext")) {\r
+ return -1;\r
+ }\r
+\r
+ capsule->context = context;\r
+ return 0;\r
+}\r
+\r
+\r
+void *\r
+PyCapsule_Import(const char *name, int no_block)\r
+{\r
+ PyObject *object = NULL;\r
+ void *return_value = NULL;\r
+ char *trace;\r
+ size_t name_length = (strlen(name) + 1) * sizeof(char);\r
+ char *name_dup = (char *)PyMem_MALLOC(name_length);\r
+\r
+ if (!name_dup) {\r
+ return NULL;\r
+ }\r
+\r
+ memcpy(name_dup, name, name_length);\r
+\r
+ trace = name_dup;\r
+ while (trace) {\r
+ char *dot = strchr(trace, '.');\r
+ if (dot) {\r
+ *dot++ = '\0';\r
+ }\r
+\r
+ if (object == NULL) {\r
+ if (no_block) {\r
+ object = PyImport_ImportModuleNoBlock(trace);\r
+ } else {\r
+ object = PyImport_ImportModule(trace);\r
+ if (!object) {\r
+ PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);\r
+ }\r
+ }\r
+ } else {\r
+ PyObject *object2 = PyObject_GetAttrString(object, trace);\r
+ Py_DECREF(object);\r
+ object = object2;\r
+ }\r
+ if (!object) {\r
+ goto EXIT;\r
+ }\r
+\r
+ trace = dot;\r
+ }\r
+\r
+ /* compare attribute name to module.name by hand */\r
+ if (PyCapsule_IsValid(object, name)) {\r
+ PyCapsule *capsule = (PyCapsule *)object;\r
+ return_value = capsule->pointer;\r
+ } else {\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "PyCapsule_Import \"%s\" is not valid",\r
+ name);\r
+ }\r
+\r
+EXIT:\r
+ Py_XDECREF(object);\r
+ if (name_dup) {\r
+ PyMem_FREE(name_dup);\r
+ }\r
+ return return_value;\r
+}\r
+\r
+\r
+static void\r
+capsule_dealloc(PyObject *o)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+ if (capsule->destructor) {\r
+ capsule->destructor(o);\r
+ }\r
+ PyObject_DEL(o);\r
+}\r
+\r
+\r
+static PyObject *\r
+capsule_repr(PyObject *o)\r
+{\r
+ PyCapsule *capsule = (PyCapsule *)o;\r
+ const char *name;\r
+ const char *quote;\r
+\r
+ if (capsule->name) {\r
+ quote = "\"";\r
+ name = capsule->name;\r
+ } else {\r
+ quote = "";\r
+ name = "NULL";\r
+ }\r
+\r
+ return PyString_FromFormat("<capsule object %s%s%s at %p>",\r
+ quote, name, quote, capsule);\r
+}\r
+\r
+\r
+\r
+PyDoc_STRVAR(PyCapsule_Type__doc__,\r
+"Capsule objects let you wrap a C \"void *\" pointer in a Python\n\\r
+object. They're a way of passing data through the Python interpreter\n\\r
+without creating your own custom type.\n\\r
+\n\\r
+Capsules are used for communication between extension modules.\n\\r
+They provide a way for an extension module to export a C interface\n\\r
+to other extension modules, so that extension modules can use the\n\\r
+Python import mechanism to link to one another.\n\\r
+");\r
+\r
+PyTypeObject PyCapsule_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "PyCapsule", /*tp_name*/\r
+ sizeof(PyCapsule), /*tp_basicsize*/\r
+ 0, /*tp_itemsize*/\r
+ /* methods */\r
+ capsule_dealloc, /*tp_dealloc*/\r
+ 0, /*tp_print*/\r
+ 0, /*tp_getattr*/\r
+ 0, /*tp_setattr*/\r
+ 0, /*tp_reserved*/\r
+ capsule_repr, /*tp_repr*/\r
+ 0, /*tp_as_number*/\r
+ 0, /*tp_as_sequence*/\r
+ 0, /*tp_as_mapping*/\r
+ 0, /*tp_hash*/\r
+ 0, /*tp_call*/\r
+ 0, /*tp_str*/\r
+ 0, /*tp_getattro*/\r
+ 0, /*tp_setattro*/\r
+ 0, /*tp_as_buffer*/\r
+ 0, /*tp_flags*/\r
+ PyCapsule_Type__doc__ /*tp_doc*/\r
+};\r
+\r
+\r
--- /dev/null
+/* Cell object implementation */\r
+\r
+#include "Python.h"\r
+\r
+PyObject *\r
+PyCell_New(PyObject *obj)\r
+{\r
+ PyCellObject *op;\r
+\r
+ op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);\r
+ if (op == NULL)\r
+ return NULL;\r
+ op->ob_ref = obj;\r
+ Py_XINCREF(obj);\r
+\r
+ _PyObject_GC_TRACK(op);\r
+ return (PyObject *)op;\r
+}\r
+\r
+PyObject *\r
+PyCell_Get(PyObject *op)\r
+{\r
+ if (!PyCell_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ Py_XINCREF(((PyCellObject*)op)->ob_ref);\r
+ return PyCell_GET(op);\r
+}\r
+\r
+int\r
+PyCell_Set(PyObject *op, PyObject *obj)\r
+{\r
+ PyObject* oldobj;\r
+ if (!PyCell_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ oldobj = PyCell_GET(op);\r
+ Py_XINCREF(obj);\r
+ PyCell_SET(op, obj);\r
+ Py_XDECREF(oldobj);\r
+ return 0;\r
+}\r
+\r
+static void\r
+cell_dealloc(PyCellObject *op)\r
+{\r
+ _PyObject_GC_UNTRACK(op);\r
+ Py_XDECREF(op->ob_ref);\r
+ PyObject_GC_Del(op);\r
+}\r
+\r
+static int\r
+cell_compare(PyCellObject *a, PyCellObject *b)\r
+{\r
+ /* Py3K warning for comparisons */\r
+ if (PyErr_WarnPy3k("cell comparisons not supported in 3.x",\r
+ 1) < 0) {\r
+ return -2;\r
+ }\r
+\r
+ if (a->ob_ref == NULL) {\r
+ if (b->ob_ref == NULL)\r
+ return 0;\r
+ return -1;\r
+ } else if (b->ob_ref == NULL)\r
+ return 1;\r
+ return PyObject_Compare(a->ob_ref, b->ob_ref);\r
+}\r
+\r
+static PyObject *\r
+cell_repr(PyCellObject *op)\r
+{\r
+ if (op->ob_ref == NULL)\r
+ return PyString_FromFormat("<cell at %p: empty>", op);\r
+\r
+ return PyString_FromFormat("<cell at %p: %.80s object at %p>",\r
+ op, op->ob_ref->ob_type->tp_name,\r
+ op->ob_ref);\r
+}\r
+\r
+static int\r
+cell_traverse(PyCellObject *op, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(op->ob_ref);\r
+ return 0;\r
+}\r
+\r
+static int\r
+cell_clear(PyCellObject *op)\r
+{\r
+ Py_CLEAR(op->ob_ref);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+cell_get_contents(PyCellObject *op, void *closure)\r
+{\r
+ if (op->ob_ref == NULL)\r
+ {\r
+ PyErr_SetString(PyExc_ValueError, "Cell is empty");\r
+ return NULL;\r
+ }\r
+ Py_INCREF(op->ob_ref);\r
+ return op->ob_ref;\r
+}\r
+\r
+static PyGetSetDef cell_getsetlist[] = {\r
+ {"cell_contents", (getter)cell_get_contents, NULL},\r
+ {NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyCell_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "cell",\r
+ sizeof(PyCellObject),\r
+ 0,\r
+ (destructor)cell_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)cell_compare, /* tp_compare */\r
+ (reprfunc)cell_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)cell_traverse, /* tp_traverse */\r
+ (inquiry)cell_clear, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ 0, /* tp_members */\r
+ cell_getsetlist, /* tp_getset */\r
+};\r
--- /dev/null
+\r
+/* Class object implementation */\r
+\r
+#include "Python.h"\r
+#include "structmember.h"\r
+\r
+/* Free list for method objects to save malloc/free overhead\r
+ * The im_self element is used to chain the elements.\r
+ */\r
+static PyMethodObject *free_list;\r
+static int numfree = 0;\r
+#ifndef PyMethod_MAXFREELIST\r
+#define PyMethod_MAXFREELIST 256\r
+#endif\r
+\r
+#define TP_DESCR_GET(t) \\r
+ (PyType_HasFeature(t, Py_TPFLAGS_HAVE_CLASS) ? (t)->tp_descr_get : NULL)\r
+\r
+/* Forward */\r
+static PyObject *class_lookup(PyClassObject *, PyObject *,\r
+ PyClassObject **);\r
+static PyObject *instance_getattr1(PyInstanceObject *, PyObject *);\r
+static PyObject *instance_getattr2(PyInstanceObject *, PyObject *);\r
+\r
+static PyObject *getattrstr, *setattrstr, *delattrstr;\r
+\r
+\r
+PyObject *\r
+PyClass_New(PyObject *bases, PyObject *dict, PyObject *name)\r
+ /* bases is NULL or tuple of classobjects! */\r
+{\r
+ PyClassObject *op, *dummy;\r
+ static PyObject *docstr, *modstr, *namestr;\r
+ if (docstr == NULL) {\r
+ docstr= PyString_InternFromString("__doc__");\r
+ if (docstr == NULL)\r
+ return NULL;\r
+ }\r
+ if (modstr == NULL) {\r
+ modstr= PyString_InternFromString("__module__");\r
+ if (modstr == NULL)\r
+ return NULL;\r
+ }\r
+ if (namestr == NULL) {\r
+ namestr= PyString_InternFromString("__name__");\r
+ if (namestr == NULL)\r
+ return NULL;\r
+ }\r
+ if (name == NULL || !PyString_Check(name)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "PyClass_New: name must be a string");\r
+ return NULL;\r
+ }\r
+ if (dict == NULL || !PyDict_Check(dict)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "PyClass_New: dict must be a dictionary");\r
+ return NULL;\r
+ }\r
+ if (PyDict_GetItem(dict, docstr) == NULL) {\r
+ if (PyDict_SetItem(dict, docstr, Py_None) < 0)\r
+ return NULL;\r
+ }\r
+ if (PyDict_GetItem(dict, modstr) == NULL) {\r
+ PyObject *globals = PyEval_GetGlobals();\r
+ if (globals != NULL) {\r
+ PyObject *modname = PyDict_GetItem(globals, namestr);\r
+ if (modname != NULL) {\r
+ if (PyDict_SetItem(dict, modstr, modname) < 0)\r
+ return NULL;\r
+ }\r
+ }\r
+ }\r
+ if (bases == NULL) {\r
+ bases = PyTuple_New(0);\r
+ if (bases == NULL)\r
+ return NULL;\r
+ }\r
+ else {\r
+ Py_ssize_t i, n;\r
+ PyObject *base;\r
+ if (!PyTuple_Check(bases)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "PyClass_New: bases must be a tuple");\r
+ return NULL;\r
+ }\r
+ n = PyTuple_Size(bases);\r
+ for (i = 0; i < n; i++) {\r
+ base = PyTuple_GET_ITEM(bases, i);\r
+ if (!PyClass_Check(base)) {\r
+ if (PyCallable_Check(\r
+ (PyObject *) base->ob_type))\r
+ return PyObject_CallFunctionObjArgs(\r
+ (PyObject *) base->ob_type,\r
+ name, bases, dict, NULL);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "PyClass_New: base must be a class");\r
+ return NULL;\r
+ }\r
+ }\r
+ Py_INCREF(bases);\r
+ }\r
+\r
+ if (getattrstr == NULL) {\r
+ getattrstr = PyString_InternFromString("__getattr__");\r
+ if (getattrstr == NULL)\r
+ goto alloc_error;\r
+ setattrstr = PyString_InternFromString("__setattr__");\r
+ if (setattrstr == NULL)\r
+ goto alloc_error;\r
+ delattrstr = PyString_InternFromString("__delattr__");\r
+ if (delattrstr == NULL)\r
+ goto alloc_error;\r
+ }\r
+\r
+ op = PyObject_GC_New(PyClassObject, &PyClass_Type);\r
+ if (op == NULL) {\r
+alloc_error:\r
+ Py_DECREF(bases);\r
+ return NULL;\r
+ }\r
+ op->cl_bases = bases;\r
+ Py_INCREF(dict);\r
+ op->cl_dict = dict;\r
+ Py_XINCREF(name);\r
+ op->cl_name = name;\r
+ op->cl_weakreflist = NULL;\r
+\r
+ op->cl_getattr = class_lookup(op, getattrstr, &dummy);\r
+ op->cl_setattr = class_lookup(op, setattrstr, &dummy);\r
+ op->cl_delattr = class_lookup(op, delattrstr, &dummy);\r
+ Py_XINCREF(op->cl_getattr);\r
+ Py_XINCREF(op->cl_setattr);\r
+ Py_XINCREF(op->cl_delattr);\r
+ _PyObject_GC_TRACK(op);\r
+ return (PyObject *) op;\r
+}\r
+\r
+PyObject *\r
+PyMethod_Function(PyObject *im)\r
+{\r
+ if (!PyMethod_Check(im)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyMethodObject *)im)->im_func;\r
+}\r
+\r
+PyObject *\r
+PyMethod_Self(PyObject *im)\r
+{\r
+ if (!PyMethod_Check(im)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyMethodObject *)im)->im_self;\r
+}\r
+\r
+PyObject *\r
+PyMethod_Class(PyObject *im)\r
+{\r
+ if (!PyMethod_Check(im)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyMethodObject *)im)->im_class;\r
+}\r
+\r
+PyDoc_STRVAR(class_doc,\r
+"classobj(name, bases, dict)\n\\r
+\n\\r
+Create a class object. The name must be a string; the second argument\n\\r
+a tuple of classes, and the third a dictionary.");\r
+\r
+static PyObject *\r
+class_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *name, *bases, *dict;\r
+ static char *kwlist[] = {"name", "bases", "dict", 0};\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist,\r
+ &name, &bases, &dict))\r
+ return NULL;\r
+ return PyClass_New(bases, dict, name);\r
+}\r
+\r
+/* Class methods */\r
+\r
+static void\r
+class_dealloc(PyClassObject *op)\r
+{\r
+ _PyObject_GC_UNTRACK(op);\r
+ if (op->cl_weakreflist != NULL)\r
+ PyObject_ClearWeakRefs((PyObject *) op);\r
+ Py_DECREF(op->cl_bases);\r
+ Py_DECREF(op->cl_dict);\r
+ Py_XDECREF(op->cl_name);\r
+ Py_XDECREF(op->cl_getattr);\r
+ Py_XDECREF(op->cl_setattr);\r
+ Py_XDECREF(op->cl_delattr);\r
+ PyObject_GC_Del(op);\r
+}\r
+\r
+static PyObject *\r
+class_lookup(PyClassObject *cp, PyObject *name, PyClassObject **pclass)\r
+{\r
+ Py_ssize_t i, n;\r
+ PyObject *value = PyDict_GetItem(cp->cl_dict, name);\r
+ if (value != NULL) {\r
+ *pclass = cp;\r
+ return value;\r
+ }\r
+ n = PyTuple_Size(cp->cl_bases);\r
+ for (i = 0; i < n; i++) {\r
+ /* XXX What if one of the bases is not a class? */\r
+ PyObject *v = class_lookup(\r
+ (PyClassObject *)\r
+ PyTuple_GetItem(cp->cl_bases, i), name, pclass);\r
+ if (v != NULL)\r
+ return v;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+class_getattr(register PyClassObject *op, PyObject *name)\r
+{\r
+ register PyObject *v;\r
+ register char *sname;\r
+ PyClassObject *klass;\r
+ descrgetfunc f;\r
+\r
+ if (!PyString_Check(name)) {\r
+ PyErr_SetString(PyExc_TypeError, "attribute name must be a string");\r
+ return NULL;\r
+ }\r
+\r
+ sname = PyString_AsString(name);\r
+ if (sname[0] == '_' && sname[1] == '_') {\r
+ if (strcmp(sname, "__dict__") == 0) {\r
+ if (PyEval_GetRestricted()) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "class.__dict__ not accessible in restricted mode");\r
+ return NULL;\r
+ }\r
+ Py_INCREF(op->cl_dict);\r
+ return op->cl_dict;\r
+ }\r
+ if (strcmp(sname, "__bases__") == 0) {\r
+ Py_INCREF(op->cl_bases);\r
+ return op->cl_bases;\r
+ }\r
+ if (strcmp(sname, "__name__") == 0) {\r
+ if (op->cl_name == NULL)\r
+ v = Py_None;\r
+ else\r
+ v = op->cl_name;\r
+ Py_INCREF(v);\r
+ return v;\r
+ }\r
+ }\r
+ v = class_lookup(op, name, &klass);\r
+ if (v == NULL) {\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "class %.50s has no attribute '%.400s'",\r
+ PyString_AS_STRING(op->cl_name), sname);\r
+ return NULL;\r
+ }\r
+ f = TP_DESCR_GET(v->ob_type);\r
+ if (f == NULL)\r
+ Py_INCREF(v);\r
+ else\r
+ v = f(v, (PyObject *)NULL, (PyObject *)op);\r
+ return v;\r
+}\r
+\r
+static void\r
+set_slot(PyObject **slot, PyObject *v)\r
+{\r
+ PyObject *temp = *slot;\r
+ Py_XINCREF(v);\r
+ *slot = v;\r
+ Py_XDECREF(temp);\r
+}\r
+\r
+static void\r
+set_attr_slots(PyClassObject *c)\r
+{\r
+ PyClassObject *dummy;\r
+\r
+ set_slot(&c->cl_getattr, class_lookup(c, getattrstr, &dummy));\r
+ set_slot(&c->cl_setattr, class_lookup(c, setattrstr, &dummy));\r
+ set_slot(&c->cl_delattr, class_lookup(c, delattrstr, &dummy));\r
+}\r
+\r
+static char *\r
+set_dict(PyClassObject *c, PyObject *v)\r
+{\r
+ if (v == NULL || !PyDict_Check(v))\r
+ return "__dict__ must be a dictionary object";\r
+ set_slot(&c->cl_dict, v);\r
+ set_attr_slots(c);\r
+ return "";\r
+}\r
+\r
+static char *\r
+set_bases(PyClassObject *c, PyObject *v)\r
+{\r
+ Py_ssize_t i, n;\r
+\r
+ if (v == NULL || !PyTuple_Check(v))\r
+ return "__bases__ must be a tuple object";\r
+ n = PyTuple_Size(v);\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *x = PyTuple_GET_ITEM(v, i);\r
+ if (!PyClass_Check(x))\r
+ return "__bases__ items must be classes";\r
+ if (PyClass_IsSubclass(x, (PyObject *)c))\r
+ return "a __bases__ item causes an inheritance cycle";\r
+ }\r
+ set_slot(&c->cl_bases, v);\r
+ set_attr_slots(c);\r
+ return "";\r
+}\r
+\r
+static char *\r
+set_name(PyClassObject *c, PyObject *v)\r
+{\r
+ if (v == NULL || !PyString_Check(v))\r
+ return "__name__ must be a string object";\r
+ if (strlen(PyString_AS_STRING(v)) != (size_t)PyString_GET_SIZE(v))\r
+ return "__name__ must not contain null bytes";\r
+ set_slot(&c->cl_name, v);\r
+ return "";\r
+}\r
+\r
+static int\r
+class_setattr(PyClassObject *op, PyObject *name, PyObject *v)\r
+{\r
+ char *sname;\r
+ if (PyEval_GetRestricted()) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "classes are read-only in restricted mode");\r
+ return -1;\r
+ }\r
+ if (!PyString_Check(name)) {\r
+ PyErr_SetString(PyExc_TypeError, "attribute name must be a string");\r
+ return -1;\r
+ }\r
+ sname = PyString_AsString(name);\r
+ if (sname[0] == '_' && sname[1] == '_') {\r
+ Py_ssize_t n = PyString_Size(name);\r
+ if (sname[n-1] == '_' && sname[n-2] == '_') {\r
+ char *err = NULL;\r
+ if (strcmp(sname, "__dict__") == 0)\r
+ err = set_dict(op, v);\r
+ else if (strcmp(sname, "__bases__") == 0)\r
+ err = set_bases(op, v);\r
+ else if (strcmp(sname, "__name__") == 0)\r
+ err = set_name(op, v);\r
+ else if (strcmp(sname, "__getattr__") == 0)\r
+ set_slot(&op->cl_getattr, v);\r
+ else if (strcmp(sname, "__setattr__") == 0)\r
+ set_slot(&op->cl_setattr, v);\r
+ else if (strcmp(sname, "__delattr__") == 0)\r
+ set_slot(&op->cl_delattr, v);\r
+ /* For the last three, we fall through to update the\r
+ dictionary as well. */\r
+ if (err != NULL) {\r
+ if (*err == '\0')\r
+ return 0;\r
+ PyErr_SetString(PyExc_TypeError, err);\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+ if (v == NULL) {\r
+ int rv = PyDict_DelItem(op->cl_dict, name);\r
+ if (rv < 0)\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "class %.50s has no attribute '%.400s'",\r
+ PyString_AS_STRING(op->cl_name), sname);\r
+ return rv;\r
+ }\r
+ else\r
+ return PyDict_SetItem(op->cl_dict, name, v);\r
+}\r
+\r
+static PyObject *\r
+class_repr(PyClassObject *op)\r
+{\r
+ PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__");\r
+ char *name;\r
+ if (op->cl_name == NULL || !PyString_Check(op->cl_name))\r
+ name = "?";\r
+ else\r
+ name = PyString_AsString(op->cl_name);\r
+ if (mod == NULL || !PyString_Check(mod))\r
+ return PyString_FromFormat("<class ?.%s at %p>", name, op);\r
+ else\r
+ return PyString_FromFormat("<class %s.%s at %p>",\r
+ PyString_AsString(mod),\r
+ name, op);\r
+}\r
+\r
+static PyObject *\r
+class_str(PyClassObject *op)\r
+{\r
+ PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__");\r
+ PyObject *name = op->cl_name;\r
+ PyObject *res;\r
+ Py_ssize_t m, n;\r
+\r
+ if (name == NULL || !PyString_Check(name))\r
+ return class_repr(op);\r
+ if (mod == NULL || !PyString_Check(mod)) {\r
+ Py_INCREF(name);\r
+ return name;\r
+ }\r
+ m = PyString_GET_SIZE(mod);\r
+ n = PyString_GET_SIZE(name);\r
+ res = PyString_FromStringAndSize((char *)NULL, m+1+n);\r
+ if (res != NULL) {\r
+ char *s = PyString_AS_STRING(res);\r
+ memcpy(s, PyString_AS_STRING(mod), m);\r
+ s += m;\r
+ *s++ = '.';\r
+ memcpy(s, PyString_AS_STRING(name), n);\r
+ }\r
+ return res;\r
+}\r
+\r
+static int\r
+class_traverse(PyClassObject *o, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(o->cl_bases);\r
+ Py_VISIT(o->cl_dict);\r
+ Py_VISIT(o->cl_name);\r
+ Py_VISIT(o->cl_getattr);\r
+ Py_VISIT(o->cl_setattr);\r
+ Py_VISIT(o->cl_delattr);\r
+ return 0;\r
+}\r
+\r
+PyTypeObject PyClass_Type = {\r
+ PyObject_HEAD_INIT(&PyType_Type)\r
+ 0,\r
+ "classobj",\r
+ sizeof(PyClassObject),\r
+ 0,\r
+ (destructor)class_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)class_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ PyInstance_New, /* tp_call */\r
+ (reprfunc)class_str, /* tp_str */\r
+ (getattrofunc)class_getattr, /* tp_getattro */\r
+ (setattrofunc)class_setattr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ class_doc, /* tp_doc */\r
+ (traverseproc)class_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ offsetof(PyClassObject, cl_weakreflist), /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ class_new, /* tp_new */\r
+};\r
+\r
+int\r
+PyClass_IsSubclass(PyObject *klass, PyObject *base)\r
+{\r
+ Py_ssize_t i, n;\r
+ PyClassObject *cp;\r
+ if (klass == base)\r
+ return 1;\r
+ if (PyTuple_Check(base)) {\r
+ n = PyTuple_GET_SIZE(base);\r
+ for (i = 0; i < n; i++) {\r
+ if (PyClass_IsSubclass(klass, PyTuple_GET_ITEM(base, i)))\r
+ return 1;\r
+ }\r
+ return 0;\r
+ }\r
+ if (klass == NULL || !PyClass_Check(klass))\r
+ return 0;\r
+ cp = (PyClassObject *)klass;\r
+ n = PyTuple_Size(cp->cl_bases);\r
+ for (i = 0; i < n; i++) {\r
+ if (PyClass_IsSubclass(PyTuple_GetItem(cp->cl_bases, i), base))\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+\r
+/* Instance objects */\r
+\r
+PyObject *\r
+PyInstance_NewRaw(PyObject *klass, PyObject *dict)\r
+{\r
+ PyInstanceObject *inst;\r
+\r
+ if (!PyClass_Check(klass)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ if (dict == NULL) {\r
+ dict = PyDict_New();\r
+ if (dict == NULL)\r
+ return NULL;\r
+ }\r
+ else {\r
+ if (!PyDict_Check(dict)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ Py_INCREF(dict);\r
+ }\r
+ inst = PyObject_GC_New(PyInstanceObject, &PyInstance_Type);\r
+ if (inst == NULL) {\r
+ Py_DECREF(dict);\r
+ return NULL;\r
+ }\r
+ inst->in_weakreflist = NULL;\r
+ Py_INCREF(klass);\r
+ inst->in_class = (PyClassObject *)klass;\r
+ inst->in_dict = dict;\r
+ _PyObject_GC_TRACK(inst);\r
+ return (PyObject *)inst;\r
+}\r
+\r
+PyObject *\r
+PyInstance_New(PyObject *klass, PyObject *arg, PyObject *kw)\r
+{\r
+ register PyInstanceObject *inst;\r
+ PyObject *init;\r
+ static PyObject *initstr;\r
+\r
+ if (initstr == NULL) {\r
+ initstr = PyString_InternFromString("__init__");\r
+ if (initstr == NULL)\r
+ return NULL;\r
+ }\r
+ inst = (PyInstanceObject *) PyInstance_NewRaw(klass, NULL);\r
+ if (inst == NULL)\r
+ return NULL;\r
+ init = instance_getattr2(inst, initstr);\r
+ if (init == NULL) {\r
+ if (PyErr_Occurred()) {\r
+ Py_DECREF(inst);\r
+ return NULL;\r
+ }\r
+ if ((arg != NULL && (!PyTuple_Check(arg) ||\r
+ PyTuple_Size(arg) != 0))\r
+ || (kw != NULL && (!PyDict_Check(kw) ||\r
+ PyDict_Size(kw) != 0))) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "this constructor takes no arguments");\r
+ Py_DECREF(inst);\r
+ inst = NULL;\r
+ }\r
+ }\r
+ else {\r
+ PyObject *res = PyEval_CallObjectWithKeywords(init, arg, kw);\r
+ Py_DECREF(init);\r
+ if (res == NULL) {\r
+ Py_DECREF(inst);\r
+ inst = NULL;\r
+ }\r
+ else {\r
+ if (res != Py_None) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__init__() should return None");\r
+ Py_DECREF(inst);\r
+ inst = NULL;\r
+ }\r
+ Py_DECREF(res);\r
+ }\r
+ }\r
+ return (PyObject *)inst;\r
+}\r
+\r
+/* Instance methods */\r
+\r
+PyDoc_STRVAR(instance_doc,\r
+"instance(class[, dict])\n\\r
+\n\\r
+Create an instance without calling its __init__() method.\n\\r
+The class must be a classic class.\n\\r
+If present, dict must be a dictionary or None.");\r
+\r
+static PyObject *\r
+instance_new(PyTypeObject* type, PyObject* args, PyObject *kw)\r
+{\r
+ PyObject *klass;\r
+ PyObject *dict = Py_None;\r
+\r
+ if (!PyArg_ParseTuple(args, "O!|O:instance",\r
+ &PyClass_Type, &klass, &dict))\r
+ return NULL;\r
+\r
+ if (dict == Py_None)\r
+ dict = NULL;\r
+ else if (!PyDict_Check(dict)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "instance() second arg must be dictionary or None");\r
+ return NULL;\r
+ }\r
+ return PyInstance_NewRaw(klass, dict);\r
+}\r
+\r
+\r
+static void\r
+instance_dealloc(register PyInstanceObject *inst)\r
+{\r
+ PyObject *error_type, *error_value, *error_traceback;\r
+ PyObject *del;\r
+ static PyObject *delstr;\r
+\r
+ _PyObject_GC_UNTRACK(inst);\r
+ if (inst->in_weakreflist != NULL)\r
+ PyObject_ClearWeakRefs((PyObject *) inst);\r
+\r
+ /* Temporarily resurrect the object. */\r
+ assert(inst->ob_type == &PyInstance_Type);\r
+ assert(inst->ob_refcnt == 0);\r
+ inst->ob_refcnt = 1;\r
+\r
+ /* Save the current exception, if any. */\r
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);\r
+ /* Execute __del__ method, if any. */\r
+ if (delstr == NULL) {\r
+ delstr = PyString_InternFromString("__del__");\r
+ if (delstr == NULL)\r
+ PyErr_WriteUnraisable((PyObject*)inst);\r
+ }\r
+ if (delstr && (del = instance_getattr2(inst, delstr)) != NULL) {\r
+ PyObject *res = PyEval_CallObject(del, (PyObject *)NULL);\r
+ if (res == NULL)\r
+ PyErr_WriteUnraisable(del);\r
+ else\r
+ Py_DECREF(res);\r
+ Py_DECREF(del);\r
+ }\r
+ /* Restore the saved exception. */\r
+ PyErr_Restore(error_type, error_value, error_traceback);\r
+\r
+ /* Undo the temporary resurrection; can't use DECREF here, it would\r
+ * cause a recursive call.\r
+ */\r
+ assert(inst->ob_refcnt > 0);\r
+ if (--inst->ob_refcnt == 0) {\r
+\r
+ /* New weakrefs could be created during the finalizer call.\r
+ If this occurs, clear them out without calling their\r
+ finalizers since they might rely on part of the object\r
+ being finalized that has already been destroyed. */\r
+ while (inst->in_weakreflist != NULL) {\r
+ _PyWeakref_ClearRef((PyWeakReference *)\r
+ (inst->in_weakreflist));\r
+ }\r
+\r
+ Py_DECREF(inst->in_class);\r
+ Py_XDECREF(inst->in_dict);\r
+ PyObject_GC_Del(inst);\r
+ }\r
+ else {\r
+ Py_ssize_t refcnt = inst->ob_refcnt;\r
+ /* __del__ resurrected it! Make it look like the original\r
+ * Py_DECREF never happened.\r
+ */\r
+ _Py_NewReference((PyObject *)inst);\r
+ inst->ob_refcnt = refcnt;\r
+ _PyObject_GC_TRACK(inst);\r
+ /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so\r
+ * we need to undo that. */\r
+ _Py_DEC_REFTOTAL;\r
+ /* If Py_TRACE_REFS, _Py_NewReference re-added self to the\r
+ * object chain, so no more to do there.\r
+ * If COUNT_ALLOCS, the original decref bumped tp_frees, and\r
+ * _Py_NewReference bumped tp_allocs: both of those need to be\r
+ * undone.\r
+ */\r
+#ifdef COUNT_ALLOCS\r
+ --inst->ob_type->tp_frees;\r
+ --inst->ob_type->tp_allocs;\r
+#endif\r
+ }\r
+}\r
+\r
+static PyObject *\r
+instance_getattr1(register PyInstanceObject *inst, PyObject *name)\r
+{\r
+ register PyObject *v;\r
+ register char *sname;\r
+\r
+ if (!PyString_Check(name)) {\r
+ PyErr_SetString(PyExc_TypeError, "attribute name must be a string");\r
+ return NULL;\r
+ }\r
+\r
+ sname = PyString_AsString(name);\r
+ if (sname[0] == '_' && sname[1] == '_') {\r
+ if (strcmp(sname, "__dict__") == 0) {\r
+ if (PyEval_GetRestricted()) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "instance.__dict__ not accessible in restricted mode");\r
+ return NULL;\r
+ }\r
+ Py_INCREF(inst->in_dict);\r
+ return inst->in_dict;\r
+ }\r
+ if (strcmp(sname, "__class__") == 0) {\r
+ Py_INCREF(inst->in_class);\r
+ return (PyObject *)inst->in_class;\r
+ }\r
+ }\r
+ v = instance_getattr2(inst, name);\r
+ if (v == NULL && !PyErr_Occurred()) {\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "%.50s instance has no attribute '%.400s'",\r
+ PyString_AS_STRING(inst->in_class->cl_name), sname);\r
+ }\r
+ return v;\r
+}\r
+\r
+static PyObject *\r
+instance_getattr2(register PyInstanceObject *inst, PyObject *name)\r
+{\r
+ register PyObject *v;\r
+ PyClassObject *klass;\r
+ descrgetfunc f;\r
+\r
+ v = PyDict_GetItem(inst->in_dict, name);\r
+ if (v != NULL) {\r
+ Py_INCREF(v);\r
+ return v;\r
+ }\r
+ v = class_lookup(inst->in_class, name, &klass);\r
+ if (v != NULL) {\r
+ Py_INCREF(v);\r
+ f = TP_DESCR_GET(v->ob_type);\r
+ if (f != NULL) {\r
+ PyObject *w = f(v, (PyObject *)inst,\r
+ (PyObject *)(inst->in_class));\r
+ Py_DECREF(v);\r
+ v = w;\r
+ }\r
+ }\r
+ return v;\r
+}\r
+\r
+static PyObject *\r
+instance_getattr(register PyInstanceObject *inst, PyObject *name)\r
+{\r
+ register PyObject *func, *res;\r
+ res = instance_getattr1(inst, name);\r
+ if (res == NULL && (func = inst->in_class->cl_getattr) != NULL) {\r
+ PyObject *args;\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ args = PyTuple_Pack(2, inst, name);\r
+ if (args == NULL)\r
+ return NULL;\r
+ res = PyEval_CallObject(func, args);\r
+ Py_DECREF(args);\r
+ }\r
+ return res;\r
+}\r
+\r
+/* See classobject.h comments: this only does dict lookups, and is always\r
+ * safe to call.\r
+ */\r
+PyObject *\r
+_PyInstance_Lookup(PyObject *pinst, PyObject *name)\r
+{\r
+ PyObject *v;\r
+ PyClassObject *klass;\r
+ PyInstanceObject *inst; /* pinst cast to the right type */\r
+\r
+ assert(PyInstance_Check(pinst));\r
+ inst = (PyInstanceObject *)pinst;\r
+\r
+ assert(PyString_Check(name));\r
+\r
+ v = PyDict_GetItem(inst->in_dict, name);\r
+ if (v == NULL)\r
+ v = class_lookup(inst->in_class, name, &klass);\r
+ return v;\r
+}\r
+\r
+static int\r
+instance_setattr1(PyInstanceObject *inst, PyObject *name, PyObject *v)\r
+{\r
+ if (v == NULL) {\r
+ int rv = PyDict_DelItem(inst->in_dict, name);\r
+ if (rv < 0)\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "%.50s instance has no attribute '%.400s'",\r
+ PyString_AS_STRING(inst->in_class->cl_name),\r
+ PyString_AS_STRING(name));\r
+ return rv;\r
+ }\r
+ else\r
+ return PyDict_SetItem(inst->in_dict, name, v);\r
+}\r
+\r
+static int\r
+instance_setattr(PyInstanceObject *inst, PyObject *name, PyObject *v)\r
+{\r
+ PyObject *func, *args, *res, *tmp;\r
+ char *sname;\r
+\r
+ if (!PyString_Check(name)) {\r
+ PyErr_SetString(PyExc_TypeError, "attribute name must be a string");\r
+ return -1;\r
+ }\r
+\r
+ sname = PyString_AsString(name);\r
+ if (sname[0] == '_' && sname[1] == '_') {\r
+ Py_ssize_t n = PyString_Size(name);\r
+ if (sname[n-1] == '_' && sname[n-2] == '_') {\r
+ if (strcmp(sname, "__dict__") == 0) {\r
+ if (PyEval_GetRestricted()) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "__dict__ not accessible in restricted mode");\r
+ return -1;\r
+ }\r
+ if (v == NULL || !PyDict_Check(v)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__dict__ must be set to a dictionary");\r
+ return -1;\r
+ }\r
+ tmp = inst->in_dict;\r
+ Py_INCREF(v);\r
+ inst->in_dict = v;\r
+ Py_DECREF(tmp);\r
+ return 0;\r
+ }\r
+ if (strcmp(sname, "__class__") == 0) {\r
+ if (PyEval_GetRestricted()) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "__class__ not accessible in restricted mode");\r
+ return -1;\r
+ }\r
+ if (v == NULL || !PyClass_Check(v)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__class__ must be set to a class");\r
+ return -1;\r
+ }\r
+ tmp = (PyObject *)(inst->in_class);\r
+ Py_INCREF(v);\r
+ inst->in_class = (PyClassObject *)v;\r
+ Py_DECREF(tmp);\r
+ return 0;\r
+ }\r
+ }\r
+ }\r
+ if (v == NULL)\r
+ func = inst->in_class->cl_delattr;\r
+ else\r
+ func = inst->in_class->cl_setattr;\r
+ if (func == NULL)\r
+ return instance_setattr1(inst, name, v);\r
+ if (v == NULL)\r
+ args = PyTuple_Pack(2, inst, name);\r
+ else\r
+ args = PyTuple_Pack(3, inst, name, v);\r
+ if (args == NULL)\r
+ return -1;\r
+ res = PyEval_CallObject(func, args);\r
+ Py_DECREF(args);\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+instance_repr(PyInstanceObject *inst)\r
+{\r
+ PyObject *func;\r
+ PyObject *res;\r
+ static PyObject *reprstr;\r
+\r
+ if (reprstr == NULL) {\r
+ reprstr = PyString_InternFromString("__repr__");\r
+ if (reprstr == NULL)\r
+ return NULL;\r
+ }\r
+ func = instance_getattr(inst, reprstr);\r
+ if (func == NULL) {\r
+ PyObject *classname, *mod;\r
+ char *cname;\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ classname = inst->in_class->cl_name;\r
+ mod = PyDict_GetItemString(inst->in_class->cl_dict,\r
+ "__module__");\r
+ if (classname != NULL && PyString_Check(classname))\r
+ cname = PyString_AsString(classname);\r
+ else\r
+ cname = "?";\r
+ if (mod == NULL || !PyString_Check(mod))\r
+ return PyString_FromFormat("<?.%s instance at %p>",\r
+ cname, inst);\r
+ else\r
+ return PyString_FromFormat("<%s.%s instance at %p>",\r
+ PyString_AsString(mod),\r
+ cname, inst);\r
+ }\r
+ res = PyEval_CallObject(func, (PyObject *)NULL);\r
+ Py_DECREF(func);\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+instance_str(PyInstanceObject *inst)\r
+{\r
+ PyObject *func;\r
+ PyObject *res;\r
+ static PyObject *strstr;\r
+\r
+ if (strstr == NULL) {\r
+ strstr = PyString_InternFromString("__str__");\r
+ if (strstr == NULL)\r
+ return NULL;\r
+ }\r
+ func = instance_getattr(inst, strstr);\r
+ if (func == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ return instance_repr(inst);\r
+ }\r
+ res = PyEval_CallObject(func, (PyObject *)NULL);\r
+ Py_DECREF(func);\r
+ return res;\r
+}\r
+\r
+static long\r
+instance_hash(PyInstanceObject *inst)\r
+{\r
+ PyObject *func;\r
+ PyObject *res;\r
+ long outcome;\r
+ static PyObject *hashstr, *eqstr, *cmpstr;\r
+\r
+ if (hashstr == NULL) {\r
+ hashstr = PyString_InternFromString("__hash__");\r
+ if (hashstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, hashstr);\r
+ if (func == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ /* If there is no __eq__ and no __cmp__ method, we hash on the\r
+ address. If an __eq__ or __cmp__ method exists, there must\r
+ be a __hash__. */\r
+ if (eqstr == NULL) {\r
+ eqstr = PyString_InternFromString("__eq__");\r
+ if (eqstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, eqstr);\r
+ if (func == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ if (cmpstr == NULL) {\r
+ cmpstr = PyString_InternFromString("__cmp__");\r
+ if (cmpstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, cmpstr);\r
+ if (func == NULL) {\r
+ if (!PyErr_ExceptionMatches(\r
+ PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ return _Py_HashPointer(inst);\r
+ }\r
+ }\r
+ Py_XDECREF(func);\r
+ PyErr_SetString(PyExc_TypeError, "unhashable instance");\r
+ return -1;\r
+ }\r
+ res = PyEval_CallObject(func, (PyObject *)NULL);\r
+ Py_DECREF(func);\r
+ if (res == NULL)\r
+ return -1;\r
+ if (PyInt_Check(res) || PyLong_Check(res))\r
+ /* This already converts a -1 result to -2. */\r
+ outcome = res->ob_type->tp_hash(res);\r
+ else {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__hash__() should return an int");\r
+ outcome = -1;\r
+ }\r
+ Py_DECREF(res);\r
+ return outcome;\r
+}\r
+\r
+static int\r
+instance_traverse(PyInstanceObject *o, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(o->in_class);\r
+ Py_VISIT(o->in_dict);\r
+ return 0;\r
+}\r
+\r
+static PyObject *getitemstr, *setitemstr, *delitemstr, *lenstr;\r
+static PyObject *iterstr, *nextstr;\r
+\r
+static Py_ssize_t\r
+instance_length(PyInstanceObject *inst)\r
+{\r
+ PyObject *func;\r
+ PyObject *res;\r
+ Py_ssize_t outcome;\r
+\r
+ if (lenstr == NULL) {\r
+ lenstr = PyString_InternFromString("__len__");\r
+ if (lenstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, lenstr);\r
+ if (func == NULL)\r
+ return -1;\r
+ res = PyEval_CallObject(func, (PyObject *)NULL);\r
+ Py_DECREF(func);\r
+ if (res == NULL)\r
+ return -1;\r
+ if (PyInt_Check(res)) {\r
+ outcome = PyInt_AsSsize_t(res);\r
+ if (outcome == -1 && PyErr_Occurred()) {\r
+ Py_DECREF(res);\r
+ return -1;\r
+ }\r
+#if SIZEOF_SIZE_T < SIZEOF_INT\r
+ /* Overflow check -- range of PyInt is more than C int */\r
+ if (outcome != (int)outcome) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "__len__() should return 0 <= outcome < 2**31");\r
+ outcome = -1;\r
+ }\r
+ else\r
+#endif\r
+ if (outcome < 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "__len__() should return >= 0");\r
+ outcome = -1;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__len__() should return an int");\r
+ outcome = -1;\r
+ }\r
+ Py_DECREF(res);\r
+ return outcome;\r
+}\r
+\r
+static PyObject *\r
+instance_subscript(PyInstanceObject *inst, PyObject *key)\r
+{\r
+ PyObject *func;\r
+ PyObject *arg;\r
+ PyObject *res;\r
+\r
+ if (getitemstr == NULL) {\r
+ getitemstr = PyString_InternFromString("__getitem__");\r
+ if (getitemstr == NULL)\r
+ return NULL;\r
+ }\r
+ func = instance_getattr(inst, getitemstr);\r
+ if (func == NULL)\r
+ return NULL;\r
+ arg = PyTuple_Pack(1, key);\r
+ if (arg == NULL) {\r
+ Py_DECREF(func);\r
+ return NULL;\r
+ }\r
+ res = PyEval_CallObject(func, arg);\r
+ Py_DECREF(func);\r
+ Py_DECREF(arg);\r
+ return res;\r
+}\r
+\r
+static int\r
+instance_ass_subscript(PyInstanceObject *inst, PyObject *key, PyObject *value)\r
+{\r
+ PyObject *func;\r
+ PyObject *arg;\r
+ PyObject *res;\r
+\r
+ if (value == NULL) {\r
+ if (delitemstr == NULL) {\r
+ delitemstr = PyString_InternFromString("__delitem__");\r
+ if (delitemstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, delitemstr);\r
+ }\r
+ else {\r
+ if (setitemstr == NULL) {\r
+ setitemstr = PyString_InternFromString("__setitem__");\r
+ if (setitemstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, setitemstr);\r
+ }\r
+ if (func == NULL)\r
+ return -1;\r
+ if (value == NULL)\r
+ arg = PyTuple_Pack(1, key);\r
+ else\r
+ arg = PyTuple_Pack(2, key, value);\r
+ if (arg == NULL) {\r
+ Py_DECREF(func);\r
+ return -1;\r
+ }\r
+ res = PyEval_CallObject(func, arg);\r
+ Py_DECREF(func);\r
+ Py_DECREF(arg);\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static PyMappingMethods instance_as_mapping = {\r
+ (lenfunc)instance_length, /* mp_length */\r
+ (binaryfunc)instance_subscript, /* mp_subscript */\r
+ (objobjargproc)instance_ass_subscript, /* mp_ass_subscript */\r
+};\r
+\r
+static PyObject *\r
+instance_item(PyInstanceObject *inst, Py_ssize_t i)\r
+{\r
+ PyObject *func, *res;\r
+\r
+ if (getitemstr == NULL) {\r
+ getitemstr = PyString_InternFromString("__getitem__");\r
+ if (getitemstr == NULL)\r
+ return NULL;\r
+ }\r
+ func = instance_getattr(inst, getitemstr);\r
+ if (func == NULL)\r
+ return NULL;\r
+ res = PyObject_CallFunction(func, "n", i);\r
+ Py_DECREF(func);\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+instance_slice(PyInstanceObject *inst, Py_ssize_t i, Py_ssize_t j)\r
+{\r
+ PyObject *func, *arg, *res;\r
+ static PyObject *getslicestr;\r
+\r
+ if (getslicestr == NULL) {\r
+ getslicestr = PyString_InternFromString("__getslice__");\r
+ if (getslicestr == NULL)\r
+ return NULL;\r
+ }\r
+ func = instance_getattr(inst, getslicestr);\r
+\r
+ if (func == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+\r
+ if (getitemstr == NULL) {\r
+ getitemstr = PyString_InternFromString("__getitem__");\r
+ if (getitemstr == NULL)\r
+ return NULL;\r
+ }\r
+ func = instance_getattr(inst, getitemstr);\r
+ if (func == NULL)\r
+ return NULL;\r
+ arg = Py_BuildValue("(N)", _PySlice_FromIndices(i, j));\r
+ }\r
+ else {\r
+ if (PyErr_WarnPy3k("in 3.x, __getslice__ has been removed; "\r
+ "use __getitem__", 1) < 0) {\r
+ Py_DECREF(func);\r
+ return NULL;\r
+ }\r
+ arg = Py_BuildValue("(nn)", i, j);\r
+ }\r
+\r
+ if (arg == NULL) {\r
+ Py_DECREF(func);\r
+ return NULL;\r
+ }\r
+ res = PyEval_CallObject(func, arg);\r
+ Py_DECREF(func);\r
+ Py_DECREF(arg);\r
+ return res;\r
+}\r
+\r
+static int\r
+instance_ass_item(PyInstanceObject *inst, Py_ssize_t i, PyObject *item)\r
+{\r
+ PyObject *func, *arg, *res;\r
+\r
+ if (item == NULL) {\r
+ if (delitemstr == NULL) {\r
+ delitemstr = PyString_InternFromString("__delitem__");\r
+ if (delitemstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, delitemstr);\r
+ }\r
+ else {\r
+ if (setitemstr == NULL) {\r
+ setitemstr = PyString_InternFromString("__setitem__");\r
+ if (setitemstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, setitemstr);\r
+ }\r
+ if (func == NULL)\r
+ return -1;\r
+ if (item == NULL)\r
+ arg = Py_BuildValue("(n)", i);\r
+ else\r
+ arg = Py_BuildValue("(nO)", i, item);\r
+ if (arg == NULL) {\r
+ Py_DECREF(func);\r
+ return -1;\r
+ }\r
+ res = PyEval_CallObject(func, arg);\r
+ Py_DECREF(func);\r
+ Py_DECREF(arg);\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static int\r
+instance_ass_slice(PyInstanceObject *inst, Py_ssize_t i, Py_ssize_t j, PyObject *value)\r
+{\r
+ PyObject *func, *arg, *res;\r
+ static PyObject *setslicestr, *delslicestr;\r
+\r
+ if (value == NULL) {\r
+ if (delslicestr == NULL) {\r
+ delslicestr =\r
+ PyString_InternFromString("__delslice__");\r
+ if (delslicestr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, delslicestr);\r
+ if (func == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ if (delitemstr == NULL) {\r
+ delitemstr =\r
+ PyString_InternFromString("__delitem__");\r
+ if (delitemstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, delitemstr);\r
+ if (func == NULL)\r
+ return -1;\r
+\r
+ arg = Py_BuildValue("(N)",\r
+ _PySlice_FromIndices(i, j));\r
+ }\r
+ else {\r
+ if (PyErr_WarnPy3k("in 3.x, __delslice__ has been "\r
+ "removed; use __delitem__", 1) < 0) {\r
+ Py_DECREF(func);\r
+ return -1;\r
+ }\r
+ arg = Py_BuildValue("(nn)", i, j);\r
+ }\r
+ }\r
+ else {\r
+ if (setslicestr == NULL) {\r
+ setslicestr =\r
+ PyString_InternFromString("__setslice__");\r
+ if (setslicestr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, setslicestr);\r
+ if (func == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ if (setitemstr == NULL) {\r
+ setitemstr =\r
+ PyString_InternFromString("__setitem__");\r
+ if (setitemstr == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, setitemstr);\r
+ if (func == NULL)\r
+ return -1;\r
+\r
+ arg = Py_BuildValue("(NO)",\r
+ _PySlice_FromIndices(i, j), value);\r
+ }\r
+ else {\r
+ if (PyErr_WarnPy3k("in 3.x, __setslice__ has been "\r
+ "removed; use __setitem__", 1) < 0) {\r
+ Py_DECREF(func);\r
+ return -1;\r
+ }\r
+ arg = Py_BuildValue("(nnO)", i, j, value);\r
+ }\r
+ }\r
+ if (arg == NULL) {\r
+ Py_DECREF(func);\r
+ return -1;\r
+ }\r
+ res = PyEval_CallObject(func, arg);\r
+ Py_DECREF(func);\r
+ Py_DECREF(arg);\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static int\r
+instance_contains(PyInstanceObject *inst, PyObject *member)\r
+{\r
+ static PyObject *__contains__;\r
+ PyObject *func;\r
+\r
+ /* Try __contains__ first.\r
+ * If that can't be done, try iterator-based searching.\r
+ */\r
+\r
+ if(__contains__ == NULL) {\r
+ __contains__ = PyString_InternFromString("__contains__");\r
+ if(__contains__ == NULL)\r
+ return -1;\r
+ }\r
+ func = instance_getattr(inst, __contains__);\r
+ if (func) {\r
+ PyObject *res;\r
+ int ret;\r
+ PyObject *arg = PyTuple_Pack(1, member);\r
+ if(arg == NULL) {\r
+ Py_DECREF(func);\r
+ return -1;\r
+ }\r
+ res = PyEval_CallObject(func, arg);\r
+ Py_DECREF(func);\r
+ Py_DECREF(arg);\r
+ if(res == NULL)\r
+ return -1;\r
+ ret = PyObject_IsTrue(res);\r
+ Py_DECREF(res);\r
+ return ret;\r
+ }\r
+\r
+ /* Couldn't find __contains__. */\r
+ if (PyErr_ExceptionMatches(PyExc_AttributeError)) {\r
+ Py_ssize_t rc;\r
+ /* Assume the failure was simply due to that there is no\r
+ * __contains__ attribute, and try iterating instead.\r
+ */\r
+ PyErr_Clear();\r
+ rc = _PySequence_IterSearch((PyObject *)inst, member,\r
+ PY_ITERSEARCH_CONTAINS);\r
+ if (rc >= 0)\r
+ return rc > 0;\r
+ }\r
+ return -1;\r
+}\r
+\r
+static PySequenceMethods\r
+instance_as_sequence = {\r
+ (lenfunc)instance_length, /* sq_length */\r
+ 0, /* sq_concat */\r
+ 0, /* sq_repeat */\r
+ (ssizeargfunc)instance_item, /* sq_item */\r
+ (ssizessizeargfunc)instance_slice, /* sq_slice */\r
+ (ssizeobjargproc)instance_ass_item, /* sq_ass_item */\r
+ (ssizessizeobjargproc)instance_ass_slice,/* sq_ass_slice */\r
+ (objobjproc)instance_contains, /* sq_contains */\r
+};\r
+\r
+static PyObject *\r
+generic_unary_op(PyInstanceObject *self, PyObject *methodname)\r
+{\r
+ PyObject *func, *res;\r
+\r
+ if ((func = instance_getattr(self, methodname)) == NULL)\r
+ return NULL;\r
+ res = PyEval_CallObject(func, (PyObject *)NULL);\r
+ Py_DECREF(func);\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+generic_binary_op(PyObject *v, PyObject *w, char *opname)\r
+{\r
+ PyObject *result;\r
+ PyObject *args;\r
+ PyObject *func = PyObject_GetAttrString(v, opname);\r
+ if (func == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ args = PyTuple_Pack(1, w);\r
+ if (args == NULL) {\r
+ Py_DECREF(func);\r
+ return NULL;\r
+ }\r
+ result = PyEval_CallObject(func, args);\r
+ Py_DECREF(args);\r
+ Py_DECREF(func);\r
+ return result;\r
+}\r
+\r
+\r
+static PyObject *coerce_obj;\r
+\r
+/* Try one half of a binary operator involving a class instance. */\r
+static PyObject *\r
+half_binop(PyObject *v, PyObject *w, char *opname, binaryfunc thisfunc,\r
+ int swapped)\r
+{\r
+ PyObject *args;\r
+ PyObject *coercefunc;\r
+ PyObject *coerced = NULL;\r
+ PyObject *v1;\r
+ PyObject *result;\r
+\r
+ if (!PyInstance_Check(v)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+\r
+ if (coerce_obj == NULL) {\r
+ coerce_obj = PyString_InternFromString("__coerce__");\r
+ if (coerce_obj == NULL)\r
+ return NULL;\r
+ }\r
+ coercefunc = PyObject_GetAttr(v, coerce_obj);\r
+ if (coercefunc == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ return generic_binary_op(v, w, opname);\r
+ }\r
+\r
+ args = PyTuple_Pack(1, w);\r
+ if (args == NULL) {\r
+ Py_DECREF(coercefunc);\r
+ return NULL;\r
+ }\r
+ coerced = PyEval_CallObject(coercefunc, args);\r
+ Py_DECREF(args);\r
+ Py_DECREF(coercefunc);\r
+ if (coerced == NULL) {\r
+ return NULL;\r
+ }\r
+ if (coerced == Py_None || coerced == Py_NotImplemented) {\r
+ Py_DECREF(coerced);\r
+ return generic_binary_op(v, w, opname);\r
+ }\r
+ if (!PyTuple_Check(coerced) || PyTuple_Size(coerced) != 2) {\r
+ Py_DECREF(coerced);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "coercion should return None or 2-tuple");\r
+ return NULL;\r
+ }\r
+ v1 = PyTuple_GetItem(coerced, 0);\r
+ w = PyTuple_GetItem(coerced, 1);\r
+ if (v1->ob_type == v->ob_type && PyInstance_Check(v)) {\r
+ /* prevent recursion if __coerce__ returns self as the first\r
+ * argument */\r
+ result = generic_binary_op(v1, w, opname);\r
+ } else {\r
+ if (Py_EnterRecursiveCall(" after coercion"))\r
+ return NULL;\r
+ if (swapped)\r
+ result = (thisfunc)(w, v1);\r
+ else\r
+ result = (thisfunc)(v1, w);\r
+ Py_LeaveRecursiveCall();\r
+ }\r
+ Py_DECREF(coerced);\r
+ return result;\r
+}\r
+\r
+/* Implement a binary operator involving at least one class instance. */\r
+static PyObject *\r
+do_binop(PyObject *v, PyObject *w, char *opname, char *ropname,\r
+ binaryfunc thisfunc)\r
+{\r
+ PyObject *result = half_binop(v, w, opname, thisfunc, 0);\r
+ if (result == Py_NotImplemented) {\r
+ Py_DECREF(result);\r
+ result = half_binop(w, v, ropname, thisfunc, 1);\r
+ }\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+do_binop_inplace(PyObject *v, PyObject *w, char *iopname, char *opname,\r
+ char *ropname, binaryfunc thisfunc)\r
+{\r
+ PyObject *result = half_binop(v, w, iopname, thisfunc, 0);\r
+ if (result == Py_NotImplemented) {\r
+ Py_DECREF(result);\r
+ result = do_binop(v, w, opname, ropname, thisfunc);\r
+ }\r
+ return result;\r
+}\r
+\r
+static int\r
+instance_coerce(PyObject **pv, PyObject **pw)\r
+{\r
+ PyObject *v = *pv;\r
+ PyObject *w = *pw;\r
+ PyObject *coercefunc;\r
+ PyObject *args;\r
+ PyObject *coerced;\r
+\r
+ if (coerce_obj == NULL) {\r
+ coerce_obj = PyString_InternFromString("__coerce__");\r
+ if (coerce_obj == NULL)\r
+ return -1;\r
+ }\r
+ coercefunc = PyObject_GetAttr(v, coerce_obj);\r
+ if (coercefunc == NULL) {\r
+ /* No __coerce__ method */\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ return 1;\r
+ }\r
+ /* Has __coerce__ method: call it */\r
+ args = PyTuple_Pack(1, w);\r
+ if (args == NULL) {\r
+ return -1;\r
+ }\r
+ coerced = PyEval_CallObject(coercefunc, args);\r
+ Py_DECREF(args);\r
+ Py_DECREF(coercefunc);\r
+ if (coerced == NULL) {\r
+ /* __coerce__ call raised an exception */\r
+ return -1;\r
+ }\r
+ if (coerced == Py_None || coerced == Py_NotImplemented) {\r
+ /* __coerce__ says "I can't do it" */\r
+ Py_DECREF(coerced);\r
+ return 1;\r
+ }\r
+ if (!PyTuple_Check(coerced) || PyTuple_Size(coerced) != 2) {\r
+ /* __coerce__ return value is malformed */\r
+ Py_DECREF(coerced);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "coercion should return None or 2-tuple");\r
+ return -1;\r
+ }\r
+ /* __coerce__ returned two new values */\r
+ *pv = PyTuple_GetItem(coerced, 0);\r
+ *pw = PyTuple_GetItem(coerced, 1);\r
+ Py_INCREF(*pv);\r
+ Py_INCREF(*pw);\r
+ Py_DECREF(coerced);\r
+ return 0;\r
+}\r
+\r
+#define UNARY(funcname, methodname) \\r
+static PyObject *funcname(PyInstanceObject *self) { \\r
+ static PyObject *o; \\r
+ if (o == NULL) { o = PyString_InternFromString(methodname); \\r
+ if (o == NULL) return NULL; } \\r
+ return generic_unary_op(self, o); \\r
+}\r
+\r
+/* unary function with a fallback */\r
+#define UNARY_FB(funcname, methodname, funcname_fb) \\r
+static PyObject *funcname(PyInstanceObject *self) { \\r
+ static PyObject *o; \\r
+ if (o == NULL) { o = PyString_InternFromString(methodname); \\r
+ if (o == NULL) return NULL; } \\r
+ if (PyObject_HasAttr((PyObject*)self, o)) \\r
+ return generic_unary_op(self, o); \\r
+ else \\r
+ return funcname_fb(self); \\r
+}\r
+\r
+#define BINARY(f, m, n) \\r
+static PyObject *f(PyObject *v, PyObject *w) { \\r
+ return do_binop(v, w, "__" m "__", "__r" m "__", n); \\r
+}\r
+\r
+#define BINARY_INPLACE(f, m, n) \\r
+static PyObject *f(PyObject *v, PyObject *w) { \\r
+ return do_binop_inplace(v, w, "__i" m "__", "__" m "__", \\r
+ "__r" m "__", n); \\r
+}\r
+\r
+UNARY(instance_neg, "__neg__")\r
+UNARY(instance_pos, "__pos__")\r
+UNARY(instance_abs, "__abs__")\r
+\r
+BINARY(instance_or, "or", PyNumber_Or)\r
+BINARY(instance_and, "and", PyNumber_And)\r
+BINARY(instance_xor, "xor", PyNumber_Xor)\r
+BINARY(instance_lshift, "lshift", PyNumber_Lshift)\r
+BINARY(instance_rshift, "rshift", PyNumber_Rshift)\r
+BINARY(instance_add, "add", PyNumber_Add)\r
+BINARY(instance_sub, "sub", PyNumber_Subtract)\r
+BINARY(instance_mul, "mul", PyNumber_Multiply)\r
+BINARY(instance_div, "div", PyNumber_Divide)\r
+BINARY(instance_mod, "mod", PyNumber_Remainder)\r
+BINARY(instance_divmod, "divmod", PyNumber_Divmod)\r
+BINARY(instance_floordiv, "floordiv", PyNumber_FloorDivide)\r
+BINARY(instance_truediv, "truediv", PyNumber_TrueDivide)\r
+\r
+BINARY_INPLACE(instance_ior, "or", PyNumber_InPlaceOr)\r
+BINARY_INPLACE(instance_ixor, "xor", PyNumber_InPlaceXor)\r
+BINARY_INPLACE(instance_iand, "and", PyNumber_InPlaceAnd)\r
+BINARY_INPLACE(instance_ilshift, "lshift", PyNumber_InPlaceLshift)\r
+BINARY_INPLACE(instance_irshift, "rshift", PyNumber_InPlaceRshift)\r
+BINARY_INPLACE(instance_iadd, "add", PyNumber_InPlaceAdd)\r
+BINARY_INPLACE(instance_isub, "sub", PyNumber_InPlaceSubtract)\r
+BINARY_INPLACE(instance_imul, "mul", PyNumber_InPlaceMultiply)\r
+BINARY_INPLACE(instance_idiv, "div", PyNumber_InPlaceDivide)\r
+BINARY_INPLACE(instance_imod, "mod", PyNumber_InPlaceRemainder)\r
+BINARY_INPLACE(instance_ifloordiv, "floordiv", PyNumber_InPlaceFloorDivide)\r
+BINARY_INPLACE(instance_itruediv, "truediv", PyNumber_InPlaceTrueDivide)\r
+\r
+/* Try a 3-way comparison, returning an int; v is an instance. Return:\r
+ -2 for an exception;\r
+ -1 if v < w;\r
+ 0 if v == w;\r
+ 1 if v > w;\r
+ 2 if this particular 3-way comparison is not implemented or undefined.\r
+*/\r
+static int\r
+half_cmp(PyObject *v, PyObject *w)\r
+{\r
+ static PyObject *cmp_obj;\r
+ PyObject *args;\r
+ PyObject *cmp_func;\r
+ PyObject *result;\r
+ long l;\r
+\r
+ assert(PyInstance_Check(v));\r
+\r
+ if (cmp_obj == NULL) {\r
+ cmp_obj = PyString_InternFromString("__cmp__");\r
+ if (cmp_obj == NULL)\r
+ return -2;\r
+ }\r
+\r
+ cmp_func = PyObject_GetAttr(v, cmp_obj);\r
+ if (cmp_func == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -2;\r
+ PyErr_Clear();\r
+ return 2;\r
+ }\r
+\r
+ args = PyTuple_Pack(1, w);\r
+ if (args == NULL) {\r
+ Py_DECREF(cmp_func);\r
+ return -2;\r
+ }\r
+\r
+ result = PyEval_CallObject(cmp_func, args);\r
+ Py_DECREF(args);\r
+ Py_DECREF(cmp_func);\r
+\r
+ if (result == NULL)\r
+ return -2;\r
+\r
+ if (result == Py_NotImplemented) {\r
+ Py_DECREF(result);\r
+ return 2;\r
+ }\r
+\r
+ l = PyInt_AsLong(result);\r
+ Py_DECREF(result);\r
+ if (l == -1 && PyErr_Occurred()) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "comparison did not return an int");\r
+ return -2;\r
+ }\r
+\r
+ return l < 0 ? -1 : l > 0 ? 1 : 0;\r
+}\r
+\r
+/* Try a 3-way comparison, returning an int; either v or w is an instance.\r
+ We first try a coercion. Return:\r
+ -2 for an exception;\r
+ -1 if v < w;\r
+ 0 if v == w;\r
+ 1 if v > w;\r
+ 2 if this particular 3-way comparison is not implemented or undefined.\r
+ THIS IS ONLY CALLED FROM object.c!\r
+*/\r
+static int\r
+instance_compare(PyObject *v, PyObject *w)\r
+{\r
+ int c;\r
+\r
+ c = PyNumber_CoerceEx(&v, &w);\r
+ if (c < 0)\r
+ return -2;\r
+ if (c == 0) {\r
+ /* If neither is now an instance, use regular comparison */\r
+ if (!PyInstance_Check(v) && !PyInstance_Check(w)) {\r
+ c = PyObject_Compare(v, w);\r
+ Py_DECREF(v);\r
+ Py_DECREF(w);\r
+ if (PyErr_Occurred())\r
+ return -2;\r
+ return c < 0 ? -1 : c > 0 ? 1 : 0;\r
+ }\r
+ }\r
+ else {\r
+ /* The coercion didn't do anything.\r
+ Treat this the same as returning v and w unchanged. */\r
+ Py_INCREF(v);\r
+ Py_INCREF(w);\r
+ }\r
+\r
+ if (PyInstance_Check(v)) {\r
+ c = half_cmp(v, w);\r
+ if (c <= 1) {\r
+ Py_DECREF(v);\r
+ Py_DECREF(w);\r
+ return c;\r
+ }\r
+ }\r
+ if (PyInstance_Check(w)) {\r
+ c = half_cmp(w, v);\r
+ if (c <= 1) {\r
+ Py_DECREF(v);\r
+ Py_DECREF(w);\r
+ if (c >= -1)\r
+ c = -c;\r
+ return c;\r
+ }\r
+ }\r
+ Py_DECREF(v);\r
+ Py_DECREF(w);\r
+ return 2;\r
+}\r
+\r
+static int\r
+instance_nonzero(PyInstanceObject *self)\r
+{\r
+ PyObject *func, *res;\r
+ long outcome;\r
+ static PyObject *nonzerostr;\r
+\r
+ if (nonzerostr == NULL) {\r
+ nonzerostr = PyString_InternFromString("__nonzero__");\r
+ if (nonzerostr == NULL)\r
+ return -1;\r
+ }\r
+ if ((func = instance_getattr(self, nonzerostr)) == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ if (lenstr == NULL) {\r
+ lenstr = PyString_InternFromString("__len__");\r
+ if (lenstr == NULL)\r
+ return -1;\r
+ }\r
+ if ((func = instance_getattr(self, lenstr)) == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ /* Fall back to the default behavior:\r
+ all instances are nonzero */\r
+ return 1;\r
+ }\r
+ }\r
+ res = PyEval_CallObject(func, (PyObject *)NULL);\r
+ Py_DECREF(func);\r
+ if (res == NULL)\r
+ return -1;\r
+ if (!PyInt_Check(res)) {\r
+ Py_DECREF(res);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__nonzero__ should return an int");\r
+ return -1;\r
+ }\r
+ outcome = PyInt_AsLong(res);\r
+ Py_DECREF(res);\r
+ if (outcome < 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "__nonzero__ should return >= 0");\r
+ return -1;\r
+ }\r
+ return outcome > 0;\r
+}\r
+\r
+static PyObject *\r
+instance_index(PyInstanceObject *self)\r
+{\r
+ PyObject *func, *res;\r
+ static PyObject *indexstr = NULL;\r
+\r
+ if (indexstr == NULL) {\r
+ indexstr = PyString_InternFromString("__index__");\r
+ if (indexstr == NULL)\r
+ return NULL;\r
+ }\r
+ if ((func = instance_getattr(self, indexstr)) == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "object cannot be interpreted as an index");\r
+ return NULL;\r
+ }\r
+ res = PyEval_CallObject(func, (PyObject *)NULL);\r
+ Py_DECREF(func);\r
+ return res;\r
+}\r
+\r
+\r
+UNARY(instance_invert, "__invert__")\r
+UNARY(_instance_trunc, "__trunc__")\r
+\r
+static PyObject *\r
+instance_int(PyInstanceObject *self)\r
+{\r
+ PyObject *truncated;\r
+ static PyObject *int_name;\r
+ if (int_name == NULL) {\r
+ int_name = PyString_InternFromString("__int__");\r
+ if (int_name == NULL)\r
+ return NULL;\r
+ }\r
+ if (PyObject_HasAttr((PyObject*)self, int_name))\r
+ return generic_unary_op(self, int_name);\r
+\r
+ truncated = _instance_trunc(self);\r
+ /* __trunc__ is specified to return an Integral type, but\r
+ int() needs to return an int. */\r
+ return _PyNumber_ConvertIntegralToInt(\r
+ truncated,\r
+ "__trunc__ returned non-Integral (type %.200s)");\r
+}\r
+\r
+UNARY_FB(instance_long, "__long__", instance_int)\r
+UNARY(instance_float, "__float__")\r
+UNARY(instance_oct, "__oct__")\r
+UNARY(instance_hex, "__hex__")\r
+\r
+static PyObject *\r
+bin_power(PyObject *v, PyObject *w)\r
+{\r
+ return PyNumber_Power(v, w, Py_None);\r
+}\r
+\r
+/* This version is for ternary calls only (z != None) */\r
+static PyObject *\r
+instance_pow(PyObject *v, PyObject *w, PyObject *z)\r
+{\r
+ if (z == Py_None) {\r
+ return do_binop(v, w, "__pow__", "__rpow__", bin_power);\r
+ }\r
+ else {\r
+ PyObject *func;\r
+ PyObject *args;\r
+ PyObject *result;\r
+\r
+ /* XXX Doesn't do coercions... */\r
+ func = PyObject_GetAttrString(v, "__pow__");\r
+ if (func == NULL)\r
+ return NULL;\r
+ args = PyTuple_Pack(2, w, z);\r
+ if (args == NULL) {\r
+ Py_DECREF(func);\r
+ return NULL;\r
+ }\r
+ result = PyEval_CallObject(func, args);\r
+ Py_DECREF(func);\r
+ Py_DECREF(args);\r
+ return result;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+bin_inplace_power(PyObject *v, PyObject *w)\r
+{\r
+ return PyNumber_InPlacePower(v, w, Py_None);\r
+}\r
+\r
+\r
+static PyObject *\r
+instance_ipow(PyObject *v, PyObject *w, PyObject *z)\r
+{\r
+ if (z == Py_None) {\r
+ return do_binop_inplace(v, w, "__ipow__", "__pow__",\r
+ "__rpow__", bin_inplace_power);\r
+ }\r
+ else {\r
+ /* XXX Doesn't do coercions... */\r
+ PyObject *func;\r
+ PyObject *args;\r
+ PyObject *result;\r
+\r
+ func = PyObject_GetAttrString(v, "__ipow__");\r
+ if (func == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ return instance_pow(v, w, z);\r
+ }\r
+ args = PyTuple_Pack(2, w, z);\r
+ if (args == NULL) {\r
+ Py_DECREF(func);\r
+ return NULL;\r
+ }\r
+ result = PyEval_CallObject(func, args);\r
+ Py_DECREF(func);\r
+ Py_DECREF(args);\r
+ return result;\r
+ }\r
+}\r
+\r
+\r
+/* Map rich comparison operators to their __xx__ namesakes */\r
+#define NAME_OPS 6\r
+static PyObject **name_op = NULL;\r
+\r
+static int\r
+init_name_op(void)\r
+{\r
+ int i;\r
+ char *_name_op[] = {\r
+ "__lt__",\r
+ "__le__",\r
+ "__eq__",\r
+ "__ne__",\r
+ "__gt__",\r
+ "__ge__",\r
+ };\r
+\r
+ name_op = (PyObject **)malloc(sizeof(PyObject *) * NAME_OPS);\r
+ if (name_op == NULL)\r
+ return -1;\r
+ for (i = 0; i < NAME_OPS; ++i) {\r
+ name_op[i] = PyString_InternFromString(_name_op[i]);\r
+ if (name_op[i] == NULL)\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+half_richcompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyObject *method;\r
+ PyObject *args;\r
+ PyObject *res;\r
+\r
+ assert(PyInstance_Check(v));\r
+\r
+ if (name_op == NULL) {\r
+ if (init_name_op() < 0)\r
+ return NULL;\r
+ }\r
+ /* If the instance doesn't define an __getattr__ method, use\r
+ instance_getattr2 directly because it will not set an\r
+ exception on failure. */\r
+ if (((PyInstanceObject *)v)->in_class->cl_getattr == NULL)\r
+ method = instance_getattr2((PyInstanceObject *)v,\r
+ name_op[op]);\r
+ else\r
+ method = PyObject_GetAttr(v, name_op[op]);\r
+ if (method == NULL) {\r
+ if (PyErr_Occurred()) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ }\r
+ res = Py_NotImplemented;\r
+ Py_INCREF(res);\r
+ return res;\r
+ }\r
+\r
+ args = PyTuple_Pack(1, w);\r
+ if (args == NULL) {\r
+ Py_DECREF(method);\r
+ return NULL;\r
+ }\r
+\r
+ res = PyEval_CallObject(method, args);\r
+ Py_DECREF(args);\r
+ Py_DECREF(method);\r
+\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+instance_richcompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyObject *res;\r
+\r
+ if (PyInstance_Check(v)) {\r
+ res = half_richcompare(v, w, op);\r
+ if (res != Py_NotImplemented)\r
+ return res;\r
+ Py_DECREF(res);\r
+ }\r
+\r
+ if (PyInstance_Check(w)) {\r
+ res = half_richcompare(w, v, _Py_SwappedOp[op]);\r
+ if (res != Py_NotImplemented)\r
+ return res;\r
+ Py_DECREF(res);\r
+ }\r
+\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+}\r
+\r
+\r
+/* Get the iterator */\r
+static PyObject *\r
+instance_getiter(PyInstanceObject *self)\r
+{\r
+ PyObject *func;\r
+\r
+ if (iterstr == NULL) {\r
+ iterstr = PyString_InternFromString("__iter__");\r
+ if (iterstr == NULL)\r
+ return NULL;\r
+ }\r
+ if (getitemstr == NULL) {\r
+ getitemstr = PyString_InternFromString("__getitem__");\r
+ if (getitemstr == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ if ((func = instance_getattr(self, iterstr)) != NULL) {\r
+ PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);\r
+ Py_DECREF(func);\r
+ if (res != NULL && !PyIter_Check(res)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__iter__ returned non-iterator "\r
+ "of type '%.100s'",\r
+ res->ob_type->tp_name);\r
+ Py_DECREF(res);\r
+ res = NULL;\r
+ }\r
+ return res;\r
+ }\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ if ((func = instance_getattr(self, getitemstr)) == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "iteration over non-sequence");\r
+ return NULL;\r
+ }\r
+ Py_DECREF(func);\r
+ return PySeqIter_New((PyObject *)self);\r
+}\r
+\r
+\r
+/* Call the iterator's next */\r
+static PyObject *\r
+instance_iternext(PyInstanceObject *self)\r
+{\r
+ PyObject *func;\r
+\r
+ if (nextstr == NULL) {\r
+ nextstr = PyString_InternFromString("next");\r
+ if (nextstr == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ if ((func = instance_getattr(self, nextstr)) != NULL) {\r
+ PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);\r
+ Py_DECREF(func);\r
+ if (res != NULL) {\r
+ return res;\r
+ }\r
+ if (PyErr_ExceptionMatches(PyExc_StopIteration)) {\r
+ PyErr_Clear();\r
+ return NULL;\r
+ }\r
+ return NULL;\r
+ }\r
+ PyErr_SetString(PyExc_TypeError, "instance has no next() method");\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+instance_call(PyObject *func, PyObject *arg, PyObject *kw)\r
+{\r
+ PyObject *res, *call = PyObject_GetAttrString(func, "__call__");\r
+ if (call == NULL) {\r
+ PyInstanceObject *inst = (PyInstanceObject*) func;\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "%.200s instance has no __call__ method",\r
+ PyString_AsString(inst->in_class->cl_name));\r
+ return NULL;\r
+ }\r
+ /* We must check and increment the recursion depth here. Scenario:\r
+ class A:\r
+ pass\r
+ A.__call__ = A() # that's right\r
+ a = A() # ok\r
+ a() # infinite recursion\r
+ This bounces between instance_call() and PyObject_Call() without\r
+ ever hitting eval_frame() (which has the main recursion check). */\r
+ if (Py_EnterRecursiveCall(" in __call__")) {\r
+ res = NULL;\r
+ }\r
+ else {\r
+ res = PyObject_Call(call, arg, kw);\r
+ Py_LeaveRecursiveCall();\r
+ }\r
+ Py_DECREF(call);\r
+ return res;\r
+}\r
+\r
+\r
+static PyNumberMethods instance_as_number = {\r
+ instance_add, /* nb_add */\r
+ instance_sub, /* nb_subtract */\r
+ instance_mul, /* nb_multiply */\r
+ instance_div, /* nb_divide */\r
+ instance_mod, /* nb_remainder */\r
+ instance_divmod, /* nb_divmod */\r
+ instance_pow, /* nb_power */\r
+ (unaryfunc)instance_neg, /* nb_negative */\r
+ (unaryfunc)instance_pos, /* nb_positive */\r
+ (unaryfunc)instance_abs, /* nb_absolute */\r
+ (inquiry)instance_nonzero, /* nb_nonzero */\r
+ (unaryfunc)instance_invert, /* nb_invert */\r
+ instance_lshift, /* nb_lshift */\r
+ instance_rshift, /* nb_rshift */\r
+ instance_and, /* nb_and */\r
+ instance_xor, /* nb_xor */\r
+ instance_or, /* nb_or */\r
+ instance_coerce, /* nb_coerce */\r
+ (unaryfunc)instance_int, /* nb_int */\r
+ (unaryfunc)instance_long, /* nb_long */\r
+ (unaryfunc)instance_float, /* nb_float */\r
+ (unaryfunc)instance_oct, /* nb_oct */\r
+ (unaryfunc)instance_hex, /* nb_hex */\r
+ instance_iadd, /* nb_inplace_add */\r
+ instance_isub, /* nb_inplace_subtract */\r
+ instance_imul, /* nb_inplace_multiply */\r
+ instance_idiv, /* nb_inplace_divide */\r
+ instance_imod, /* nb_inplace_remainder */\r
+ instance_ipow, /* nb_inplace_power */\r
+ instance_ilshift, /* nb_inplace_lshift */\r
+ instance_irshift, /* nb_inplace_rshift */\r
+ instance_iand, /* nb_inplace_and */\r
+ instance_ixor, /* nb_inplace_xor */\r
+ instance_ior, /* nb_inplace_or */\r
+ instance_floordiv, /* nb_floor_divide */\r
+ instance_truediv, /* nb_true_divide */\r
+ instance_ifloordiv, /* nb_inplace_floor_divide */\r
+ instance_itruediv, /* nb_inplace_true_divide */\r
+ (unaryfunc)instance_index, /* nb_index */\r
+};\r
+\r
+PyTypeObject PyInstance_Type = {\r
+ PyObject_HEAD_INIT(&PyType_Type)\r
+ 0,\r
+ "instance",\r
+ sizeof(PyInstanceObject),\r
+ 0,\r
+ (destructor)instance_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ instance_compare, /* tp_compare */\r
+ (reprfunc)instance_repr, /* tp_repr */\r
+ &instance_as_number, /* tp_as_number */\r
+ &instance_as_sequence, /* tp_as_sequence */\r
+ &instance_as_mapping, /* tp_as_mapping */\r
+ (hashfunc)instance_hash, /* tp_hash */\r
+ instance_call, /* tp_call */\r
+ (reprfunc)instance_str, /* tp_str */\r
+ (getattrofunc)instance_getattr, /* tp_getattro */\r
+ (setattrofunc)instance_setattr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES,/*tp_flags*/\r
+ instance_doc, /* tp_doc */\r
+ (traverseproc)instance_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ instance_richcompare, /* tp_richcompare */\r
+ offsetof(PyInstanceObject, in_weakreflist), /* tp_weaklistoffset */\r
+ (getiterfunc)instance_getiter, /* tp_iter */\r
+ (iternextfunc)instance_iternext, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ instance_new, /* tp_new */\r
+};\r
+\r
+\r
+/* Instance method objects are used for two purposes:\r
+ (a) as bound instance methods (returned by instancename.methodname)\r
+ (b) as unbound methods (returned by ClassName.methodname)\r
+ In case (b), im_self is NULL\r
+*/\r
+\r
+PyObject *\r
+PyMethod_New(PyObject *func, PyObject *self, PyObject *klass)\r
+{\r
+ register PyMethodObject *im;\r
+ im = free_list;\r
+ if (im != NULL) {\r
+ free_list = (PyMethodObject *)(im->im_self);\r
+ PyObject_INIT(im, &PyMethod_Type);\r
+ numfree--;\r
+ }\r
+ else {\r
+ im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);\r
+ if (im == NULL)\r
+ return NULL;\r
+ }\r
+ im->im_weakreflist = NULL;\r
+ Py_INCREF(func);\r
+ im->im_func = func;\r
+ Py_XINCREF(self);\r
+ im->im_self = self;\r
+ Py_XINCREF(klass);\r
+ im->im_class = klass;\r
+ _PyObject_GC_TRACK(im);\r
+ return (PyObject *)im;\r
+}\r
+\r
+/* Descriptors for PyMethod attributes */\r
+\r
+/* im_class, im_func and im_self are stored in the PyMethod object */\r
+\r
+#define OFF(x) offsetof(PyMethodObject, x)\r
+\r
+static PyMemberDef instancemethod_memberlist[] = {\r
+ {"im_class", T_OBJECT, OFF(im_class), READONLY|RESTRICTED,\r
+ "the class associated with a method"},\r
+ {"im_func", T_OBJECT, OFF(im_func), READONLY|RESTRICTED,\r
+ "the function (or other callable) implementing a method"},\r
+ {"__func__", T_OBJECT, OFF(im_func), READONLY|RESTRICTED,\r
+ "the function (or other callable) implementing a method"},\r
+ {"im_self", T_OBJECT, OFF(im_self), READONLY|RESTRICTED,\r
+ "the instance to which a method is bound; None for unbound methods"},\r
+ {"__self__", T_OBJECT, OFF(im_self), READONLY|RESTRICTED,\r
+ "the instance to which a method is bound; None for unbound methods"},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+/* Christian Tismer argued convincingly that method attributes should\r
+ (nearly) always override function attributes.\r
+ The one exception is __doc__; there's a default __doc__ which\r
+ should only be used for the class, not for instances */\r
+\r
+static PyObject *\r
+instancemethod_get_doc(PyMethodObject *im, void *context)\r
+{\r
+ static PyObject *docstr;\r
+ if (docstr == NULL) {\r
+ docstr= PyString_InternFromString("__doc__");\r
+ if (docstr == NULL)\r
+ return NULL;\r
+ }\r
+ return PyObject_GetAttr(im->im_func, docstr);\r
+}\r
+\r
+static PyGetSetDef instancemethod_getset[] = {\r
+ {"__doc__", (getter)instancemethod_get_doc, NULL, NULL},\r
+ {0}\r
+};\r
+\r
+static PyObject *\r
+instancemethod_getattro(PyObject *obj, PyObject *name)\r
+{\r
+ PyMethodObject *im = (PyMethodObject *)obj;\r
+ PyTypeObject *tp = obj->ob_type;\r
+ PyObject *descr = NULL;\r
+\r
+ if (PyType_HasFeature(tp, Py_TPFLAGS_HAVE_CLASS)) {\r
+ if (tp->tp_dict == NULL) {\r
+ if (PyType_Ready(tp) < 0)\r
+ return NULL;\r
+ }\r
+ descr = _PyType_Lookup(tp, name);\r
+ }\r
+\r
+ if (descr != NULL) {\r
+ descrgetfunc f = TP_DESCR_GET(descr->ob_type);\r
+ if (f != NULL)\r
+ return f(descr, obj, (PyObject *)obj->ob_type);\r
+ else {\r
+ Py_INCREF(descr);\r
+ return descr;\r
+ }\r
+ }\r
+\r
+ return PyObject_GetAttr(im->im_func, name);\r
+}\r
+\r
+PyDoc_STRVAR(instancemethod_doc,\r
+"instancemethod(function, instance, class)\n\\r
+\n\\r
+Create an instance method object.");\r
+\r
+static PyObject *\r
+instancemethod_new(PyTypeObject* type, PyObject* args, PyObject *kw)\r
+{\r
+ PyObject *func;\r
+ PyObject *self;\r
+ PyObject *classObj = NULL;\r
+\r
+ if (!_PyArg_NoKeywords("instancemethod", kw))\r
+ return NULL;\r
+ if (!PyArg_UnpackTuple(args, "instancemethod", 2, 3,\r
+ &func, &self, &classObj))\r
+ return NULL;\r
+ if (!PyCallable_Check(func)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "first argument must be callable");\r
+ return NULL;\r
+ }\r
+ if (self == Py_None)\r
+ self = NULL;\r
+ if (self == NULL && classObj == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "unbound methods must have non-NULL im_class");\r
+ return NULL;\r
+ }\r
+\r
+ return PyMethod_New(func, self, classObj);\r
+}\r
+\r
+static void\r
+instancemethod_dealloc(register PyMethodObject *im)\r
+{\r
+ _PyObject_GC_UNTRACK(im);\r
+ if (im->im_weakreflist != NULL)\r
+ PyObject_ClearWeakRefs((PyObject *)im);\r
+ Py_DECREF(im->im_func);\r
+ Py_XDECREF(im->im_self);\r
+ Py_XDECREF(im->im_class);\r
+ if (numfree < PyMethod_MAXFREELIST) {\r
+ im->im_self = (PyObject *)free_list;\r
+ free_list = im;\r
+ numfree++;\r
+ }\r
+ else {\r
+ PyObject_GC_Del(im);\r
+ }\r
+}\r
+\r
+static int\r
+instancemethod_compare(PyMethodObject *a, PyMethodObject *b)\r
+{\r
+ int cmp;\r
+ cmp = PyObject_Compare(a->im_func, b->im_func);\r
+ if (cmp)\r
+ return cmp;\r
+\r
+ if (a->im_self == b->im_self)\r
+ return 0;\r
+ if (a->im_self == NULL || b->im_self == NULL)\r
+ return (a->im_self < b->im_self) ? -1 : 1;\r
+ else\r
+ return PyObject_Compare(a->im_self, b->im_self);\r
+}\r
+\r
+static PyObject *\r
+instancemethod_repr(PyMethodObject *a)\r
+{\r
+ PyObject *self = a->im_self;\r
+ PyObject *func = a->im_func;\r
+ PyObject *klass = a->im_class;\r
+ PyObject *funcname = NULL, *klassname = NULL, *result = NULL;\r
+ char *sfuncname = "?", *sklassname = "?";\r
+\r
+ funcname = PyObject_GetAttrString(func, "__name__");\r
+ if (funcname == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ }\r
+ else if (!PyString_Check(funcname)) {\r
+ Py_DECREF(funcname);\r
+ funcname = NULL;\r
+ }\r
+ else\r
+ sfuncname = PyString_AS_STRING(funcname);\r
+ if (klass == NULL)\r
+ klassname = NULL;\r
+ else {\r
+ klassname = PyObject_GetAttrString(klass, "__name__");\r
+ if (klassname == NULL) {\r
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ }\r
+ else if (!PyString_Check(klassname)) {\r
+ Py_DECREF(klassname);\r
+ klassname = NULL;\r
+ }\r
+ else\r
+ sklassname = PyString_AS_STRING(klassname);\r
+ }\r
+ if (self == NULL)\r
+ result = PyString_FromFormat("<unbound method %s.%s>",\r
+ sklassname, sfuncname);\r
+ else {\r
+ /* XXX Shouldn't use repr() here! */\r
+ PyObject *selfrepr = PyObject_Repr(self);\r
+ if (selfrepr == NULL)\r
+ goto fail;\r
+ if (!PyString_Check(selfrepr)) {\r
+ Py_DECREF(selfrepr);\r
+ goto fail;\r
+ }\r
+ result = PyString_FromFormat("<bound method %s.%s of %s>",\r
+ sklassname, sfuncname,\r
+ PyString_AS_STRING(selfrepr));\r
+ Py_DECREF(selfrepr);\r
+ }\r
+ fail:\r
+ Py_XDECREF(funcname);\r
+ Py_XDECREF(klassname);\r
+ return result;\r
+}\r
+\r
+static long\r
+instancemethod_hash(PyMethodObject *a)\r
+{\r
+ long x, y;\r
+ if (a->im_self == NULL)\r
+ x = PyObject_Hash(Py_None);\r
+ else\r
+ x = PyObject_Hash(a->im_self);\r
+ if (x == -1)\r
+ return -1;\r
+ y = PyObject_Hash(a->im_func);\r
+ if (y == -1)\r
+ return -1;\r
+ x = x ^ y;\r
+ if (x == -1)\r
+ x = -2;\r
+ return x;\r
+}\r
+\r
+static int\r
+instancemethod_traverse(PyMethodObject *im, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(im->im_func);\r
+ Py_VISIT(im->im_self);\r
+ Py_VISIT(im->im_class);\r
+ return 0;\r
+}\r
+\r
+static void\r
+getclassname(PyObject *klass, char *buf, int bufsize)\r
+{\r
+ PyObject *name;\r
+\r
+ assert(bufsize > 1);\r
+ strcpy(buf, "?"); /* Default outcome */\r
+ if (klass == NULL)\r
+ return;\r
+ name = PyObject_GetAttrString(klass, "__name__");\r
+ if (name == NULL) {\r
+ /* This function cannot return an exception */\r
+ PyErr_Clear();\r
+ return;\r
+ }\r
+ if (PyString_Check(name)) {\r
+ strncpy(buf, PyString_AS_STRING(name), bufsize);\r
+ buf[bufsize-1] = '\0';\r
+ }\r
+ Py_DECREF(name);\r
+}\r
+\r
+static void\r
+getinstclassname(PyObject *inst, char *buf, int bufsize)\r
+{\r
+ PyObject *klass;\r
+\r
+ if (inst == NULL) {\r
+ assert(bufsize > 0 && (size_t)bufsize > strlen("nothing"));\r
+ strcpy(buf, "nothing");\r
+ return;\r
+ }\r
+\r
+ klass = PyObject_GetAttrString(inst, "__class__");\r
+ if (klass == NULL) {\r
+ /* This function cannot return an exception */\r
+ PyErr_Clear();\r
+ klass = (PyObject *)(inst->ob_type);\r
+ Py_INCREF(klass);\r
+ }\r
+ getclassname(klass, buf, bufsize);\r
+ Py_XDECREF(klass);\r
+}\r
+\r
+static PyObject *\r
+instancemethod_call(PyObject *func, PyObject *arg, PyObject *kw)\r
+{\r
+ PyObject *self = PyMethod_GET_SELF(func);\r
+ PyObject *klass = PyMethod_GET_CLASS(func);\r
+ PyObject *result;\r
+\r
+ func = PyMethod_GET_FUNCTION(func);\r
+ if (self == NULL) {\r
+ /* Unbound methods must be called with an instance of\r
+ the class (or a derived class) as first argument */\r
+ int ok;\r
+ if (PyTuple_Size(arg) >= 1)\r
+ self = PyTuple_GET_ITEM(arg, 0);\r
+ if (self == NULL)\r
+ ok = 0;\r
+ else {\r
+ ok = PyObject_IsInstance(self, klass);\r
+ if (ok < 0)\r
+ return NULL;\r
+ }\r
+ if (!ok) {\r
+ char clsbuf[256];\r
+ char instbuf[256];\r
+ getclassname(klass, clsbuf, sizeof(clsbuf));\r
+ getinstclassname(self, instbuf, sizeof(instbuf));\r
+ PyErr_Format(PyExc_TypeError,\r
+ "unbound method %s%s must be called with "\r
+ "%s instance as first argument "\r
+ "(got %s%s instead)",\r
+ PyEval_GetFuncName(func),\r
+ PyEval_GetFuncDesc(func),\r
+ clsbuf,\r
+ instbuf,\r
+ self == NULL ? "" : " instance");\r
+ return NULL;\r
+ }\r
+ Py_INCREF(arg);\r
+ }\r
+ else {\r
+ Py_ssize_t argcount = PyTuple_Size(arg);\r
+ PyObject *newarg = PyTuple_New(argcount + 1);\r
+ int i;\r
+ if (newarg == NULL)\r
+ return NULL;\r
+ Py_INCREF(self);\r
+ PyTuple_SET_ITEM(newarg, 0, self);\r
+ for (i = 0; i < argcount; i++) {\r
+ PyObject *v = PyTuple_GET_ITEM(arg, i);\r
+ Py_XINCREF(v);\r
+ PyTuple_SET_ITEM(newarg, i+1, v);\r
+ }\r
+ arg = newarg;\r
+ }\r
+ result = PyObject_Call((PyObject *)func, arg, kw);\r
+ Py_DECREF(arg);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+instancemethod_descr_get(PyObject *meth, PyObject *obj, PyObject *cls)\r
+{\r
+ /* Don't rebind an already bound method, or an unbound method\r
+ of a class that's not a base class of cls. */\r
+\r
+ if (PyMethod_GET_SELF(meth) != NULL) {\r
+ /* Already bound */\r
+ Py_INCREF(meth);\r
+ return meth;\r
+ }\r
+ /* No, it is an unbound method */\r
+ if (PyMethod_GET_CLASS(meth) != NULL && cls != NULL) {\r
+ /* Do subclass test. If it fails, return meth unchanged. */\r
+ int ok = PyObject_IsSubclass(cls, PyMethod_GET_CLASS(meth));\r
+ if (ok < 0)\r
+ return NULL;\r
+ if (!ok) {\r
+ Py_INCREF(meth);\r
+ return meth;\r
+ }\r
+ }\r
+ /* Bind it to obj */\r
+ return PyMethod_New(PyMethod_GET_FUNCTION(meth), obj, cls);\r
+}\r
+\r
+PyTypeObject PyMethod_Type = {\r
+ PyObject_HEAD_INIT(&PyType_Type)\r
+ 0,\r
+ "instancemethod",\r
+ sizeof(PyMethodObject),\r
+ 0,\r
+ (destructor)instancemethod_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)instancemethod_compare, /* tp_compare */\r
+ (reprfunc)instancemethod_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)instancemethod_hash, /* tp_hash */\r
+ instancemethod_call, /* tp_call */\r
+ 0, /* tp_str */\r
+ instancemethod_getattro, /* tp_getattro */\r
+ PyObject_GenericSetAttr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */\r
+ instancemethod_doc, /* tp_doc */\r
+ (traverseproc)instancemethod_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ offsetof(PyMethodObject, im_weakreflist), /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ instancemethod_memberlist, /* tp_members */\r
+ instancemethod_getset, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ instancemethod_descr_get, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ instancemethod_new, /* tp_new */\r
+};\r
+\r
+/* Clear out the free list */\r
+\r
+int\r
+PyMethod_ClearFreeList(void)\r
+{\r
+ int freelist_size = numfree;\r
+\r
+ while (free_list) {\r
+ PyMethodObject *im = free_list;\r
+ free_list = (PyMethodObject *)(im->im_self);\r
+ PyObject_GC_Del(im);\r
+ numfree--;\r
+ }\r
+ assert(numfree == 0);\r
+ return freelist_size;\r
+}\r
+\r
+void\r
+PyMethod_Fini(void)\r
+{\r
+ (void)PyMethod_ClearFreeList();\r
+}\r
--- /dev/null
+\r
+/* Wrap void* pointers to be passed between C modules */\r
+\r
+#include "Python.h"\r
+\r
+\r
+/* Declarations for objects of type PyCObject */\r
+\r
+typedef void (*destructor1)(void *);\r
+typedef void (*destructor2)(void *, void*);\r
+\r
+static int cobject_deprecation_warning(void)\r
+{\r
+ return PyErr_WarnPy3k("CObject type is not supported in 3.x. "\r
+ "Please use capsule objects instead.", 1);\r
+}\r
+\r
+\r
+PyObject *\r
+PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *))\r
+{\r
+ PyCObject *self;\r
+\r
+ if (cobject_deprecation_warning()) {\r
+ return NULL;\r
+ }\r
+\r
+ self = PyObject_NEW(PyCObject, &PyCObject_Type);\r
+ if (self == NULL)\r
+ return NULL;\r
+ self->cobject=cobj;\r
+ self->destructor=destr;\r
+ self->desc=NULL;\r
+\r
+ return (PyObject *)self;\r
+}\r
+\r
+PyObject *\r
+PyCObject_FromVoidPtrAndDesc(void *cobj, void *desc,\r
+ void (*destr)(void *, void *))\r
+{\r
+ PyCObject *self;\r
+\r
+ if (cobject_deprecation_warning()) {\r
+ return NULL;\r
+ }\r
+\r
+ if (!desc) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "PyCObject_FromVoidPtrAndDesc called with null"\r
+ " description");\r
+ return NULL;\r
+ }\r
+ self = PyObject_NEW(PyCObject, &PyCObject_Type);\r
+ if (self == NULL)\r
+ return NULL;\r
+ self->cobject = cobj;\r
+ self->destructor = (destructor1)destr;\r
+ self->desc = desc;\r
+\r
+ return (PyObject *)self;\r
+}\r
+\r
+void *\r
+PyCObject_AsVoidPtr(PyObject *self)\r
+{\r
+ if (self) {\r
+ if (PyCapsule_CheckExact(self)) {\r
+ const char *name = PyCapsule_GetName(self);\r
+ return (void *)PyCapsule_GetPointer(self, name);\r
+ }\r
+ if (self->ob_type == &PyCObject_Type)\r
+ return ((PyCObject *)self)->cobject;\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "PyCObject_AsVoidPtr with non-C-object");\r
+ }\r
+ if (!PyErr_Occurred())\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "PyCObject_AsVoidPtr called with null pointer");\r
+ return NULL;\r
+}\r
+\r
+void *\r
+PyCObject_GetDesc(PyObject *self)\r
+{\r
+ if (self) {\r
+ if (self->ob_type == &PyCObject_Type)\r
+ return ((PyCObject *)self)->desc;\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "PyCObject_GetDesc with non-C-object");\r
+ }\r
+ if (!PyErr_Occurred())\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "PyCObject_GetDesc called with null pointer");\r
+ return NULL;\r
+}\r
+\r
+void *\r
+PyCObject_Import(char *module_name, char *name)\r
+{\r
+ PyObject *m, *c;\r
+ void *r = NULL;\r
+\r
+ if ((m = PyImport_ImportModule(module_name))) {\r
+ if ((c = PyObject_GetAttrString(m,name))) {\r
+ r = PyCObject_AsVoidPtr(c);\r
+ Py_DECREF(c);\r
+ }\r
+ Py_DECREF(m);\r
+ }\r
+ return r;\r
+}\r
+\r
+int\r
+PyCObject_SetVoidPtr(PyObject *self, void *cobj)\r
+{\r
+ PyCObject* cself = (PyCObject*)self;\r
+ if (cself == NULL || !PyCObject_Check(cself) ||\r
+ cself->destructor != NULL) {\r
+ PyErr_SetString(PyExc_TypeError, \r
+ "Invalid call to PyCObject_SetVoidPtr");\r
+ return 0;\r
+ }\r
+ cself->cobject = cobj;\r
+ return 1;\r
+}\r
+\r
+static void\r
+PyCObject_dealloc(PyCObject *self)\r
+{\r
+ if (self->destructor) {\r
+ if(self->desc)\r
+ ((destructor2)(self->destructor))(self->cobject, self->desc);\r
+ else\r
+ (self->destructor)(self->cobject);\r
+ }\r
+ PyObject_DEL(self);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(PyCObject_Type__doc__,\r
+"C objects to be exported from one extension module to another\n\\r
+\n\\r
+C objects are used for communication between extension modules. They\n\\r
+provide a way for an extension module to export a C interface to other\n\\r
+extension modules, so that extension modules can use the Python import\n\\r
+mechanism to link to one another.");\r
+\r
+PyTypeObject PyCObject_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "PyCObject", /*tp_name*/\r
+ sizeof(PyCObject), /*tp_basicsize*/\r
+ 0, /*tp_itemsize*/\r
+ /* methods */\r
+ (destructor)PyCObject_dealloc, /*tp_dealloc*/\r
+ 0, /*tp_print*/\r
+ 0, /*tp_getattr*/\r
+ 0, /*tp_setattr*/\r
+ 0, /*tp_compare*/\r
+ 0, /*tp_repr*/\r
+ 0, /*tp_as_number*/\r
+ 0, /*tp_as_sequence*/\r
+ 0, /*tp_as_mapping*/\r
+ 0, /*tp_hash*/\r
+ 0, /*tp_call*/\r
+ 0, /*tp_str*/\r
+ 0, /*tp_getattro*/\r
+ 0, /*tp_setattro*/\r
+ 0, /*tp_as_buffer*/\r
+ 0, /*tp_flags*/\r
+ PyCObject_Type__doc__ /*tp_doc*/\r
+};\r
--- /dev/null
+#include "Python.h"\r
+#include "code.h"\r
+#include "structmember.h"\r
+\r
+#define NAME_CHARS \\r
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"\r
+\r
+/* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */\r
+\r
+static int\r
+all_name_chars(unsigned char *s)\r
+{\r
+ static char ok_name_char[256];\r
+ static unsigned char *name_chars = (unsigned char *)NAME_CHARS;\r
+\r
+ if (ok_name_char[*name_chars] == 0) {\r
+ unsigned char *p;\r
+ for (p = name_chars; *p; p++)\r
+ ok_name_char[*p] = 1;\r
+ }\r
+ while (*s) {\r
+ if (ok_name_char[*s++] == 0)\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+static void\r
+intern_strings(PyObject *tuple)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {\r
+ PyObject *v = PyTuple_GET_ITEM(tuple, i);\r
+ if (v == NULL || !PyString_CheckExact(v)) {\r
+ Py_FatalError("non-string found in code slot");\r
+ }\r
+ PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i));\r
+ }\r
+}\r
+\r
+\r
+PyCodeObject *\r
+PyCode_New(int argcount, int nlocals, int stacksize, int flags,\r
+ PyObject *code, PyObject *consts, PyObject *names,\r
+ PyObject *varnames, PyObject *freevars, PyObject *cellvars,\r
+ PyObject *filename, PyObject *name, int firstlineno,\r
+ PyObject *lnotab)\r
+{\r
+ PyCodeObject *co;\r
+ Py_ssize_t i;\r
+ /* Check argument types */\r
+ if (argcount < 0 || nlocals < 0 ||\r
+ code == NULL ||\r
+ consts == NULL || !PyTuple_Check(consts) ||\r
+ names == NULL || !PyTuple_Check(names) ||\r
+ varnames == NULL || !PyTuple_Check(varnames) ||\r
+ freevars == NULL || !PyTuple_Check(freevars) ||\r
+ cellvars == NULL || !PyTuple_Check(cellvars) ||\r
+ name == NULL || !PyString_Check(name) ||\r
+ filename == NULL || !PyString_Check(filename) ||\r
+ lnotab == NULL || !PyString_Check(lnotab) ||\r
+ !PyObject_CheckReadBuffer(code)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ intern_strings(names);\r
+ intern_strings(varnames);\r
+ intern_strings(freevars);\r
+ intern_strings(cellvars);\r
+ /* Intern selected string constants */\r
+ for (i = PyTuple_Size(consts); --i >= 0; ) {\r
+ PyObject *v = PyTuple_GetItem(consts, i);\r
+ if (!PyString_Check(v))\r
+ continue;\r
+ if (!all_name_chars((unsigned char *)PyString_AS_STRING(v)))\r
+ continue;\r
+ PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));\r
+ }\r
+ co = PyObject_NEW(PyCodeObject, &PyCode_Type);\r
+ if (co != NULL) {\r
+ co->co_argcount = argcount;\r
+ co->co_nlocals = nlocals;\r
+ co->co_stacksize = stacksize;\r
+ co->co_flags = flags;\r
+ Py_INCREF(code);\r
+ co->co_code = code;\r
+ Py_INCREF(consts);\r
+ co->co_consts = consts;\r
+ Py_INCREF(names);\r
+ co->co_names = names;\r
+ Py_INCREF(varnames);\r
+ co->co_varnames = varnames;\r
+ Py_INCREF(freevars);\r
+ co->co_freevars = freevars;\r
+ Py_INCREF(cellvars);\r
+ co->co_cellvars = cellvars;\r
+ Py_INCREF(filename);\r
+ co->co_filename = filename;\r
+ Py_INCREF(name);\r
+ co->co_name = name;\r
+ co->co_firstlineno = firstlineno;\r
+ Py_INCREF(lnotab);\r
+ co->co_lnotab = lnotab;\r
+ co->co_zombieframe = NULL;\r
+ co->co_weakreflist = NULL;\r
+ }\r
+ return co;\r
+}\r
+\r
+PyCodeObject *\r
+PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)\r
+{\r
+ static PyObject *emptystring = NULL;\r
+ static PyObject *nulltuple = NULL;\r
+ PyObject *filename_ob = NULL;\r
+ PyObject *funcname_ob = NULL;\r
+ PyCodeObject *result = NULL;\r
+ if (emptystring == NULL) {\r
+ emptystring = PyString_FromString("");\r
+ if (emptystring == NULL)\r
+ goto failed;\r
+ }\r
+ if (nulltuple == NULL) {\r
+ nulltuple = PyTuple_New(0);\r
+ if (nulltuple == NULL)\r
+ goto failed;\r
+ }\r
+ funcname_ob = PyString_FromString(funcname);\r
+ if (funcname_ob == NULL)\r
+ goto failed;\r
+ filename_ob = PyString_FromString(filename);\r
+ if (filename_ob == NULL)\r
+ goto failed;\r
+\r
+ result = PyCode_New(0, /* argcount */\r
+ 0, /* nlocals */\r
+ 0, /* stacksize */\r
+ 0, /* flags */\r
+ emptystring, /* code */\r
+ nulltuple, /* consts */\r
+ nulltuple, /* names */\r
+ nulltuple, /* varnames */\r
+ nulltuple, /* freevars */\r
+ nulltuple, /* cellvars */\r
+ filename_ob, /* filename */\r
+ funcname_ob, /* name */\r
+ firstlineno, /* firstlineno */\r
+ emptystring /* lnotab */\r
+ );\r
+\r
+failed:\r
+ Py_XDECREF(funcname_ob);\r
+ Py_XDECREF(filename_ob);\r
+ return result;\r
+}\r
+\r
+#define OFF(x) offsetof(PyCodeObject, x)\r
+\r
+static PyMemberDef code_memberlist[] = {\r
+ {"co_argcount", T_INT, OFF(co_argcount), READONLY},\r
+ {"co_nlocals", T_INT, OFF(co_nlocals), READONLY},\r
+ {"co_stacksize",T_INT, OFF(co_stacksize), READONLY},\r
+ {"co_flags", T_INT, OFF(co_flags), READONLY},\r
+ {"co_code", T_OBJECT, OFF(co_code), READONLY},\r
+ {"co_consts", T_OBJECT, OFF(co_consts), READONLY},\r
+ {"co_names", T_OBJECT, OFF(co_names), READONLY},\r
+ {"co_varnames", T_OBJECT, OFF(co_varnames), READONLY},\r
+ {"co_freevars", T_OBJECT, OFF(co_freevars), READONLY},\r
+ {"co_cellvars", T_OBJECT, OFF(co_cellvars), READONLY},\r
+ {"co_filename", T_OBJECT, OFF(co_filename), READONLY},\r
+ {"co_name", T_OBJECT, OFF(co_name), READONLY},\r
+ {"co_firstlineno", T_INT, OFF(co_firstlineno), READONLY},\r
+ {"co_lnotab", T_OBJECT, OFF(co_lnotab), READONLY},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+/* Helper for code_new: return a shallow copy of a tuple that is\r
+ guaranteed to contain exact strings, by converting string subclasses\r
+ to exact strings and complaining if a non-string is found. */\r
+static PyObject*\r
+validate_and_copy_tuple(PyObject *tup)\r
+{\r
+ PyObject *newtuple;\r
+ PyObject *item;\r
+ Py_ssize_t i, len;\r
+\r
+ len = PyTuple_GET_SIZE(tup);\r
+ newtuple = PyTuple_New(len);\r
+ if (newtuple == NULL)\r
+ return NULL;\r
+\r
+ for (i = 0; i < len; i++) {\r
+ item = PyTuple_GET_ITEM(tup, i);\r
+ if (PyString_CheckExact(item)) {\r
+ Py_INCREF(item);\r
+ }\r
+ else if (!PyString_Check(item)) {\r
+ PyErr_Format(\r
+ PyExc_TypeError,\r
+ "name tuples must contain only "\r
+ "strings, not '%.500s'",\r
+ item->ob_type->tp_name);\r
+ Py_DECREF(newtuple);\r
+ return NULL;\r
+ }\r
+ else {\r
+ item = PyString_FromStringAndSize(\r
+ PyString_AS_STRING(item),\r
+ PyString_GET_SIZE(item));\r
+ if (item == NULL) {\r
+ Py_DECREF(newtuple);\r
+ return NULL;\r
+ }\r
+ }\r
+ PyTuple_SET_ITEM(newtuple, i, item);\r
+ }\r
+\r
+ return newtuple;\r
+}\r
+\r
+PyDoc_STRVAR(code_doc,\r
+"code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n\\r
+ varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\\r
+\n\\r
+Create a code object. Not for the faint of heart.");\r
+\r
+static PyObject *\r
+code_new(PyTypeObject *type, PyObject *args, PyObject *kw)\r
+{\r
+ int argcount;\r
+ int nlocals;\r
+ int stacksize;\r
+ int flags;\r
+ PyObject *co = NULL;\r
+ PyObject *code;\r
+ PyObject *consts;\r
+ PyObject *names, *ournames = NULL;\r
+ PyObject *varnames, *ourvarnames = NULL;\r
+ PyObject *freevars = NULL, *ourfreevars = NULL;\r
+ PyObject *cellvars = NULL, *ourcellvars = NULL;\r
+ PyObject *filename;\r
+ PyObject *name;\r
+ int firstlineno;\r
+ PyObject *lnotab;\r
+\r
+ if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",\r
+ &argcount, &nlocals, &stacksize, &flags,\r
+ &code,\r
+ &PyTuple_Type, &consts,\r
+ &PyTuple_Type, &names,\r
+ &PyTuple_Type, &varnames,\r
+ &filename, &name,\r
+ &firstlineno, &lnotab,\r
+ &PyTuple_Type, &freevars,\r
+ &PyTuple_Type, &cellvars))\r
+ return NULL;\r
+\r
+ if (argcount < 0) {\r
+ PyErr_SetString(\r
+ PyExc_ValueError,\r
+ "code: argcount must not be negative");\r
+ goto cleanup;\r
+ }\r
+\r
+ if (nlocals < 0) {\r
+ PyErr_SetString(\r
+ PyExc_ValueError,\r
+ "code: nlocals must not be negative");\r
+ goto cleanup;\r
+ }\r
+\r
+ ournames = validate_and_copy_tuple(names);\r
+ if (ournames == NULL)\r
+ goto cleanup;\r
+ ourvarnames = validate_and_copy_tuple(varnames);\r
+ if (ourvarnames == NULL)\r
+ goto cleanup;\r
+ if (freevars)\r
+ ourfreevars = validate_and_copy_tuple(freevars);\r
+ else\r
+ ourfreevars = PyTuple_New(0);\r
+ if (ourfreevars == NULL)\r
+ goto cleanup;\r
+ if (cellvars)\r
+ ourcellvars = validate_and_copy_tuple(cellvars);\r
+ else\r
+ ourcellvars = PyTuple_New(0);\r
+ if (ourcellvars == NULL)\r
+ goto cleanup;\r
+\r
+ co = (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags,\r
+ code, consts, ournames, ourvarnames,\r
+ ourfreevars, ourcellvars, filename,\r
+ name, firstlineno, lnotab);\r
+ cleanup:\r
+ Py_XDECREF(ournames);\r
+ Py_XDECREF(ourvarnames);\r
+ Py_XDECREF(ourfreevars);\r
+ Py_XDECREF(ourcellvars);\r
+ return co;\r
+}\r
+\r
+static void\r
+code_dealloc(PyCodeObject *co)\r
+{\r
+ Py_XDECREF(co->co_code);\r
+ Py_XDECREF(co->co_consts);\r
+ Py_XDECREF(co->co_names);\r
+ Py_XDECREF(co->co_varnames);\r
+ Py_XDECREF(co->co_freevars);\r
+ Py_XDECREF(co->co_cellvars);\r
+ Py_XDECREF(co->co_filename);\r
+ Py_XDECREF(co->co_name);\r
+ Py_XDECREF(co->co_lnotab);\r
+ if (co->co_zombieframe != NULL)\r
+ PyObject_GC_Del(co->co_zombieframe);\r
+ if (co->co_weakreflist != NULL)\r
+ PyObject_ClearWeakRefs((PyObject*)co);\r
+ PyObject_DEL(co);\r
+}\r
+\r
+static PyObject *\r
+code_repr(PyCodeObject *co)\r
+{\r
+ char buf[500];\r
+ int lineno = -1;\r
+ char *filename = "???";\r
+ char *name = "???";\r
+\r
+ if (co->co_firstlineno != 0)\r
+ lineno = co->co_firstlineno;\r
+ if (co->co_filename && PyString_Check(co->co_filename))\r
+ filename = PyString_AS_STRING(co->co_filename);\r
+ if (co->co_name && PyString_Check(co->co_name))\r
+ name = PyString_AS_STRING(co->co_name);\r
+ PyOS_snprintf(buf, sizeof(buf),\r
+ "<code object %.100s at %p, file \"%.300s\", line %d>",\r
+ name, co, filename, lineno);\r
+ return PyString_FromString(buf);\r
+}\r
+\r
+static int\r
+code_compare(PyCodeObject *co, PyCodeObject *cp)\r
+{\r
+ int cmp;\r
+ cmp = PyObject_Compare(co->co_name, cp->co_name);\r
+ if (cmp) return cmp;\r
+ cmp = co->co_argcount - cp->co_argcount;\r
+ if (cmp) goto normalize;\r
+ cmp = co->co_nlocals - cp->co_nlocals;\r
+ if (cmp) goto normalize;\r
+ cmp = co->co_flags - cp->co_flags;\r
+ if (cmp) goto normalize;\r
+ cmp = co->co_firstlineno - cp->co_firstlineno;\r
+ if (cmp) goto normalize;\r
+ cmp = PyObject_Compare(co->co_code, cp->co_code);\r
+ if (cmp) return cmp;\r
+ cmp = PyObject_Compare(co->co_consts, cp->co_consts);\r
+ if (cmp) return cmp;\r
+ cmp = PyObject_Compare(co->co_names, cp->co_names);\r
+ if (cmp) return cmp;\r
+ cmp = PyObject_Compare(co->co_varnames, cp->co_varnames);\r
+ if (cmp) return cmp;\r
+ cmp = PyObject_Compare(co->co_freevars, cp->co_freevars);\r
+ if (cmp) return cmp;\r
+ cmp = PyObject_Compare(co->co_cellvars, cp->co_cellvars);\r
+ return cmp;\r
+\r
+ normalize:\r
+ if (cmp > 0)\r
+ return 1;\r
+ else if (cmp < 0)\r
+ return -1;\r
+ else\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+code_richcompare(PyObject *self, PyObject *other, int op)\r
+{\r
+ PyCodeObject *co, *cp;\r
+ int eq;\r
+ PyObject *res;\r
+\r
+ if ((op != Py_EQ && op != Py_NE) ||\r
+ !PyCode_Check(self) ||\r
+ !PyCode_Check(other)) {\r
+\r
+ /* Py3K warning if types are not equal and comparison\r
+ isn't == or != */\r
+ if (PyErr_WarnPy3k("code inequality comparisons not supported "\r
+ "in 3.x", 1) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+\r
+ co = (PyCodeObject *)self;\r
+ cp = (PyCodeObject *)other;\r
+\r
+ eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ);\r
+ if (eq <= 0) goto unequal;\r
+ eq = co->co_argcount == cp->co_argcount;\r
+ if (!eq) goto unequal;\r
+ eq = co->co_nlocals == cp->co_nlocals;\r
+ if (!eq) goto unequal;\r
+ eq = co->co_flags == cp->co_flags;\r
+ if (!eq) goto unequal;\r
+ eq = co->co_firstlineno == cp->co_firstlineno;\r
+ if (!eq) goto unequal;\r
+ eq = PyObject_RichCompareBool(co->co_code, cp->co_code, Py_EQ);\r
+ if (eq <= 0) goto unequal;\r
+ eq = PyObject_RichCompareBool(co->co_consts, cp->co_consts, Py_EQ);\r
+ if (eq <= 0) goto unequal;\r
+ eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ);\r
+ if (eq <= 0) goto unequal;\r
+ eq = PyObject_RichCompareBool(co->co_varnames, cp->co_varnames, Py_EQ);\r
+ if (eq <= 0) goto unequal;\r
+ eq = PyObject_RichCompareBool(co->co_freevars, cp->co_freevars, Py_EQ);\r
+ if (eq <= 0) goto unequal;\r
+ eq = PyObject_RichCompareBool(co->co_cellvars, cp->co_cellvars, Py_EQ);\r
+ if (eq <= 0) goto unequal;\r
+\r
+ if (op == Py_EQ)\r
+ res = Py_True;\r
+ else\r
+ res = Py_False;\r
+ goto done;\r
+\r
+ unequal:\r
+ if (eq < 0)\r
+ return NULL;\r
+ if (op == Py_NE)\r
+ res = Py_True;\r
+ else\r
+ res = Py_False;\r
+\r
+ done:\r
+ Py_INCREF(res);\r
+ return res;\r
+}\r
+\r
+static long\r
+code_hash(PyCodeObject *co)\r
+{\r
+ long h, h0, h1, h2, h3, h4, h5, h6;\r
+ h0 = PyObject_Hash(co->co_name);\r
+ if (h0 == -1) return -1;\r
+ h1 = PyObject_Hash(co->co_code);\r
+ if (h1 == -1) return -1;\r
+ h2 = PyObject_Hash(co->co_consts);\r
+ if (h2 == -1) return -1;\r
+ h3 = PyObject_Hash(co->co_names);\r
+ if (h3 == -1) return -1;\r
+ h4 = PyObject_Hash(co->co_varnames);\r
+ if (h4 == -1) return -1;\r
+ h5 = PyObject_Hash(co->co_freevars);\r
+ if (h5 == -1) return -1;\r
+ h6 = PyObject_Hash(co->co_cellvars);\r
+ if (h6 == -1) return -1;\r
+ h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^\r
+ co->co_argcount ^ co->co_nlocals ^ co->co_flags;\r
+ if (h == -1) h = -2;\r
+ return h;\r
+}\r
+\r
+/* XXX code objects need to participate in GC? */\r
+\r
+PyTypeObject PyCode_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "code",\r
+ sizeof(PyCodeObject),\r
+ 0,\r
+ (destructor)code_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)code_compare, /* tp_compare */\r
+ (reprfunc)code_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)code_hash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT, /* tp_flags */\r
+ code_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ code_richcompare, /* tp_richcompare */\r
+ offsetof(PyCodeObject, co_weakreflist), /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ code_memberlist, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ code_new, /* tp_new */\r
+};\r
+\r
+/* Use co_lnotab to compute the line number from a bytecode index, addrq. See\r
+ lnotab_notes.txt for the details of the lnotab representation.\r
+*/\r
+\r
+int\r
+PyCode_Addr2Line(PyCodeObject *co, int addrq)\r
+{\r
+ int size = PyString_Size(co->co_lnotab) / 2;\r
+ unsigned char *p = (unsigned char*)PyString_AsString(co->co_lnotab);\r
+ int line = co->co_firstlineno;\r
+ int addr = 0;\r
+ while (--size >= 0) {\r
+ addr += *p++;\r
+ if (addr > addrq)\r
+ break;\r
+ line += *p++;\r
+ }\r
+ return line;\r
+}\r
+\r
+/* Update *bounds to describe the first and one-past-the-last instructions in\r
+ the same line as lasti. Return the number of that line. */\r
+int\r
+_PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)\r
+{\r
+ int size, addr, line;\r
+ unsigned char* p;\r
+\r
+ p = (unsigned char*)PyString_AS_STRING(co->co_lnotab);\r
+ size = PyString_GET_SIZE(co->co_lnotab) / 2;\r
+\r
+ addr = 0;\r
+ line = co->co_firstlineno;\r
+ assert(line > 0);\r
+\r
+ /* possible optimization: if f->f_lasti == instr_ub\r
+ (likely to be a common case) then we already know\r
+ instr_lb -- if we stored the matching value of p\r
+ somwhere we could skip the first while loop. */\r
+\r
+ /* See lnotab_notes.txt for the description of\r
+ co_lnotab. A point to remember: increments to p\r
+ come in (addr, line) pairs. */\r
+\r
+ bounds->ap_lower = 0;\r
+ while (size > 0) {\r
+ if (addr + *p > lasti)\r
+ break;\r
+ addr += *p++;\r
+ if (*p)\r
+ bounds->ap_lower = addr;\r
+ line += *p++;\r
+ --size;\r
+ }\r
+\r
+ if (size > 0) {\r
+ while (--size >= 0) {\r
+ addr += *p++;\r
+ if (*p++)\r
+ break;\r
+ }\r
+ bounds->ap_upper = addr;\r
+ }\r
+ else {\r
+ bounds->ap_upper = INT_MAX;\r
+ }\r
+\r
+ return line;\r
+}\r
--- /dev/null
+\r
+/* Complex object implementation */\r
+\r
+/* Borrows heavily from floatobject.c */\r
+\r
+/* Submitted by Jim Hugunin */\r
+\r
+#include "Python.h"\r
+#include "structmember.h"\r
+\r
+#ifndef WITHOUT_COMPLEX\r
+\r
+/* Precisions used by repr() and str(), respectively.\r
+\r
+ The repr() precision (17 significant decimal digits) is the minimal number\r
+ that is guaranteed to have enough precision so that if the number is read\r
+ back in the exact same binary value is recreated. This is true for IEEE\r
+ floating point by design, and also happens to work for all other modern\r
+ hardware.\r
+\r
+ The str() precision is chosen so that in most cases, the rounding noise\r
+ created by various operations is suppressed, while giving plenty of\r
+ precision for practical use.\r
+*/\r
+\r
+#define PREC_REPR 17\r
+#define PREC_STR 12\r
+\r
+/* elementary operations on complex numbers */\r
+\r
+static Py_complex c_1 = {1., 0.};\r
+\r
+Py_complex\r
+c_sum(Py_complex a, Py_complex b)\r
+{\r
+ Py_complex r;\r
+ r.real = a.real + b.real;\r
+ r.imag = a.imag + b.imag;\r
+ return r;\r
+}\r
+\r
+Py_complex\r
+c_diff(Py_complex a, Py_complex b)\r
+{\r
+ Py_complex r;\r
+ r.real = a.real - b.real;\r
+ r.imag = a.imag - b.imag;\r
+ return r;\r
+}\r
+\r
+Py_complex\r
+c_neg(Py_complex a)\r
+{\r
+ Py_complex r;\r
+ r.real = -a.real;\r
+ r.imag = -a.imag;\r
+ return r;\r
+}\r
+\r
+Py_complex\r
+c_prod(Py_complex a, Py_complex b)\r
+{\r
+ Py_complex r;\r
+ r.real = a.real*b.real - a.imag*b.imag;\r
+ r.imag = a.real*b.imag + a.imag*b.real;\r
+ return r;\r
+}\r
+\r
+Py_complex\r
+c_quot(Py_complex a, Py_complex b)\r
+{\r
+ /******************************************************************\r
+ This was the original algorithm. It's grossly prone to spurious\r
+ overflow and underflow errors. It also merrily divides by 0 despite\r
+ checking for that(!). The code still serves a doc purpose here, as\r
+ the algorithm following is a simple by-cases transformation of this\r
+ one:\r
+\r
+ Py_complex r;\r
+ double d = b.real*b.real + b.imag*b.imag;\r
+ if (d == 0.)\r
+ errno = EDOM;\r
+ r.real = (a.real*b.real + a.imag*b.imag)/d;\r
+ r.imag = (a.imag*b.real - a.real*b.imag)/d;\r
+ return r;\r
+ ******************************************************************/\r
+\r
+ /* This algorithm is better, and is pretty obvious: first divide the\r
+ * numerators and denominator by whichever of {b.real, b.imag} has\r
+ * larger magnitude. The earliest reference I found was to CACM\r
+ * Algorithm 116 (Complex Division, Robert L. Smith, Stanford\r
+ * University). As usual, though, we're still ignoring all IEEE\r
+ * endcases.\r
+ */\r
+ Py_complex r; /* the result */\r
+ const double abs_breal = b.real < 0 ? -b.real : b.real;\r
+ const double abs_bimag = b.imag < 0 ? -b.imag : b.imag;\r
+\r
+ if (abs_breal >= abs_bimag) {\r
+ /* divide tops and bottom by b.real */\r
+ if (abs_breal == 0.0) {\r
+ errno = EDOM;\r
+ r.real = r.imag = 0.0;\r
+ }\r
+ else {\r
+ const double ratio = b.imag / b.real;\r
+ const double denom = b.real + b.imag * ratio;\r
+ r.real = (a.real + a.imag * ratio) / denom;\r
+ r.imag = (a.imag - a.real * ratio) / denom;\r
+ }\r
+ }\r
+ else if (abs_bimag >= abs_breal) {\r
+ /* divide tops and bottom by b.imag */\r
+ const double ratio = b.real / b.imag;\r
+ const double denom = b.real * ratio + b.imag;\r
+ assert(b.imag != 0.0);\r
+ r.real = (a.real * ratio + a.imag) / denom;\r
+ r.imag = (a.imag * ratio - a.real) / denom;\r
+ }\r
+ else {\r
+ /* At least one of b.real or b.imag is a NaN */\r
+ r.real = r.imag = Py_NAN;\r
+ }\r
+ return r;\r
+}\r
+\r
+Py_complex\r
+c_pow(Py_complex a, Py_complex b)\r
+{\r
+ Py_complex r;\r
+ double vabs,len,at,phase;\r
+ if (b.real == 0. && b.imag == 0.) {\r
+ r.real = 1.;\r
+ r.imag = 0.;\r
+ }\r
+ else if (a.real == 0. && a.imag == 0.) {\r
+ if (b.imag != 0. || b.real < 0.)\r
+ errno = EDOM;\r
+ r.real = 0.;\r
+ r.imag = 0.;\r
+ }\r
+ else {\r
+ vabs = hypot(a.real,a.imag);\r
+ len = pow(vabs,b.real);\r
+ at = atan2(a.imag, a.real);\r
+ phase = at*b.real;\r
+ if (b.imag != 0.0) {\r
+ len /= exp(at*b.imag);\r
+ phase += b.imag*log(vabs);\r
+ }\r
+ r.real = len*cos(phase);\r
+ r.imag = len*sin(phase);\r
+ }\r
+ return r;\r
+}\r
+\r
+static Py_complex\r
+c_powu(Py_complex x, long n)\r
+{\r
+ Py_complex r, p;\r
+ long mask = 1;\r
+ r = c_1;\r
+ p = x;\r
+ while (mask > 0 && n >= mask) {\r
+ if (n & mask)\r
+ r = c_prod(r,p);\r
+ mask <<= 1;\r
+ p = c_prod(p,p);\r
+ }\r
+ return r;\r
+}\r
+\r
+static Py_complex\r
+c_powi(Py_complex x, long n)\r
+{\r
+ Py_complex cn;\r
+\r
+ if (n > 100 || n < -100) {\r
+ cn.real = (double) n;\r
+ cn.imag = 0.;\r
+ return c_pow(x,cn);\r
+ }\r
+ else if (n > 0)\r
+ return c_powu(x,n);\r
+ else\r
+ return c_quot(c_1,c_powu(x,-n));\r
+\r
+}\r
+\r
+double\r
+c_abs(Py_complex z)\r
+{\r
+ /* sets errno = ERANGE on overflow; otherwise errno = 0 */\r
+ double result;\r
+\r
+ if (!Py_IS_FINITE(z.real) || !Py_IS_FINITE(z.imag)) {\r
+ /* C99 rules: if either the real or the imaginary part is an\r
+ infinity, return infinity, even if the other part is a\r
+ NaN. */\r
+ if (Py_IS_INFINITY(z.real)) {\r
+ result = fabs(z.real);\r
+ errno = 0;\r
+ return result;\r
+ }\r
+ if (Py_IS_INFINITY(z.imag)) {\r
+ result = fabs(z.imag);\r
+ errno = 0;\r
+ return result;\r
+ }\r
+ /* either the real or imaginary part is a NaN,\r
+ and neither is infinite. Result should be NaN. */\r
+ return Py_NAN;\r
+ }\r
+ result = hypot(z.real, z.imag);\r
+ if (!Py_IS_FINITE(result))\r
+ errno = ERANGE;\r
+ else\r
+ errno = 0;\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval)\r
+{\r
+ PyObject *op;\r
+\r
+ op = type->tp_alloc(type, 0);\r
+ if (op != NULL)\r
+ ((PyComplexObject *)op)->cval = cval;\r
+ return op;\r
+}\r
+\r
+PyObject *\r
+PyComplex_FromCComplex(Py_complex cval)\r
+{\r
+ register PyComplexObject *op;\r
+\r
+ /* Inline PyObject_New */\r
+ op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));\r
+ if (op == NULL)\r
+ return PyErr_NoMemory();\r
+ PyObject_INIT(op, &PyComplex_Type);\r
+ op->cval = cval;\r
+ return (PyObject *) op;\r
+}\r
+\r
+static PyObject *\r
+complex_subtype_from_doubles(PyTypeObject *type, double real, double imag)\r
+{\r
+ Py_complex c;\r
+ c.real = real;\r
+ c.imag = imag;\r
+ return complex_subtype_from_c_complex(type, c);\r
+}\r
+\r
+PyObject *\r
+PyComplex_FromDoubles(double real, double imag)\r
+{\r
+ Py_complex c;\r
+ c.real = real;\r
+ c.imag = imag;\r
+ return PyComplex_FromCComplex(c);\r
+}\r
+\r
+double\r
+PyComplex_RealAsDouble(PyObject *op)\r
+{\r
+ if (PyComplex_Check(op)) {\r
+ return ((PyComplexObject *)op)->cval.real;\r
+ }\r
+ else {\r
+ return PyFloat_AsDouble(op);\r
+ }\r
+}\r
+\r
+double\r
+PyComplex_ImagAsDouble(PyObject *op)\r
+{\r
+ if (PyComplex_Check(op)) {\r
+ return ((PyComplexObject *)op)->cval.imag;\r
+ }\r
+ else {\r
+ return 0.0;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+try_complex_special_method(PyObject *op) {\r
+ PyObject *f;\r
+ static PyObject *complexstr;\r
+\r
+ if (complexstr == NULL) {\r
+ complexstr = PyString_InternFromString("__complex__");\r
+ if (complexstr == NULL)\r
+ return NULL;\r
+ }\r
+ if (PyInstance_Check(op)) {\r
+ f = PyObject_GetAttr(op, complexstr);\r
+ if (f == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ PyErr_Clear();\r
+ else\r
+ return NULL;\r
+ }\r
+ }\r
+ else {\r
+ f = _PyObject_LookupSpecial(op, "__complex__", &complexstr);\r
+ if (f == NULL && PyErr_Occurred())\r
+ return NULL;\r
+ }\r
+ if (f != NULL) {\r
+ PyObject *res = PyObject_CallFunctionObjArgs(f, NULL);\r
+ Py_DECREF(f);\r
+ return res;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+Py_complex\r
+PyComplex_AsCComplex(PyObject *op)\r
+{\r
+ Py_complex cv;\r
+ PyObject *newop = NULL;\r
+\r
+ assert(op);\r
+ /* If op is already of type PyComplex_Type, return its value */\r
+ if (PyComplex_Check(op)) {\r
+ return ((PyComplexObject *)op)->cval;\r
+ }\r
+ /* If not, use op's __complex__ method, if it exists */\r
+\r
+ /* return -1 on failure */\r
+ cv.real = -1.;\r
+ cv.imag = 0.;\r
+\r
+ newop = try_complex_special_method(op);\r
+\r
+ if (newop) {\r
+ if (!PyComplex_Check(newop)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__complex__ should return a complex object");\r
+ Py_DECREF(newop);\r
+ return cv;\r
+ }\r
+ cv = ((PyComplexObject *)newop)->cval;\r
+ Py_DECREF(newop);\r
+ return cv;\r
+ }\r
+ else if (PyErr_Occurred()) {\r
+ return cv;\r
+ }\r
+ /* If neither of the above works, interpret op as a float giving the\r
+ real part of the result, and fill in the imaginary part as 0. */\r
+ else {\r
+ /* PyFloat_AsDouble will return -1 on failure */\r
+ cv.real = PyFloat_AsDouble(op);\r
+ return cv;\r
+ }\r
+}\r
+\r
+static void\r
+complex_dealloc(PyObject *op)\r
+{\r
+ op->ob_type->tp_free(op);\r
+}\r
+\r
+\r
+static PyObject *\r
+complex_format(PyComplexObject *v, int precision, char format_code)\r
+{\r
+ PyObject *result = NULL;\r
+ Py_ssize_t len;\r
+\r
+ /* If these are non-NULL, they'll need to be freed. */\r
+ char *pre = NULL;\r
+ char *im = NULL;\r
+ char *buf = NULL;\r
+\r
+ /* These do not need to be freed. re is either an alias\r
+ for pre or a pointer to a constant. lead and tail\r
+ are pointers to constants. */\r
+ char *re = NULL;\r
+ char *lead = "";\r
+ char *tail = "";\r
+\r
+ if (v->cval.real == 0. && copysign(1.0, v->cval.real)==1.0) {\r
+ re = "";\r
+ im = PyOS_double_to_string(v->cval.imag, format_code,\r
+ precision, 0, NULL);\r
+ if (!im) {\r
+ PyErr_NoMemory();\r
+ goto done;\r
+ }\r
+ } else {\r
+ /* Format imaginary part with sign, real part without */\r
+ pre = PyOS_double_to_string(v->cval.real, format_code,\r
+ precision, 0, NULL);\r
+ if (!pre) {\r
+ PyErr_NoMemory();\r
+ goto done;\r
+ }\r
+ re = pre;\r
+\r
+ im = PyOS_double_to_string(v->cval.imag, format_code,\r
+ precision, Py_DTSF_SIGN, NULL);\r
+ if (!im) {\r
+ PyErr_NoMemory();\r
+ goto done;\r
+ }\r
+ lead = "(";\r
+ tail = ")";\r
+ }\r
+ /* Alloc the final buffer. Add one for the "j" in the format string,\r
+ and one for the trailing zero. */\r
+ len = strlen(lead) + strlen(re) + strlen(im) + strlen(tail) + 2;\r
+ buf = PyMem_Malloc(len);\r
+ if (!buf) {\r
+ PyErr_NoMemory();\r
+ goto done;\r
+ }\r
+ PyOS_snprintf(buf, len, "%s%s%sj%s", lead, re, im, tail);\r
+ result = PyString_FromString(buf);\r
+ done:\r
+ PyMem_Free(im);\r
+ PyMem_Free(pre);\r
+ PyMem_Free(buf);\r
+\r
+ return result;\r
+}\r
+\r
+static int\r
+complex_print(PyComplexObject *v, FILE *fp, int flags)\r
+{\r
+ PyObject *formatv;\r
+ char *buf;\r
+ if (flags & Py_PRINT_RAW)\r
+ formatv = complex_format(v, PyFloat_STR_PRECISION, 'g');\r
+ else\r
+ formatv = complex_format(v, 0, 'r');\r
+ if (formatv == NULL)\r
+ return -1;\r
+ buf = PyString_AS_STRING(formatv);\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fputs(buf, fp);\r
+ Py_END_ALLOW_THREADS\r
+ Py_DECREF(formatv);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+complex_repr(PyComplexObject *v)\r
+{\r
+ return complex_format(v, 0, 'r');\r
+}\r
+\r
+static PyObject *\r
+complex_str(PyComplexObject *v)\r
+{\r
+ return complex_format(v, PyFloat_STR_PRECISION, 'g');\r
+}\r
+\r
+static long\r
+complex_hash(PyComplexObject *v)\r
+{\r
+ long hashreal, hashimag, combined;\r
+ hashreal = _Py_HashDouble(v->cval.real);\r
+ if (hashreal == -1)\r
+ return -1;\r
+ hashimag = _Py_HashDouble(v->cval.imag);\r
+ if (hashimag == -1)\r
+ return -1;\r
+ /* Note: if the imaginary part is 0, hashimag is 0 now,\r
+ * so the following returns hashreal unchanged. This is\r
+ * important because numbers of different types that\r
+ * compare equal must have the same hash value, so that\r
+ * hash(x + 0*j) must equal hash(x).\r
+ */\r
+ combined = hashreal + 1000003 * hashimag;\r
+ if (combined == -1)\r
+ combined = -2;\r
+ return combined;\r
+}\r
+\r
+/* This macro may return! */\r
+#define TO_COMPLEX(obj, c) \\r
+ if (PyComplex_Check(obj)) \\r
+ c = ((PyComplexObject *)(obj))->cval; \\r
+ else if (to_complex(&(obj), &(c)) < 0) \\r
+ return (obj)\r
+\r
+static int\r
+to_complex(PyObject **pobj, Py_complex *pc)\r
+{\r
+ PyObject *obj = *pobj;\r
+\r
+ pc->real = pc->imag = 0.0;\r
+ if (PyInt_Check(obj)) {\r
+ pc->real = PyInt_AS_LONG(obj);\r
+ return 0;\r
+ }\r
+ if (PyLong_Check(obj)) {\r
+ pc->real = PyLong_AsDouble(obj);\r
+ if (pc->real == -1.0 && PyErr_Occurred()) {\r
+ *pobj = NULL;\r
+ return -1;\r
+ }\r
+ return 0;\r
+ }\r
+ if (PyFloat_Check(obj)) {\r
+ pc->real = PyFloat_AsDouble(obj);\r
+ return 0;\r
+ }\r
+ Py_INCREF(Py_NotImplemented);\r
+ *pobj = Py_NotImplemented;\r
+ return -1;\r
+}\r
+\r
+\r
+static PyObject *\r
+complex_add(PyObject *v, PyObject *w)\r
+{\r
+ Py_complex result;\r
+ Py_complex a, b;\r
+ TO_COMPLEX(v, a);\r
+ TO_COMPLEX(w, b);\r
+ PyFPE_START_PROTECT("complex_add", return 0)\r
+ result = c_sum(a, b);\r
+ PyFPE_END_PROTECT(result)\r
+ return PyComplex_FromCComplex(result);\r
+}\r
+\r
+static PyObject *\r
+complex_sub(PyObject *v, PyObject *w)\r
+{\r
+ Py_complex result;\r
+ Py_complex a, b;\r
+ TO_COMPLEX(v, a);\r
+ TO_COMPLEX(w, b);;\r
+ PyFPE_START_PROTECT("complex_sub", return 0)\r
+ result = c_diff(a, b);\r
+ PyFPE_END_PROTECT(result)\r
+ return PyComplex_FromCComplex(result);\r
+}\r
+\r
+static PyObject *\r
+complex_mul(PyObject *v, PyObject *w)\r
+{\r
+ Py_complex result;\r
+ Py_complex a, b;\r
+ TO_COMPLEX(v, a);\r
+ TO_COMPLEX(w, b);\r
+ PyFPE_START_PROTECT("complex_mul", return 0)\r
+ result = c_prod(a, b);\r
+ PyFPE_END_PROTECT(result)\r
+ return PyComplex_FromCComplex(result);\r
+}\r
+\r
+static PyObject *\r
+complex_div(PyObject *v, PyObject *w)\r
+{\r
+ Py_complex quot;\r
+ Py_complex a, b;\r
+ TO_COMPLEX(v, a);\r
+ TO_COMPLEX(w, b);\r
+ PyFPE_START_PROTECT("complex_div", return 0)\r
+ errno = 0;\r
+ quot = c_quot(a, b);\r
+ PyFPE_END_PROTECT(quot)\r
+ if (errno == EDOM) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError, "complex division by zero");\r
+ return NULL;\r
+ }\r
+ return PyComplex_FromCComplex(quot);\r
+}\r
+\r
+static PyObject *\r
+complex_classic_div(PyObject *v, PyObject *w)\r
+{\r
+ Py_complex quot;\r
+ Py_complex a, b;\r
+ TO_COMPLEX(v, a);\r
+ TO_COMPLEX(w, b);\r
+ if (Py_DivisionWarningFlag >= 2 &&\r
+ PyErr_Warn(PyExc_DeprecationWarning,\r
+ "classic complex division") < 0)\r
+ return NULL;\r
+\r
+ PyFPE_START_PROTECT("complex_classic_div", return 0)\r
+ errno = 0;\r
+ quot = c_quot(a, b);\r
+ PyFPE_END_PROTECT(quot)\r
+ if (errno == EDOM) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError, "complex division by zero");\r
+ return NULL;\r
+ }\r
+ return PyComplex_FromCComplex(quot);\r
+}\r
+\r
+static PyObject *\r
+complex_remainder(PyObject *v, PyObject *w)\r
+{\r
+ Py_complex div, mod;\r
+ Py_complex a, b;\r
+ TO_COMPLEX(v, a);\r
+ TO_COMPLEX(w, b);\r
+ if (PyErr_Warn(PyExc_DeprecationWarning,\r
+ "complex divmod(), // and % are deprecated") < 0)\r
+ return NULL;\r
+\r
+ errno = 0;\r
+ div = c_quot(a, b); /* The raw divisor value. */\r
+ if (errno == EDOM) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError, "complex remainder");\r
+ return NULL;\r
+ }\r
+ div.real = floor(div.real); /* Use the floor of the real part. */\r
+ div.imag = 0.0;\r
+ mod = c_diff(a, c_prod(b, div));\r
+\r
+ return PyComplex_FromCComplex(mod);\r
+}\r
+\r
+\r
+static PyObject *\r
+complex_divmod(PyObject *v, PyObject *w)\r
+{\r
+ Py_complex div, mod;\r
+ PyObject *d, *m, *z;\r
+ Py_complex a, b;\r
+ TO_COMPLEX(v, a);\r
+ TO_COMPLEX(w, b);\r
+ if (PyErr_Warn(PyExc_DeprecationWarning,\r
+ "complex divmod(), // and % are deprecated") < 0)\r
+ return NULL;\r
+\r
+ errno = 0;\r
+ div = c_quot(a, b); /* The raw divisor value. */\r
+ if (errno == EDOM) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError, "complex divmod()");\r
+ return NULL;\r
+ }\r
+ div.real = floor(div.real); /* Use the floor of the real part. */\r
+ div.imag = 0.0;\r
+ mod = c_diff(a, c_prod(b, div));\r
+ d = PyComplex_FromCComplex(div);\r
+ m = PyComplex_FromCComplex(mod);\r
+ z = PyTuple_Pack(2, d, m);\r
+ Py_XDECREF(d);\r
+ Py_XDECREF(m);\r
+ return z;\r
+}\r
+\r
+static PyObject *\r
+complex_pow(PyObject *v, PyObject *w, PyObject *z)\r
+{\r
+ Py_complex p;\r
+ Py_complex exponent;\r
+ long int_exponent;\r
+ Py_complex a, b;\r
+ TO_COMPLEX(v, a);\r
+ TO_COMPLEX(w, b);\r
+ if (z!=Py_None) {\r
+ PyErr_SetString(PyExc_ValueError, "complex modulo");\r
+ return NULL;\r
+ }\r
+ PyFPE_START_PROTECT("complex_pow", return 0)\r
+ errno = 0;\r
+ exponent = b;\r
+ int_exponent = (long)exponent.real;\r
+ if (exponent.imag == 0. && exponent.real == int_exponent)\r
+ p = c_powi(a,int_exponent);\r
+ else\r
+ p = c_pow(a,exponent);\r
+\r
+ PyFPE_END_PROTECT(p)\r
+ Py_ADJUST_ERANGE2(p.real, p.imag);\r
+ if (errno == EDOM) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError,\r
+ "0.0 to a negative or complex power");\r
+ return NULL;\r
+ }\r
+ else if (errno == ERANGE) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "complex exponentiation");\r
+ return NULL;\r
+ }\r
+ return PyComplex_FromCComplex(p);\r
+}\r
+\r
+static PyObject *\r
+complex_int_div(PyObject *v, PyObject *w)\r
+{\r
+ PyObject *t, *r;\r
+ Py_complex a, b;\r
+ TO_COMPLEX(v, a);\r
+ TO_COMPLEX(w, b);\r
+ if (PyErr_Warn(PyExc_DeprecationWarning,\r
+ "complex divmod(), // and % are deprecated") < 0)\r
+ return NULL;\r
+\r
+ t = complex_divmod(v, w);\r
+ if (t != NULL) {\r
+ r = PyTuple_GET_ITEM(t, 0);\r
+ Py_INCREF(r);\r
+ Py_DECREF(t);\r
+ return r;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+complex_neg(PyComplexObject *v)\r
+{\r
+ Py_complex neg;\r
+ neg.real = -v->cval.real;\r
+ neg.imag = -v->cval.imag;\r
+ return PyComplex_FromCComplex(neg);\r
+}\r
+\r
+static PyObject *\r
+complex_pos(PyComplexObject *v)\r
+{\r
+ if (PyComplex_CheckExact(v)) {\r
+ Py_INCREF(v);\r
+ return (PyObject *)v;\r
+ }\r
+ else\r
+ return PyComplex_FromCComplex(v->cval);\r
+}\r
+\r
+static PyObject *\r
+complex_abs(PyComplexObject *v)\r
+{\r
+ double result;\r
+\r
+ PyFPE_START_PROTECT("complex_abs", return 0)\r
+ result = c_abs(v->cval);\r
+ PyFPE_END_PROTECT(result)\r
+\r
+ if (errno == ERANGE) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "absolute value too large");\r
+ return NULL;\r
+ }\r
+ return PyFloat_FromDouble(result);\r
+}\r
+\r
+static int\r
+complex_nonzero(PyComplexObject *v)\r
+{\r
+ return v->cval.real != 0.0 || v->cval.imag != 0.0;\r
+}\r
+\r
+static int\r
+complex_coerce(PyObject **pv, PyObject **pw)\r
+{\r
+ Py_complex cval;\r
+ cval.imag = 0.;\r
+ if (PyInt_Check(*pw)) {\r
+ cval.real = (double)PyInt_AsLong(*pw);\r
+ *pw = PyComplex_FromCComplex(cval);\r
+ Py_INCREF(*pv);\r
+ return 0;\r
+ }\r
+ else if (PyLong_Check(*pw)) {\r
+ cval.real = PyLong_AsDouble(*pw);\r
+ if (cval.real == -1.0 && PyErr_Occurred())\r
+ return -1;\r
+ *pw = PyComplex_FromCComplex(cval);\r
+ Py_INCREF(*pv);\r
+ return 0;\r
+ }\r
+ else if (PyFloat_Check(*pw)) {\r
+ cval.real = PyFloat_AsDouble(*pw);\r
+ *pw = PyComplex_FromCComplex(cval);\r
+ Py_INCREF(*pv);\r
+ return 0;\r
+ }\r
+ else if (PyComplex_Check(*pw)) {\r
+ Py_INCREF(*pv);\r
+ Py_INCREF(*pw);\r
+ return 0;\r
+ }\r
+ return 1; /* Can't do it */\r
+}\r
+\r
+static PyObject *\r
+complex_richcompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyObject *res;\r
+ Py_complex i;\r
+ int equal;\r
+\r
+ if (op != Py_EQ && op != Py_NE) {\r
+ /* for backwards compatibility, comparisons with non-numbers return\r
+ * NotImplemented. Only comparisons with core numeric types raise\r
+ * TypeError.\r
+ */\r
+ if (PyInt_Check(w) || PyLong_Check(w) ||\r
+ PyFloat_Check(w) || PyComplex_Check(w)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "no ordering relation is defined "\r
+ "for complex numbers");\r
+ return NULL;\r
+ }\r
+ goto Unimplemented;\r
+ }\r
+\r
+ assert(PyComplex_Check(v));\r
+ TO_COMPLEX(v, i);\r
+\r
+ if (PyInt_Check(w) || PyLong_Check(w)) {\r
+ /* Check for 0.0 imaginary part first to avoid the rich\r
+ * comparison when possible.\r
+ */\r
+ if (i.imag == 0.0) {\r
+ PyObject *j, *sub_res;\r
+ j = PyFloat_FromDouble(i.real);\r
+ if (j == NULL)\r
+ return NULL;\r
+\r
+ sub_res = PyObject_RichCompare(j, w, op);\r
+ Py_DECREF(j);\r
+ return sub_res;\r
+ }\r
+ else {\r
+ equal = 0;\r
+ }\r
+ }\r
+ else if (PyFloat_Check(w)) {\r
+ equal = (i.real == PyFloat_AsDouble(w) && i.imag == 0.0);\r
+ }\r
+ else if (PyComplex_Check(w)) {\r
+ Py_complex j;\r
+\r
+ TO_COMPLEX(w, j);\r
+ equal = (i.real == j.real && i.imag == j.imag);\r
+ }\r
+ else {\r
+ goto Unimplemented;\r
+ }\r
+\r
+ if (equal == (op == Py_EQ))\r
+ res = Py_True;\r
+ else\r
+ res = Py_False;\r
+\r
+ Py_INCREF(res);\r
+ return res;\r
+\r
+ Unimplemented:\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+}\r
+\r
+static PyObject *\r
+complex_int(PyObject *v)\r
+{\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "can't convert complex to int");\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+complex_long(PyObject *v)\r
+{\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "can't convert complex to long");\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+complex_float(PyObject *v)\r
+{\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "can't convert complex to float");\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+complex_conjugate(PyObject *self)\r
+{\r
+ Py_complex c;\r
+ c = ((PyComplexObject *)self)->cval;\r
+ c.imag = -c.imag;\r
+ return PyComplex_FromCComplex(c);\r
+}\r
+\r
+PyDoc_STRVAR(complex_conjugate_doc,\r
+"complex.conjugate() -> complex\n"\r
+"\n"\r
+"Return the complex conjugate of its argument. (3-4j).conjugate() == 3+4j.");\r
+\r
+static PyObject *\r
+complex_getnewargs(PyComplexObject *v)\r
+{\r
+ Py_complex c = v->cval;\r
+ return Py_BuildValue("(dd)", c.real, c.imag);\r
+}\r
+\r
+PyDoc_STRVAR(complex__format__doc,\r
+"complex.__format__() -> str\n"\r
+"\n"\r
+"Convert to a string according to format_spec.");\r
+\r
+static PyObject *\r
+complex__format__(PyObject* self, PyObject* args)\r
+{\r
+ PyObject *format_spec;\r
+\r
+ if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))\r
+ return NULL;\r
+ if (PyBytes_Check(format_spec))\r
+ return _PyComplex_FormatAdvanced(self,\r
+ PyBytes_AS_STRING(format_spec),\r
+ PyBytes_GET_SIZE(format_spec));\r
+ if (PyUnicode_Check(format_spec)) {\r
+ /* Convert format_spec to a str */\r
+ PyObject *result;\r
+ PyObject *str_spec = PyObject_Str(format_spec);\r
+\r
+ if (str_spec == NULL)\r
+ return NULL;\r
+\r
+ result = _PyComplex_FormatAdvanced(self,\r
+ PyBytes_AS_STRING(str_spec),\r
+ PyBytes_GET_SIZE(str_spec));\r
+\r
+ Py_DECREF(str_spec);\r
+ return result;\r
+ }\r
+ PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");\r
+ return NULL;\r
+}\r
+\r
+#if 0\r
+static PyObject *\r
+complex_is_finite(PyObject *self)\r
+{\r
+ Py_complex c;\r
+ c = ((PyComplexObject *)self)->cval;\r
+ return PyBool_FromLong((long)(Py_IS_FINITE(c.real) &&\r
+ Py_IS_FINITE(c.imag)));\r
+}\r
+\r
+PyDoc_STRVAR(complex_is_finite_doc,\r
+"complex.is_finite() -> bool\n"\r
+"\n"\r
+"Returns True if the real and the imaginary part is finite.");\r
+#endif\r
+\r
+static PyMethodDef complex_methods[] = {\r
+ {"conjugate", (PyCFunction)complex_conjugate, METH_NOARGS,\r
+ complex_conjugate_doc},\r
+#if 0\r
+ {"is_finite", (PyCFunction)complex_is_finite, METH_NOARGS,\r
+ complex_is_finite_doc},\r
+#endif\r
+ {"__getnewargs__", (PyCFunction)complex_getnewargs, METH_NOARGS},\r
+ {"__format__", (PyCFunction)complex__format__,\r
+ METH_VARARGS, complex__format__doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyMemberDef complex_members[] = {\r
+ {"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), READONLY,\r
+ "the real part of a complex number"},\r
+ {"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), READONLY,\r
+ "the imaginary part of a complex number"},\r
+ {0},\r
+};\r
+\r
+static PyObject *\r
+complex_subtype_from_string(PyTypeObject *type, PyObject *v)\r
+{\r
+ const char *s, *start;\r
+ char *end;\r
+ double x=0.0, y=0.0, z;\r
+ int got_bracket=0;\r
+#ifdef Py_USING_UNICODE\r
+ char *s_buffer = NULL;\r
+#endif\r
+ Py_ssize_t len;\r
+\r
+ if (PyString_Check(v)) {\r
+ s = PyString_AS_STRING(v);\r
+ len = PyString_GET_SIZE(v);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(v)) {\r
+ s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1);\r
+ if (s_buffer == NULL)\r
+ return PyErr_NoMemory();\r
+ if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),\r
+ PyUnicode_GET_SIZE(v),\r
+ s_buffer,\r
+ NULL))\r
+ goto error;\r
+ s = s_buffer;\r
+ len = strlen(s);\r
+ }\r
+#endif\r
+ else if (PyObject_AsCharBuffer(v, &s, &len)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "complex() arg is not a string");\r
+ return NULL;\r
+ }\r
+\r
+ /* position on first nonblank */\r
+ start = s;\r
+ while (Py_ISSPACE(*s))\r
+ s++;\r
+ if (*s == '(') {\r
+ /* Skip over possible bracket from repr(). */\r
+ got_bracket = 1;\r
+ s++;\r
+ while (Py_ISSPACE(*s))\r
+ s++;\r
+ }\r
+\r
+ /* a valid complex string usually takes one of the three forms:\r
+\r
+ <float> - real part only\r
+ <float>j - imaginary part only\r
+ <float><signed-float>j - real and imaginary parts\r
+\r
+ where <float> represents any numeric string that's accepted by the\r
+ float constructor (including 'nan', 'inf', 'infinity', etc.), and\r
+ <signed-float> is any string of the form <float> whose first\r
+ character is '+' or '-'.\r
+\r
+ For backwards compatibility, the extra forms\r
+\r
+ <float><sign>j\r
+ <sign>j\r
+ j\r
+\r
+ are also accepted, though support for these forms may be removed from\r
+ a future version of Python.\r
+ */\r
+\r
+ /* first look for forms starting with <float> */\r
+ z = PyOS_string_to_double(s, &end, NULL);\r
+ if (z == -1.0 && PyErr_Occurred()) {\r
+ if (PyErr_ExceptionMatches(PyExc_ValueError))\r
+ PyErr_Clear();\r
+ else\r
+ goto error;\r
+ }\r
+ if (end != s) {\r
+ /* all 4 forms starting with <float> land here */\r
+ s = end;\r
+ if (*s == '+' || *s == '-') {\r
+ /* <float><signed-float>j | <float><sign>j */\r
+ x = z;\r
+ y = PyOS_string_to_double(s, &end, NULL);\r
+ if (y == -1.0 && PyErr_Occurred()) {\r
+ if (PyErr_ExceptionMatches(PyExc_ValueError))\r
+ PyErr_Clear();\r
+ else\r
+ goto error;\r
+ }\r
+ if (end != s)\r
+ /* <float><signed-float>j */\r
+ s = end;\r
+ else {\r
+ /* <float><sign>j */\r
+ y = *s == '+' ? 1.0 : -1.0;\r
+ s++;\r
+ }\r
+ if (!(*s == 'j' || *s == 'J'))\r
+ goto parse_error;\r
+ s++;\r
+ }\r
+ else if (*s == 'j' || *s == 'J') {\r
+ /* <float>j */\r
+ s++;\r
+ y = z;\r
+ }\r
+ else\r
+ /* <float> */\r
+ x = z;\r
+ }\r
+ else {\r
+ /* not starting with <float>; must be <sign>j or j */\r
+ if (*s == '+' || *s == '-') {\r
+ /* <sign>j */\r
+ y = *s == '+' ? 1.0 : -1.0;\r
+ s++;\r
+ }\r
+ else\r
+ /* j */\r
+ y = 1.0;\r
+ if (!(*s == 'j' || *s == 'J'))\r
+ goto parse_error;\r
+ s++;\r
+ }\r
+\r
+ /* trailing whitespace and closing bracket */\r
+ while (Py_ISSPACE(*s))\r
+ s++;\r
+ if (got_bracket) {\r
+ /* if there was an opening parenthesis, then the corresponding\r
+ closing parenthesis should be right here */\r
+ if (*s != ')')\r
+ goto parse_error;\r
+ s++;\r
+ while (Py_ISSPACE(*s))\r
+ s++;\r
+ }\r
+\r
+ /* we should now be at the end of the string */\r
+ if (s-start != len)\r
+ goto parse_error;\r
+\r
+\r
+#ifdef Py_USING_UNICODE\r
+ if (s_buffer)\r
+ PyMem_FREE(s_buffer);\r
+#endif\r
+ return complex_subtype_from_doubles(type, x, y);\r
+\r
+ parse_error:\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "complex() arg is a malformed string");\r
+ error:\r
+#ifdef Py_USING_UNICODE\r
+ if (s_buffer)\r
+ PyMem_FREE(s_buffer);\r
+#endif\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *r, *i, *tmp;\r
+ PyNumberMethods *nbr, *nbi = NULL;\r
+ Py_complex cr, ci;\r
+ int own_r = 0;\r
+ int cr_is_complex = 0;\r
+ int ci_is_complex = 0;\r
+ static char *kwlist[] = {"real", "imag", 0};\r
+\r
+ r = Py_False;\r
+ i = NULL;\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:complex", kwlist,\r
+ &r, &i))\r
+ return NULL;\r
+\r
+ /* Special-case for a single argument when type(arg) is complex. */\r
+ if (PyComplex_CheckExact(r) && i == NULL &&\r
+ type == &PyComplex_Type) {\r
+ /* Note that we can't know whether it's safe to return\r
+ a complex *subclass* instance as-is, hence the restriction\r
+ to exact complexes here. If either the input or the\r
+ output is a complex subclass, it will be handled below\r
+ as a non-orthogonal vector. */\r
+ Py_INCREF(r);\r
+ return r;\r
+ }\r
+ if (PyString_Check(r) || PyUnicode_Check(r)) {\r
+ if (i != NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "complex() can't take second arg"\r
+ " if first is a string");\r
+ return NULL;\r
+ }\r
+ return complex_subtype_from_string(type, r);\r
+ }\r
+ if (i != NULL && (PyString_Check(i) || PyUnicode_Check(i))) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "complex() second arg can't be a string");\r
+ return NULL;\r
+ }\r
+\r
+ tmp = try_complex_special_method(r);\r
+ if (tmp) {\r
+ r = tmp;\r
+ own_r = 1;\r
+ }\r
+ else if (PyErr_Occurred()) {\r
+ return NULL;\r
+ }\r
+\r
+ nbr = r->ob_type->tp_as_number;\r
+ if (i != NULL)\r
+ nbi = i->ob_type->tp_as_number;\r
+ if (nbr == NULL || nbr->nb_float == NULL ||\r
+ ((i != NULL) && (nbi == NULL || nbi->nb_float == NULL))) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "complex() argument must be a string or a number");\r
+ if (own_r) {\r
+ Py_DECREF(r);\r
+ }\r
+ return NULL;\r
+ }\r
+\r
+ /* If we get this far, then the "real" and "imag" parts should\r
+ both be treated as numbers, and the constructor should return a\r
+ complex number equal to (real + imag*1j).\r
+\r
+ Note that we do NOT assume the input to already be in canonical\r
+ form; the "real" and "imag" parts might themselves be complex\r
+ numbers, which slightly complicates the code below. */\r
+ if (PyComplex_Check(r)) {\r
+ /* Note that if r is of a complex subtype, we're only\r
+ retaining its real & imag parts here, and the return\r
+ value is (properly) of the builtin complex type. */\r
+ cr = ((PyComplexObject*)r)->cval;\r
+ cr_is_complex = 1;\r
+ if (own_r) {\r
+ Py_DECREF(r);\r
+ }\r
+ }\r
+ else {\r
+ /* The "real" part really is entirely real, and contributes\r
+ nothing in the imaginary direction.\r
+ Just treat it as a double. */\r
+ tmp = PyNumber_Float(r);\r
+ if (own_r) {\r
+ /* r was a newly created complex number, rather\r
+ than the original "real" argument. */\r
+ Py_DECREF(r);\r
+ }\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ if (!PyFloat_Check(tmp)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "float(r) didn't return a float");\r
+ Py_DECREF(tmp);\r
+ return NULL;\r
+ }\r
+ cr.real = PyFloat_AsDouble(tmp);\r
+ cr.imag = 0.0; /* Shut up compiler warning */\r
+ Py_DECREF(tmp);\r
+ }\r
+ if (i == NULL) {\r
+ ci.real = 0.0;\r
+ }\r
+ else if (PyComplex_Check(i)) {\r
+ ci = ((PyComplexObject*)i)->cval;\r
+ ci_is_complex = 1;\r
+ } else {\r
+ /* The "imag" part really is entirely imaginary, and\r
+ contributes nothing in the real direction.\r
+ Just treat it as a double. */\r
+ tmp = (*nbi->nb_float)(i);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ ci.real = PyFloat_AsDouble(tmp);\r
+ Py_DECREF(tmp);\r
+ }\r
+ /* If the input was in canonical form, then the "real" and "imag"\r
+ parts are real numbers, so that ci.imag and cr.imag are zero.\r
+ We need this correction in case they were not real numbers. */\r
+\r
+ if (ci_is_complex) {\r
+ cr.real -= ci.imag;\r
+ }\r
+ if (cr_is_complex) {\r
+ ci.real += cr.imag;\r
+ }\r
+ return complex_subtype_from_doubles(type, cr.real, ci.real);\r
+}\r
+\r
+PyDoc_STRVAR(complex_doc,\r
+"complex(real[, imag]) -> complex number\n"\r
+"\n"\r
+"Create a complex number from a real part and an optional imaginary part.\n"\r
+"This is equivalent to (real + imag*1j) where imag defaults to 0.");\r
+\r
+static PyNumberMethods complex_as_number = {\r
+ (binaryfunc)complex_add, /* nb_add */\r
+ (binaryfunc)complex_sub, /* nb_subtract */\r
+ (binaryfunc)complex_mul, /* nb_multiply */\r
+ (binaryfunc)complex_classic_div, /* nb_divide */\r
+ (binaryfunc)complex_remainder, /* nb_remainder */\r
+ (binaryfunc)complex_divmod, /* nb_divmod */\r
+ (ternaryfunc)complex_pow, /* nb_power */\r
+ (unaryfunc)complex_neg, /* nb_negative */\r
+ (unaryfunc)complex_pos, /* nb_positive */\r
+ (unaryfunc)complex_abs, /* nb_absolute */\r
+ (inquiry)complex_nonzero, /* nb_nonzero */\r
+ 0, /* nb_invert */\r
+ 0, /* nb_lshift */\r
+ 0, /* nb_rshift */\r
+ 0, /* nb_and */\r
+ 0, /* nb_xor */\r
+ 0, /* nb_or */\r
+ complex_coerce, /* nb_coerce */\r
+ complex_int, /* nb_int */\r
+ complex_long, /* nb_long */\r
+ complex_float, /* nb_float */\r
+ 0, /* nb_oct */\r
+ 0, /* nb_hex */\r
+ 0, /* nb_inplace_add */\r
+ 0, /* nb_inplace_subtract */\r
+ 0, /* nb_inplace_multiply*/\r
+ 0, /* nb_inplace_divide */\r
+ 0, /* nb_inplace_remainder */\r
+ 0, /* nb_inplace_power */\r
+ 0, /* nb_inplace_lshift */\r
+ 0, /* nb_inplace_rshift */\r
+ 0, /* nb_inplace_and */\r
+ 0, /* nb_inplace_xor */\r
+ 0, /* nb_inplace_or */\r
+ (binaryfunc)complex_int_div, /* nb_floor_divide */\r
+ (binaryfunc)complex_div, /* nb_true_divide */\r
+ 0, /* nb_inplace_floor_divide */\r
+ 0, /* nb_inplace_true_divide */\r
+};\r
+\r
+PyTypeObject PyComplex_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "complex",\r
+ sizeof(PyComplexObject),\r
+ 0,\r
+ complex_dealloc, /* tp_dealloc */\r
+ (printfunc)complex_print, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)complex_repr, /* tp_repr */\r
+ &complex_as_number, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)complex_hash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ (reprfunc)complex_str, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |\r
+ Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ complex_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ complex_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ complex_methods, /* tp_methods */\r
+ complex_members, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ complex_new, /* tp_new */\r
+ PyObject_Del, /* tp_free */\r
+};\r
+\r
+#endif\r
--- /dev/null
+/* Descriptors -- a new, flexible way to describe attributes */\r
+\r
+#include "Python.h"\r
+#include "structmember.h" /* Why is this not included in Python.h? */\r
+\r
+static void\r
+descr_dealloc(PyDescrObject *descr)\r
+{\r
+ _PyObject_GC_UNTRACK(descr);\r
+ Py_XDECREF(descr->d_type);\r
+ Py_XDECREF(descr->d_name);\r
+ PyObject_GC_Del(descr);\r
+}\r
+\r
+static char *\r
+descr_name(PyDescrObject *descr)\r
+{\r
+ if (descr->d_name != NULL && PyString_Check(descr->d_name))\r
+ return PyString_AS_STRING(descr->d_name);\r
+ else\r
+ return "?";\r
+}\r
+\r
+static PyObject *\r
+descr_repr(PyDescrObject *descr, char *format)\r
+{\r
+ return PyString_FromFormat(format, descr_name(descr),\r
+ descr->d_type->tp_name);\r
+}\r
+\r
+static PyObject *\r
+method_repr(PyMethodDescrObject *descr)\r
+{\r
+ return descr_repr((PyDescrObject *)descr,\r
+ "<method '%s' of '%s' objects>");\r
+}\r
+\r
+static PyObject *\r
+member_repr(PyMemberDescrObject *descr)\r
+{\r
+ return descr_repr((PyDescrObject *)descr,\r
+ "<member '%s' of '%s' objects>");\r
+}\r
+\r
+static PyObject *\r
+getset_repr(PyGetSetDescrObject *descr)\r
+{\r
+ return descr_repr((PyDescrObject *)descr,\r
+ "<attribute '%s' of '%s' objects>");\r
+}\r
+\r
+static PyObject *\r
+wrapperdescr_repr(PyWrapperDescrObject *descr)\r
+{\r
+ return descr_repr((PyDescrObject *)descr,\r
+ "<slot wrapper '%s' of '%s' objects>");\r
+}\r
+\r
+static int\r
+descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)\r
+{\r
+ if (obj == NULL) {\r
+ Py_INCREF(descr);\r
+ *pres = (PyObject *)descr;\r
+ return 1;\r
+ }\r
+ if (!PyObject_TypeCheck(obj, descr->d_type)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%s' for '%s' objects "\r
+ "doesn't apply to '%s' object",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name,\r
+ obj->ob_type->tp_name);\r
+ *pres = NULL;\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)\r
+{\r
+ /* Ensure a valid type. Class methods ignore obj. */\r
+ if (type == NULL) {\r
+ if (obj != NULL)\r
+ type = (PyObject *)obj->ob_type;\r
+ else {\r
+ /* Wot - no type?! */\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%s' for type '%s' "\r
+ "needs either an object or a type",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name);\r
+ return NULL;\r
+ }\r
+ }\r
+ if (!PyType_Check(type)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%s' for type '%s' "\r
+ "needs a type, not a '%s' as arg 2",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name,\r
+ type->ob_type->tp_name);\r
+ return NULL;\r
+ }\r
+ if (!PyType_IsSubtype((PyTypeObject *)type, descr->d_type)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%s' for type '%s' "\r
+ "doesn't apply to type '%s'",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name,\r
+ ((PyTypeObject *)type)->tp_name);\r
+ return NULL;\r
+ }\r
+ return PyCFunction_New(descr->d_method, type);\r
+}\r
+\r
+static PyObject *\r
+method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)\r
+{\r
+ PyObject *res;\r
+\r
+ if (descr_check((PyDescrObject *)descr, obj, &res))\r
+ return res;\r
+ return PyCFunction_New(descr->d_method, obj);\r
+}\r
+\r
+static PyObject *\r
+member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)\r
+{\r
+ PyObject *res;\r
+\r
+ if (descr_check((PyDescrObject *)descr, obj, &res))\r
+ return res;\r
+ return PyMember_GetOne((char *)obj, descr->d_member);\r
+}\r
+\r
+static PyObject *\r
+getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)\r
+{\r
+ PyObject *res;\r
+\r
+ if (descr_check((PyDescrObject *)descr, obj, &res))\r
+ return res;\r
+ if (descr->d_getset->get != NULL)\r
+ return descr->d_getset->get(obj, descr->d_getset->closure);\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "attribute '%.300s' of '%.100s' objects is not readable",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name);\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)\r
+{\r
+ PyObject *res;\r
+\r
+ if (descr_check((PyDescrObject *)descr, obj, &res))\r
+ return res;\r
+ return PyWrapper_New((PyObject *)descr, obj);\r
+}\r
+\r
+static int\r
+descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,\r
+ int *pres)\r
+{\r
+ assert(obj != NULL);\r
+ if (!PyObject_TypeCheck(obj, descr->d_type)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%.200s' for '%.100s' objects "\r
+ "doesn't apply to '%.100s' object",\r
+ descr_name(descr),\r
+ descr->d_type->tp_name,\r
+ obj->ob_type->tp_name);\r
+ *pres = -1;\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)\r
+{\r
+ int res;\r
+\r
+ if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))\r
+ return res;\r
+ return PyMember_SetOne((char *)obj, descr->d_member, value);\r
+}\r
+\r
+static int\r
+getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)\r
+{\r
+ int res;\r
+\r
+ if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))\r
+ return res;\r
+ if (descr->d_getset->set != NULL)\r
+ return descr->d_getset->set(obj, value,\r
+ descr->d_getset->closure);\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "attribute '%.300s' of '%.100s' objects is not writable",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name);\r
+ return -1;\r
+}\r
+\r
+static PyObject *\r
+methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)\r
+{\r
+ Py_ssize_t argc;\r
+ PyObject *self, *func, *result;\r
+\r
+ /* Make sure that the first argument is acceptable as 'self' */\r
+ assert(PyTuple_Check(args));\r
+ argc = PyTuple_GET_SIZE(args);\r
+ if (argc < 1) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%.300s' of '%.100s' "\r
+ "object needs an argument",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name);\r
+ return NULL;\r
+ }\r
+ self = PyTuple_GET_ITEM(args, 0);\r
+ if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),\r
+ (PyObject *)(descr->d_type))) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%.200s' "\r
+ "requires a '%.100s' object "\r
+ "but received a '%.100s'",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name,\r
+ self->ob_type->tp_name);\r
+ return NULL;\r
+ }\r
+\r
+ func = PyCFunction_New(descr->d_method, self);\r
+ if (func == NULL)\r
+ return NULL;\r
+ args = PyTuple_GetSlice(args, 1, argc);\r
+ if (args == NULL) {\r
+ Py_DECREF(func);\r
+ return NULL;\r
+ }\r
+ result = PyEval_CallObjectWithKeywords(func, args, kwds);\r
+ Py_DECREF(args);\r
+ Py_DECREF(func);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,\r
+ PyObject *kwds)\r
+{\r
+ Py_ssize_t argc;\r
+ PyObject *self, *func, *result;\r
+\r
+ /* Make sure that the first argument is acceptable as 'self' */\r
+ assert(PyTuple_Check(args));\r
+ argc = PyTuple_GET_SIZE(args);\r
+ if (argc < 1) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%s' of '%.100s' "\r
+ "object needs an argument",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name);\r
+ return NULL;\r
+ }\r
+ self = PyTuple_GET_ITEM(args, 0);\r
+ if (!PyType_Check(self)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%s' requires a type "\r
+ "but received a '%.100s'",\r
+ descr_name((PyDescrObject *)descr),\r
+ self->ob_type->tp_name);\r
+ return NULL;\r
+ }\r
+ if (!PyType_IsSubtype((PyTypeObject *)self, descr->d_type)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%s' "\r
+ "requires a subtype of '%.100s' "\r
+ "but received '%.100s",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name,\r
+ self->ob_type->tp_name);\r
+ return NULL;\r
+ }\r
+\r
+ func = PyCFunction_New(descr->d_method, self);\r
+ if (func == NULL)\r
+ return NULL;\r
+ args = PyTuple_GetSlice(args, 1, argc);\r
+ if (args == NULL) {\r
+ Py_DECREF(func);\r
+ return NULL;\r
+ }\r
+ result = PyEval_CallObjectWithKeywords(func, args, kwds);\r
+ Py_DECREF(func);\r
+ Py_DECREF(args);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)\r
+{\r
+ Py_ssize_t argc;\r
+ PyObject *self, *func, *result;\r
+\r
+ /* Make sure that the first argument is acceptable as 'self' */\r
+ assert(PyTuple_Check(args));\r
+ argc = PyTuple_GET_SIZE(args);\r
+ if (argc < 1) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%.300s' of '%.100s' "\r
+ "object needs an argument",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name);\r
+ return NULL;\r
+ }\r
+ self = PyTuple_GET_ITEM(args, 0);\r
+ if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),\r
+ (PyObject *)(descr->d_type))) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "descriptor '%.200s' "\r
+ "requires a '%.100s' object "\r
+ "but received a '%.100s'",\r
+ descr_name((PyDescrObject *)descr),\r
+ descr->d_type->tp_name,\r
+ self->ob_type->tp_name);\r
+ return NULL;\r
+ }\r
+\r
+ func = PyWrapper_New((PyObject *)descr, self);\r
+ if (func == NULL)\r
+ return NULL;\r
+ args = PyTuple_GetSlice(args, 1, argc);\r
+ if (args == NULL) {\r
+ Py_DECREF(func);\r
+ return NULL;\r
+ }\r
+ result = PyEval_CallObjectWithKeywords(func, args, kwds);\r
+ Py_DECREF(args);\r
+ Py_DECREF(func);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+method_get_doc(PyMethodDescrObject *descr, void *closure)\r
+{\r
+ if (descr->d_method->ml_doc == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ return PyString_FromString(descr->d_method->ml_doc);\r
+}\r
+\r
+static PyMemberDef descr_members[] = {\r
+ {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},\r
+ {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},\r
+ {0}\r
+};\r
+\r
+static PyGetSetDef method_getset[] = {\r
+ {"__doc__", (getter)method_get_doc},\r
+ {0}\r
+};\r
+\r
+static PyObject *\r
+member_get_doc(PyMemberDescrObject *descr, void *closure)\r
+{\r
+ if (descr->d_member->doc == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ return PyString_FromString(descr->d_member->doc);\r
+}\r
+\r
+static PyGetSetDef member_getset[] = {\r
+ {"__doc__", (getter)member_get_doc},\r
+ {0}\r
+};\r
+\r
+static PyObject *\r
+getset_get_doc(PyGetSetDescrObject *descr, void *closure)\r
+{\r
+ if (descr->d_getset->doc == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ return PyString_FromString(descr->d_getset->doc);\r
+}\r
+\r
+static PyGetSetDef getset_getset[] = {\r
+ {"__doc__", (getter)getset_get_doc},\r
+ {0}\r
+};\r
+\r
+static PyObject *\r
+wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)\r
+{\r
+ if (descr->d_base->doc == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ return PyString_FromString(descr->d_base->doc);\r
+}\r
+\r
+static PyGetSetDef wrapperdescr_getset[] = {\r
+ {"__doc__", (getter)wrapperdescr_get_doc},\r
+ {0}\r
+};\r
+\r
+static int\r
+descr_traverse(PyObject *self, visitproc visit, void *arg)\r
+{\r
+ PyDescrObject *descr = (PyDescrObject *)self;\r
+ Py_VISIT(descr->d_type);\r
+ return 0;\r
+}\r
+\r
+static PyTypeObject PyMethodDescr_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "method_descriptor",\r
+ sizeof(PyMethodDescrObject),\r
+ 0,\r
+ (destructor)descr_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)method_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ (ternaryfunc)methoddescr_call, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ descr_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ descr_members, /* tp_members */\r
+ method_getset, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ (descrgetfunc)method_get, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+};\r
+\r
+/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */\r
+static PyTypeObject PyClassMethodDescr_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "classmethod_descriptor",\r
+ sizeof(PyMethodDescrObject),\r
+ 0,\r
+ (destructor)descr_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)method_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ (ternaryfunc)classmethoddescr_call, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ descr_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ descr_members, /* tp_members */\r
+ method_getset, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ (descrgetfunc)classmethod_get, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+};\r
+\r
+PyTypeObject PyMemberDescr_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "member_descriptor",\r
+ sizeof(PyMemberDescrObject),\r
+ 0,\r
+ (destructor)descr_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)member_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ descr_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ descr_members, /* tp_members */\r
+ member_getset, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ (descrgetfunc)member_get, /* tp_descr_get */\r
+ (descrsetfunc)member_set, /* tp_descr_set */\r
+};\r
+\r
+PyTypeObject PyGetSetDescr_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "getset_descriptor",\r
+ sizeof(PyGetSetDescrObject),\r
+ 0,\r
+ (destructor)descr_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)getset_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ descr_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ descr_members, /* tp_members */\r
+ getset_getset, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ (descrgetfunc)getset_get, /* tp_descr_get */\r
+ (descrsetfunc)getset_set, /* tp_descr_set */\r
+};\r
+\r
+PyTypeObject PyWrapperDescr_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "wrapper_descriptor",\r
+ sizeof(PyWrapperDescrObject),\r
+ 0,\r
+ (destructor)descr_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)wrapperdescr_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ (ternaryfunc)wrapperdescr_call, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ descr_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ descr_members, /* tp_members */\r
+ wrapperdescr_getset, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ (descrgetfunc)wrapperdescr_get, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+};\r
+\r
+static PyDescrObject *\r
+descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)\r
+{\r
+ PyDescrObject *descr;\r
+\r
+ descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);\r
+ if (descr != NULL) {\r
+ Py_XINCREF(type);\r
+ descr->d_type = type;\r
+ descr->d_name = PyString_InternFromString(name);\r
+ if (descr->d_name == NULL) {\r
+ Py_DECREF(descr);\r
+ descr = NULL;\r
+ }\r
+ }\r
+ return descr;\r
+}\r
+\r
+PyObject *\r
+PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)\r
+{\r
+ PyMethodDescrObject *descr;\r
+\r
+ descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,\r
+ type, method->ml_name);\r
+ if (descr != NULL)\r
+ descr->d_method = method;\r
+ return (PyObject *)descr;\r
+}\r
+\r
+PyObject *\r
+PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)\r
+{\r
+ PyMethodDescrObject *descr;\r
+\r
+ descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,\r
+ type, method->ml_name);\r
+ if (descr != NULL)\r
+ descr->d_method = method;\r
+ return (PyObject *)descr;\r
+}\r
+\r
+PyObject *\r
+PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)\r
+{\r
+ PyMemberDescrObject *descr;\r
+\r
+ descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,\r
+ type, member->name);\r
+ if (descr != NULL)\r
+ descr->d_member = member;\r
+ return (PyObject *)descr;\r
+}\r
+\r
+PyObject *\r
+PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)\r
+{\r
+ PyGetSetDescrObject *descr;\r
+\r
+ descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,\r
+ type, getset->name);\r
+ if (descr != NULL)\r
+ descr->d_getset = getset;\r
+ return (PyObject *)descr;\r
+}\r
+\r
+PyObject *\r
+PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)\r
+{\r
+ PyWrapperDescrObject *descr;\r
+\r
+ descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,\r
+ type, base->name);\r
+ if (descr != NULL) {\r
+ descr->d_base = base;\r
+ descr->d_wrapped = wrapped;\r
+ }\r
+ return (PyObject *)descr;\r
+}\r
+\r
+\r
+/* --- Readonly proxy for dictionaries (actually any mapping) --- */\r
+\r
+/* This has no reason to be in this file except that adding new files is a\r
+ bit of a pain */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyObject *dict;\r
+} proxyobject;\r
+\r
+static Py_ssize_t\r
+proxy_len(proxyobject *pp)\r
+{\r
+ return PyObject_Size(pp->dict);\r
+}\r
+\r
+static PyObject *\r
+proxy_getitem(proxyobject *pp, PyObject *key)\r
+{\r
+ return PyObject_GetItem(pp->dict, key);\r
+}\r
+\r
+static PyMappingMethods proxy_as_mapping = {\r
+ (lenfunc)proxy_len, /* mp_length */\r
+ (binaryfunc)proxy_getitem, /* mp_subscript */\r
+ 0, /* mp_ass_subscript */\r
+};\r
+\r
+static int\r
+proxy_contains(proxyobject *pp, PyObject *key)\r
+{\r
+ return PyDict_Contains(pp->dict, key);\r
+}\r
+\r
+static PySequenceMethods proxy_as_sequence = {\r
+ 0, /* sq_length */\r
+ 0, /* sq_concat */\r
+ 0, /* sq_repeat */\r
+ 0, /* sq_item */\r
+ 0, /* sq_slice */\r
+ 0, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ (objobjproc)proxy_contains, /* sq_contains */\r
+ 0, /* sq_inplace_concat */\r
+ 0, /* sq_inplace_repeat */\r
+};\r
+\r
+static PyObject *\r
+proxy_has_key(proxyobject *pp, PyObject *key)\r
+{\r
+ int res = PyDict_Contains(pp->dict, key);\r
+ if (res < 0)\r
+ return NULL;\r
+ return PyBool_FromLong(res);\r
+}\r
+\r
+static PyObject *\r
+proxy_get(proxyobject *pp, PyObject *args)\r
+{\r
+ PyObject *key, *def = Py_None;\r
+\r
+ if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))\r
+ return NULL;\r
+ return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def);\r
+}\r
+\r
+static PyObject *\r
+proxy_keys(proxyobject *pp)\r
+{\r
+ return PyMapping_Keys(pp->dict);\r
+}\r
+\r
+static PyObject *\r
+proxy_values(proxyobject *pp)\r
+{\r
+ return PyMapping_Values(pp->dict);\r
+}\r
+\r
+static PyObject *\r
+proxy_items(proxyobject *pp)\r
+{\r
+ return PyMapping_Items(pp->dict);\r
+}\r
+\r
+static PyObject *\r
+proxy_iterkeys(proxyobject *pp)\r
+{\r
+ return PyObject_CallMethod(pp->dict, "iterkeys", NULL);\r
+}\r
+\r
+static PyObject *\r
+proxy_itervalues(proxyobject *pp)\r
+{\r
+ return PyObject_CallMethod(pp->dict, "itervalues", NULL);\r
+}\r
+\r
+static PyObject *\r
+proxy_iteritems(proxyobject *pp)\r
+{\r
+ return PyObject_CallMethod(pp->dict, "iteritems", NULL);\r
+}\r
+static PyObject *\r
+proxy_copy(proxyobject *pp)\r
+{\r
+ return PyObject_CallMethod(pp->dict, "copy", NULL);\r
+}\r
+\r
+static PyMethodDef proxy_methods[] = {\r
+ {"has_key", (PyCFunction)proxy_has_key, METH_O,\r
+ PyDoc_STR("D.has_key(k) -> True if D has a key k, else False")},\r
+ {"get", (PyCFunction)proxy_get, METH_VARARGS,\r
+ PyDoc_STR("D.get(k[,d]) -> D[k] if D.has_key(k), else d."\r
+ " d defaults to None.")},\r
+ {"keys", (PyCFunction)proxy_keys, METH_NOARGS,\r
+ PyDoc_STR("D.keys() -> list of D's keys")},\r
+ {"values", (PyCFunction)proxy_values, METH_NOARGS,\r
+ PyDoc_STR("D.values() -> list of D's values")},\r
+ {"items", (PyCFunction)proxy_items, METH_NOARGS,\r
+ PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},\r
+ {"iterkeys", (PyCFunction)proxy_iterkeys, METH_NOARGS,\r
+ PyDoc_STR("D.iterkeys() -> an iterator over the keys of D")},\r
+ {"itervalues",(PyCFunction)proxy_itervalues, METH_NOARGS,\r
+ PyDoc_STR("D.itervalues() -> an iterator over the values of D")},\r
+ {"iteritems", (PyCFunction)proxy_iteritems, METH_NOARGS,\r
+ PyDoc_STR("D.iteritems() ->"\r
+ " an iterator over the (key, value) items of D")},\r
+ {"copy", (PyCFunction)proxy_copy, METH_NOARGS,\r
+ PyDoc_STR("D.copy() -> a shallow copy of D")},\r
+ {0}\r
+};\r
+\r
+static void\r
+proxy_dealloc(proxyobject *pp)\r
+{\r
+ _PyObject_GC_UNTRACK(pp);\r
+ Py_DECREF(pp->dict);\r
+ PyObject_GC_Del(pp);\r
+}\r
+\r
+static PyObject *\r
+proxy_getiter(proxyobject *pp)\r
+{\r
+ return PyObject_GetIter(pp->dict);\r
+}\r
+\r
+static PyObject *\r
+proxy_str(proxyobject *pp)\r
+{\r
+ return PyObject_Str(pp->dict);\r
+}\r
+\r
+static PyObject *\r
+proxy_repr(proxyobject *pp)\r
+{\r
+ PyObject *dictrepr;\r
+ PyObject *result;\r
+\r
+ dictrepr = PyObject_Repr(pp->dict);\r
+ if (dictrepr == NULL)\r
+ return NULL;\r
+ result = PyString_FromFormat("dict_proxy(%s)", PyString_AS_STRING(dictrepr));\r
+ Py_DECREF(dictrepr);\r
+ return result;\r
+}\r
+\r
+static int\r
+proxy_traverse(PyObject *self, visitproc visit, void *arg)\r
+{\r
+ proxyobject *pp = (proxyobject *)self;\r
+ Py_VISIT(pp->dict);\r
+ return 0;\r
+}\r
+\r
+static int\r
+proxy_compare(proxyobject *v, PyObject *w)\r
+{\r
+ return PyObject_Compare(v->dict, w);\r
+}\r
+\r
+static PyObject *\r
+proxy_richcompare(proxyobject *v, PyObject *w, int op)\r
+{\r
+ return PyObject_RichCompare(v->dict, w, op);\r
+}\r
+\r
+PyTypeObject PyDictProxy_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "dictproxy", /* tp_name */\r
+ sizeof(proxyobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)proxy_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)proxy_compare, /* tp_compare */\r
+ (reprfunc)proxy_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &proxy_as_sequence, /* tp_as_sequence */\r
+ &proxy_as_mapping, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ (reprfunc)proxy_str, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ proxy_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ (richcmpfunc)proxy_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ (getiterfunc)proxy_getiter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ proxy_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+};\r
+\r
+PyObject *\r
+PyDictProxy_New(PyObject *dict)\r
+{\r
+ proxyobject *pp;\r
+\r
+ pp = PyObject_GC_New(proxyobject, &PyDictProxy_Type);\r
+ if (pp != NULL) {\r
+ Py_INCREF(dict);\r
+ pp->dict = dict;\r
+ _PyObject_GC_TRACK(pp);\r
+ }\r
+ return (PyObject *)pp;\r
+}\r
+\r
+\r
+/* --- Wrapper object for "slot" methods --- */\r
+\r
+/* This has no reason to be in this file except that adding new files is a\r
+ bit of a pain */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyWrapperDescrObject *descr;\r
+ PyObject *self;\r
+} wrapperobject;\r
+\r
+static void\r
+wrapper_dealloc(wrapperobject *wp)\r
+{\r
+ PyObject_GC_UnTrack(wp);\r
+ Py_TRASHCAN_SAFE_BEGIN(wp)\r
+ Py_XDECREF(wp->descr);\r
+ Py_XDECREF(wp->self);\r
+ PyObject_GC_Del(wp);\r
+ Py_TRASHCAN_SAFE_END(wp)\r
+}\r
+\r
+static int\r
+wrapper_compare(wrapperobject *a, wrapperobject *b)\r
+{\r
+ if (a->descr == b->descr)\r
+ return PyObject_Compare(a->self, b->self);\r
+ else\r
+ return (a->descr < b->descr) ? -1 : 1;\r
+}\r
+\r
+static long\r
+wrapper_hash(wrapperobject *wp)\r
+{\r
+ int x, y;\r
+ x = _Py_HashPointer(wp->descr);\r
+ if (x == -1)\r
+ return -1;\r
+ y = PyObject_Hash(wp->self);\r
+ if (y == -1)\r
+ return -1;\r
+ x = x ^ y;\r
+ if (x == -1)\r
+ x = -2;\r
+ return x;\r
+}\r
+\r
+static PyObject *\r
+wrapper_repr(wrapperobject *wp)\r
+{\r
+ return PyString_FromFormat("<method-wrapper '%s' of %s object at %p>",\r
+ wp->descr->d_base->name,\r
+ wp->self->ob_type->tp_name,\r
+ wp->self);\r
+}\r
+\r
+static PyMemberDef wrapper_members[] = {\r
+ {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},\r
+ {0}\r
+};\r
+\r
+static PyObject *\r
+wrapper_objclass(wrapperobject *wp)\r
+{\r
+ PyObject *c = (PyObject *)wp->descr->d_type;\r
+\r
+ Py_INCREF(c);\r
+ return c;\r
+}\r
+\r
+static PyObject *\r
+wrapper_name(wrapperobject *wp)\r
+{\r
+ char *s = wp->descr->d_base->name;\r
+\r
+ return PyString_FromString(s);\r
+}\r
+\r
+static PyObject *\r
+wrapper_doc(wrapperobject *wp)\r
+{\r
+ char *s = wp->descr->d_base->doc;\r
+\r
+ if (s == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ else {\r
+ return PyString_FromString(s);\r
+ }\r
+}\r
+\r
+static PyGetSetDef wrapper_getsets[] = {\r
+ {"__objclass__", (getter)wrapper_objclass},\r
+ {"__name__", (getter)wrapper_name},\r
+ {"__doc__", (getter)wrapper_doc},\r
+ {0}\r
+};\r
+\r
+static PyObject *\r
+wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)\r
+{\r
+ wrapperfunc wrapper = wp->descr->d_base->wrapper;\r
+ PyObject *self = wp->self;\r
+\r
+ if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {\r
+ wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;\r
+ return (*wk)(self, args, wp->descr->d_wrapped, kwds);\r
+ }\r
+\r
+ if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_Size(kwds) != 0)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "wrapper %s doesn't take keyword arguments",\r
+ wp->descr->d_base->name);\r
+ return NULL;\r
+ }\r
+ return (*wrapper)(self, args, wp->descr->d_wrapped);\r
+}\r
+\r
+static int\r
+wrapper_traverse(PyObject *self, visitproc visit, void *arg)\r
+{\r
+ wrapperobject *wp = (wrapperobject *)self;\r
+ Py_VISIT(wp->descr);\r
+ Py_VISIT(wp->self);\r
+ return 0;\r
+}\r
+\r
+static PyTypeObject wrappertype = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "method-wrapper", /* tp_name */\r
+ sizeof(wrapperobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)wrapper_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)wrapper_compare, /* tp_compare */\r
+ (reprfunc)wrapper_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)wrapper_hash, /* tp_hash */\r
+ (ternaryfunc)wrapper_call, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ wrapper_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ wrapper_members, /* tp_members */\r
+ wrapper_getsets, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+};\r
+\r
+PyObject *\r
+PyWrapper_New(PyObject *d, PyObject *self)\r
+{\r
+ wrapperobject *wp;\r
+ PyWrapperDescrObject *descr;\r
+\r
+ assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));\r
+ descr = (PyWrapperDescrObject *)d;\r
+ assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),\r
+ (PyObject *)(descr->d_type)));\r
+\r
+ wp = PyObject_GC_New(wrapperobject, &wrappertype);\r
+ if (wp != NULL) {\r
+ Py_INCREF(descr);\r
+ wp->descr = descr;\r
+ Py_INCREF(self);\r
+ wp->self = self;\r
+ _PyObject_GC_TRACK(wp);\r
+ }\r
+ return (PyObject *)wp;\r
+}\r
+\r
+\r
+/* A built-in 'property' type */\r
+\r
+/*\r
+ class property(object):\r
+\r
+ def __init__(self, fget=None, fset=None, fdel=None, doc=None):\r
+ if doc is None and fget is not None and hasattr(fget, "__doc__"):\r
+ doc = fget.__doc__\r
+ self.__get = fget\r
+ self.__set = fset\r
+ self.__del = fdel\r
+ self.__doc__ = doc\r
+\r
+ def __get__(self, inst, type=None):\r
+ if inst is None:\r
+ return self\r
+ if self.__get is None:\r
+ raise AttributeError, "unreadable attribute"\r
+ return self.__get(inst)\r
+\r
+ def __set__(self, inst, value):\r
+ if self.__set is None:\r
+ raise AttributeError, "can't set attribute"\r
+ return self.__set(inst, value)\r
+\r
+ def __delete__(self, inst):\r
+ if self.__del is None:\r
+ raise AttributeError, "can't delete attribute"\r
+ return self.__del(inst)\r
+\r
+*/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyObject *prop_get;\r
+ PyObject *prop_set;\r
+ PyObject *prop_del;\r
+ PyObject *prop_doc;\r
+ int getter_doc;\r
+} propertyobject;\r
+\r
+static PyObject * property_copy(PyObject *, PyObject *, PyObject *,\r
+ PyObject *);\r
+\r
+static PyMemberDef property_members[] = {\r
+ {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},\r
+ {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},\r
+ {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},\r
+ {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), READONLY},\r
+ {0}\r
+};\r
+\r
+\r
+PyDoc_STRVAR(getter_doc,\r
+ "Descriptor to change the getter on a property.");\r
+\r
+static PyObject *\r
+property_getter(PyObject *self, PyObject *getter)\r
+{\r
+ return property_copy(self, getter, NULL, NULL);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(setter_doc,\r
+ "Descriptor to change the setter on a property.");\r
+\r
+static PyObject *\r
+property_setter(PyObject *self, PyObject *setter)\r
+{\r
+ return property_copy(self, NULL, setter, NULL);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(deleter_doc,\r
+ "Descriptor to change the deleter on a property.");\r
+\r
+static PyObject *\r
+property_deleter(PyObject *self, PyObject *deleter)\r
+{\r
+ return property_copy(self, NULL, NULL, deleter);\r
+}\r
+\r
+\r
+static PyMethodDef property_methods[] = {\r
+ {"getter", property_getter, METH_O, getter_doc},\r
+ {"setter", property_setter, METH_O, setter_doc},\r
+ {"deleter", property_deleter, METH_O, deleter_doc},\r
+ {0}\r
+};\r
+\r
+\r
+static void\r
+property_dealloc(PyObject *self)\r
+{\r
+ propertyobject *gs = (propertyobject *)self;\r
+\r
+ _PyObject_GC_UNTRACK(self);\r
+ Py_XDECREF(gs->prop_get);\r
+ Py_XDECREF(gs->prop_set);\r
+ Py_XDECREF(gs->prop_del);\r
+ Py_XDECREF(gs->prop_doc);\r
+ self->ob_type->tp_free(self);\r
+}\r
+\r
+static PyObject *\r
+property_descr_get(PyObject *self, PyObject *obj, PyObject *type)\r
+{\r
+ propertyobject *gs = (propertyobject *)self;\r
+\r
+ if (obj == NULL || obj == Py_None) {\r
+ Py_INCREF(self);\r
+ return self;\r
+ }\r
+ if (gs->prop_get == NULL) {\r
+ PyErr_SetString(PyExc_AttributeError, "unreadable attribute");\r
+ return NULL;\r
+ }\r
+ return PyObject_CallFunction(gs->prop_get, "(O)", obj);\r
+}\r
+\r
+static int\r
+property_descr_set(PyObject *self, PyObject *obj, PyObject *value)\r
+{\r
+ propertyobject *gs = (propertyobject *)self;\r
+ PyObject *func, *res;\r
+\r
+ if (value == NULL)\r
+ func = gs->prop_del;\r
+ else\r
+ func = gs->prop_set;\r
+ if (func == NULL) {\r
+ PyErr_SetString(PyExc_AttributeError,\r
+ value == NULL ?\r
+ "can't delete attribute" :\r
+ "can't set attribute");\r
+ return -1;\r
+ }\r
+ if (value == NULL)\r
+ res = PyObject_CallFunction(func, "(O)", obj);\r
+ else\r
+ res = PyObject_CallFunction(func, "(OO)", obj, value);\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)\r
+{\r
+ propertyobject *pold = (propertyobject *)old;\r
+ PyObject *new, *type, *doc;\r
+\r
+ type = PyObject_Type(old);\r
+ if (type == NULL)\r
+ return NULL;\r
+\r
+ if (get == NULL || get == Py_None) {\r
+ Py_XDECREF(get);\r
+ get = pold->prop_get ? pold->prop_get : Py_None;\r
+ }\r
+ if (set == NULL || set == Py_None) {\r
+ Py_XDECREF(set);\r
+ set = pold->prop_set ? pold->prop_set : Py_None;\r
+ }\r
+ if (del == NULL || del == Py_None) {\r
+ Py_XDECREF(del);\r
+ del = pold->prop_del ? pold->prop_del : Py_None;\r
+ }\r
+ if (pold->getter_doc && get != Py_None) {\r
+ /* make _init use __doc__ from getter */\r
+ doc = Py_None;\r
+ }\r
+ else {\r
+ doc = pold->prop_doc ? pold->prop_doc : Py_None;\r
+ }\r
+\r
+ new = PyObject_CallFunction(type, "OOOO", get, set, del, doc);\r
+ Py_DECREF(type);\r
+ if (new == NULL)\r
+ return NULL;\r
+ return new;\r
+}\r
+\r
+static int\r
+property_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;\r
+ static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};\r
+ propertyobject *prop = (propertyobject *)self;\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",\r
+ kwlist, &get, &set, &del, &doc))\r
+ return -1;\r
+\r
+ if (get == Py_None)\r
+ get = NULL;\r
+ if (set == Py_None)\r
+ set = NULL;\r
+ if (del == Py_None)\r
+ del = NULL;\r
+\r
+ Py_XINCREF(get);\r
+ Py_XINCREF(set);\r
+ Py_XINCREF(del);\r
+ Py_XINCREF(doc);\r
+\r
+ prop->prop_get = get;\r
+ prop->prop_set = set;\r
+ prop->prop_del = del;\r
+ prop->prop_doc = doc;\r
+ prop->getter_doc = 0;\r
+\r
+ /* if no docstring given and the getter has one, use that one */\r
+ if ((doc == NULL || doc == Py_None) && get != NULL) {\r
+ PyObject *get_doc = PyObject_GetAttrString(get, "__doc__");\r
+ if (get_doc) {\r
+ if (Py_TYPE(self) == &PyProperty_Type) {\r
+ Py_XDECREF(prop->prop_doc);\r
+ prop->prop_doc = get_doc;\r
+ }\r
+ else {\r
+ /* If this is a property subclass, put __doc__\r
+ in dict of the subclass instance instead,\r
+ otherwise it gets shadowed by __doc__ in the\r
+ class's dict. */\r
+ int err = PyObject_SetAttrString(self, "__doc__", get_doc);\r
+ Py_DECREF(get_doc);\r
+ if (err < 0)\r
+ return -1;\r
+ }\r
+ prop->getter_doc = 1;\r
+ }\r
+ else if (PyErr_ExceptionMatches(PyExc_Exception)) {\r
+ PyErr_Clear();\r
+ }\r
+ else {\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+PyDoc_STRVAR(property_doc,\r
+"property(fget=None, fset=None, fdel=None, doc=None) -> property attribute\n"\r
+"\n"\r
+"fget is a function to be used for getting an attribute value, and likewise\n"\r
+"fset is a function for setting, and fdel a function for del'ing, an\n"\r
+"attribute. Typical use is to define a managed attribute x:\n\n"\r
+"class C(object):\n"\r
+" def getx(self): return self._x\n"\r
+" def setx(self, value): self._x = value\n"\r
+" def delx(self): del self._x\n"\r
+" x = property(getx, setx, delx, \"I'm the 'x' property.\")\n"\r
+"\n"\r
+"Decorators make defining new properties or modifying existing ones easy:\n\n"\r
+"class C(object):\n"\r
+" @property\n"\r
+" def x(self):\n"\r
+" \"I am the 'x' property.\"\n"\r
+" return self._x\n"\r
+" @x.setter\n"\r
+" def x(self, value):\n"\r
+" self._x = value\n"\r
+" @x.deleter\n"\r
+" def x(self):\n"\r
+" del self._x\n"\r
+);\r
+\r
+static int\r
+property_traverse(PyObject *self, visitproc visit, void *arg)\r
+{\r
+ propertyobject *pp = (propertyobject *)self;\r
+ Py_VISIT(pp->prop_get);\r
+ Py_VISIT(pp->prop_set);\r
+ Py_VISIT(pp->prop_del);\r
+ Py_VISIT(pp->prop_doc);\r
+ return 0;\r
+}\r
+\r
+PyTypeObject PyProperty_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "property", /* tp_name */\r
+ sizeof(propertyobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ property_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ property_doc, /* tp_doc */\r
+ property_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ property_methods, /* tp_methods */\r
+ property_members, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ property_descr_get, /* tp_descr_get */\r
+ property_descr_set, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ property_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ PyType_GenericNew, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
--- /dev/null
+NOTES ON OPTIMIZING DICTIONARIES\r
+================================\r
+\r
+\r
+Principal Use Cases for Dictionaries\r
+------------------------------------\r
+\r
+Passing keyword arguments\r
+ Typically, one read and one write for 1 to 3 elements.\r
+ Occurs frequently in normal python code.\r
+\r
+Class method lookup\r
+ Dictionaries vary in size with 8 to 16 elements being common.\r
+ Usually written once with many lookups.\r
+ When base classes are used, there are many failed lookups\r
+ followed by a lookup in a base class.\r
+\r
+Instance attribute lookup and Global variables\r
+ Dictionaries vary in size. 4 to 10 elements are common.\r
+ Both reads and writes are common.\r
+\r
+Builtins\r
+ Frequent reads. Almost never written.\r
+ Size 126 interned strings (as of Py2.3b1).\r
+ A few keys are accessed much more frequently than others.\r
+\r
+Uniquification\r
+ Dictionaries of any size. Bulk of work is in creation.\r
+ Repeated writes to a smaller set of keys.\r
+ Single read of each key.\r
+ Some use cases have two consecutive accesses to the same key.\r
+\r
+ * Removing duplicates from a sequence.\r
+ dict.fromkeys(seqn).keys()\r
+\r
+ * Counting elements in a sequence.\r
+ for e in seqn:\r
+ d[e] = d.get(e,0) + 1\r
+\r
+ * Accumulating references in a dictionary of lists:\r
+\r
+ for pagenumber, page in enumerate(pages):\r
+ for word in page:\r
+ d.setdefault(word, []).append(pagenumber)\r
+\r
+ Note, the second example is a use case characterized by a get and set\r
+ to the same key. There are similar use cases with a __contains__\r
+ followed by a get, set, or del to the same key. Part of the\r
+ justification for d.setdefault is combining the two lookups into one.\r
+\r
+Membership Testing\r
+ Dictionaries of any size. Created once and then rarely changes.\r
+ Single write to each key.\r
+ Many calls to __contains__() or has_key().\r
+ Similar access patterns occur with replacement dictionaries\r
+ such as with the % formatting operator.\r
+\r
+Dynamic Mappings\r
+ Characterized by deletions interspersed with adds and replacements.\r
+ Performance benefits greatly from the re-use of dummy entries.\r
+\r
+\r
+Data Layout (assuming a 32-bit box with 64 bytes per cache line)\r
+----------------------------------------------------------------\r
+\r
+Smalldicts (8 entries) are attached to the dictobject structure\r
+and the whole group nearly fills two consecutive cache lines.\r
+\r
+Larger dicts use the first half of the dictobject structure (one cache\r
+line) and a separate, continuous block of entries (at 12 bytes each\r
+for a total of 5.333 entries per cache line).\r
+\r
+\r
+Tunable Dictionary Parameters\r
+-----------------------------\r
+\r
+* PyDict_MINSIZE. Currently set to 8.\r
+ Must be a power of two. New dicts have to zero-out every cell.\r
+ Each additional 8 consumes 1.5 cache lines. Increasing improves\r
+ the sparseness of small dictionaries but costs time to read in\r
+ the additional cache lines if they are not already in cache.\r
+ That case is common when keyword arguments are passed.\r
+\r
+* Maximum dictionary load in PyDict_SetItem. Currently set to 2/3.\r
+ Increasing this ratio makes dictionaries more dense resulting\r
+ in more collisions. Decreasing it improves sparseness at the\r
+ expense of spreading entries over more cache lines and at the\r
+ cost of total memory consumed.\r
+\r
+ The load test occurs in highly time sensitive code. Efforts\r
+ to make the test more complex (for example, varying the load\r
+ for different sizes) have degraded performance.\r
+\r
+* Growth rate upon hitting maximum load. Currently set to *2.\r
+ Raising this to *4 results in half the number of resizes,\r
+ less effort to resize, better sparseness for some (but not\r
+ all dict sizes), and potentially doubles memory consumption\r
+ depending on the size of the dictionary. Setting to *4\r
+ eliminates every other resize step.\r
+\r
+* Maximum sparseness (minimum dictionary load). What percentage\r
+ of entries can be unused before the dictionary shrinks to\r
+ free up memory and speed up iteration? (The current CPython\r
+ code does not represent this parameter directly.)\r
+\r
+* Shrinkage rate upon exceeding maximum sparseness. The current\r
+ CPython code never even checks sparseness when deleting a\r
+ key. When a new key is added, it resizes based on the number\r
+ of active keys, so that the addition may trigger shrinkage\r
+ rather than growth.\r
+\r
+Tune-ups should be measured across a broad range of applications and\r
+use cases. A change to any parameter will help in some situations and\r
+hurt in others. The key is to find settings that help the most common\r
+cases and do the least damage to the less common cases. Results will\r
+vary dramatically depending on the exact number of keys, whether the\r
+keys are all strings, whether reads or writes dominate, the exact\r
+hash values of the keys (some sets of values have fewer collisions than\r
+others). Any one test or benchmark is likely to prove misleading.\r
+\r
+While making a dictionary more sparse reduces collisions, it impairs\r
+iteration and key listing. Those methods loop over every potential\r
+entry. Doubling the size of dictionary results in twice as many\r
+non-overlapping memory accesses for keys(), items(), values(),\r
+__iter__(), iterkeys(), iteritems(), itervalues(), and update().\r
+Also, every dictionary iterates at least twice, once for the memset()\r
+when it is created and once by dealloc().\r
+\r
+Dictionary operations involving only a single key can be O(1) unless \r
+resizing is possible. By checking for a resize only when the \r
+dictionary can grow (and may *require* resizing), other operations\r
+remain O(1), and the odds of resize thrashing or memory fragmentation\r
+are reduced. In particular, an algorithm that empties a dictionary\r
+by repeatedly invoking .pop will see no resizing, which might\r
+not be necessary at all because the dictionary is eventually\r
+discarded entirely.\r
+\r
+\r
+Results of Cache Locality Experiments\r
+-------------------------------------\r
+\r
+When an entry is retrieved from memory, 4.333 adjacent entries are also\r
+retrieved into a cache line. Since accessing items in cache is *much*\r
+cheaper than a cache miss, an enticing idea is to probe the adjacent\r
+entries as a first step in collision resolution. Unfortunately, the\r
+introduction of any regularity into collision searches results in more\r
+collisions than the current random chaining approach.\r
+\r
+Exploiting cache locality at the expense of additional collisions fails\r
+to payoff when the entries are already loaded in cache (the expense\r
+is paid with no compensating benefit). This occurs in small dictionaries\r
+where the whole dictionary fits into a pair of cache lines. It also\r
+occurs frequently in large dictionaries which have a common access pattern\r
+where some keys are accessed much more frequently than others. The\r
+more popular entries *and* their collision chains tend to remain in cache.\r
+\r
+To exploit cache locality, change the collision resolution section\r
+in lookdict() and lookdict_string(). Set i^=1 at the top of the\r
+loop and move the i = (i << 2) + i + perturb + 1 to an unrolled\r
+version of the loop.\r
+\r
+This optimization strategy can be leveraged in several ways:\r
+\r
+* If the dictionary is kept sparse (through the tunable parameters),\r
+then the occurrence of additional collisions is lessened.\r
+\r
+* If lookdict() and lookdict_string() are specialized for small dicts\r
+and for largedicts, then the versions for large_dicts can be given\r
+an alternate search strategy without increasing collisions in small dicts\r
+which already have the maximum benefit of cache locality.\r
+\r
+* If the use case for a dictionary is known to have a random key\r
+access pattern (as opposed to a more common pattern with a Zipf's law\r
+distribution), then there will be more benefit for large dictionaries\r
+because any given key is no more likely than another to already be\r
+in cache.\r
+\r
+* In use cases with paired accesses to the same key, the second access\r
+is always in cache and gets no benefit from efforts to further improve\r
+cache locality.\r
+\r
+Optimizing the Search of Small Dictionaries\r
+-------------------------------------------\r
+\r
+If lookdict() and lookdict_string() are specialized for smaller dictionaries,\r
+then a custom search approach can be implemented that exploits the small\r
+search space and cache locality.\r
+\r
+* The simplest example is a linear search of contiguous entries. This is\r
+ simple to implement, guaranteed to terminate rapidly, never searches\r
+ the same entry twice, and precludes the need to check for dummy entries.\r
+\r
+* A more advanced example is a self-organizing search so that the most\r
+ frequently accessed entries get probed first. The organization\r
+ adapts if the access pattern changes over time. Treaps are ideally\r
+ suited for self-organization with the most common entries at the\r
+ top of the heap and a rapid binary search pattern. Most probes and\r
+ results are all located at the top of the tree allowing them all to\r
+ be located in one or two cache lines.\r
+\r
+* Also, small dictionaries may be made more dense, perhaps filling all\r
+ eight cells to take the maximum advantage of two cache lines.\r
+\r
+\r
+Strategy Pattern\r
+----------------\r
+\r
+Consider allowing the user to set the tunable parameters or to select a\r
+particular search method. Since some dictionary use cases have known\r
+sizes and access patterns, the user may be able to provide useful hints.\r
+\r
+1) For example, if membership testing or lookups dominate runtime and memory\r
+ is not at a premium, the user may benefit from setting the maximum load\r
+ ratio at 5% or 10% instead of the usual 66.7%. This will sharply\r
+ curtail the number of collisions but will increase iteration time.\r
+ The builtin namespace is a prime example of a dictionary that can\r
+ benefit from being highly sparse.\r
+\r
+2) Dictionary creation time can be shortened in cases where the ultimate\r
+ size of the dictionary is known in advance. The dictionary can be\r
+ pre-sized so that no resize operations are required during creation.\r
+ Not only does this save resizes, but the key insertion will go\r
+ more quickly because the first half of the keys will be inserted into\r
+ a more sparse environment than before. The preconditions for this\r
+ strategy arise whenever a dictionary is created from a key or item\r
+ sequence and the number of *unique* keys is known.\r
+\r
+3) If the key space is large and the access pattern is known to be random,\r
+ then search strategies exploiting cache locality can be fruitful.\r
+ The preconditions for this strategy arise in simulations and\r
+ numerical analysis.\r
+\r
+4) If the keys are fixed and the access pattern strongly favors some of\r
+ the keys, then the entries can be stored contiguously and accessed\r
+ with a linear search or treap. This exploits knowledge of the data,\r
+ cache locality, and a simplified search routine. It also eliminates\r
+ the need to test for dummy entries on each probe. The preconditions\r
+ for this strategy arise in symbol tables and in the builtin dictionary.\r
+\r
+\r
+Readonly Dictionaries\r
+---------------------\r
+Some dictionary use cases pass through a build stage and then move to a\r
+more heavily exercised lookup stage with no further changes to the\r
+dictionary.\r
+\r
+An idea that emerged on python-dev is to be able to convert a dictionary\r
+to a read-only state. This can help prevent programming errors and also\r
+provide knowledge that can be exploited for lookup optimization.\r
+\r
+The dictionary can be immediately rebuilt (eliminating dummy entries),\r
+resized (to an appropriate level of sparseness), and the keys can be\r
+jostled (to minimize collisions). The lookdict() routine can then\r
+eliminate the test for dummy entries (saving about 1/4 of the time\r
+spent in the collision resolution loop).\r
+\r
+An additional possibility is to insert links into the empty spaces\r
+so that dictionary iteration can proceed in len(d) steps instead of\r
+(mp->mask + 1) steps. Alternatively, a separate tuple of keys can be\r
+kept just for iteration.\r
+\r
+\r
+Caching Lookups\r
+---------------\r
+The idea is to exploit key access patterns by anticipating future lookups\r
+based on previous lookups.\r
+\r
+The simplest incarnation is to save the most recently accessed entry.\r
+This gives optimal performance for use cases where every get is followed\r
+by a set or del to the same key.\r
--- /dev/null
+\r
+/* Dictionary object implementation using a hash table */\r
+\r
+/* The distribution includes a separate file, Objects/dictnotes.txt,\r
+ describing explorations into dictionary design and optimization.\r
+ It covers typical dictionary use patterns, the parameters for\r
+ tuning dictionaries, and several ideas for possible optimizations.\r
+*/\r
+\r
+#include "Python.h"\r
+\r
+\r
+/* Set a key error with the specified argument, wrapping it in a\r
+ * tuple automatically so that tuple keys are not unpacked as the\r
+ * exception arguments. */\r
+static void\r
+set_key_error(PyObject *arg)\r
+{\r
+ PyObject *tup;\r
+ tup = PyTuple_Pack(1, arg);\r
+ if (!tup)\r
+ return; /* caller will expect error to be set anyway */\r
+ PyErr_SetObject(PyExc_KeyError, tup);\r
+ Py_DECREF(tup);\r
+}\r
+\r
+/* Define this out if you don't want conversion statistics on exit. */\r
+#undef SHOW_CONVERSION_COUNTS\r
+\r
+/* See large comment block below. This must be >= 1. */\r
+#define PERTURB_SHIFT 5\r
+\r
+/*\r
+Major subtleties ahead: Most hash schemes depend on having a "good" hash\r
+function, in the sense of simulating randomness. Python doesn't: its most\r
+important hash functions (for strings and ints) are very regular in common\r
+cases:\r
+\r
+>>> map(hash, (0, 1, 2, 3))\r
+[0, 1, 2, 3]\r
+>>> map(hash, ("namea", "nameb", "namec", "named"))\r
+[-1658398457, -1658398460, -1658398459, -1658398462]\r
+>>>\r
+\r
+This isn't necessarily bad! To the contrary, in a table of size 2**i, taking\r
+the low-order i bits as the initial table index is extremely fast, and there\r
+are no collisions at all for dicts indexed by a contiguous range of ints.\r
+The same is approximately true when keys are "consecutive" strings. So this\r
+gives better-than-random behavior in common cases, and that's very desirable.\r
+\r
+OTOH, when collisions occur, the tendency to fill contiguous slices of the\r
+hash table makes a good collision resolution strategy crucial. Taking only\r
+the last i bits of the hash code is also vulnerable: for example, consider\r
+[i << 16 for i in range(20000)] as a set of keys. Since ints are their own\r
+hash codes, and this fits in a dict of size 2**15, the last 15 bits of every\r
+hash code are all 0: they *all* map to the same table index.\r
+\r
+But catering to unusual cases should not slow the usual ones, so we just take\r
+the last i bits anyway. It's up to collision resolution to do the rest. If\r
+we *usually* find the key we're looking for on the first try (and, it turns\r
+out, we usually do -- the table load factor is kept under 2/3, so the odds\r
+are solidly in our favor), then it makes best sense to keep the initial index\r
+computation dirt cheap.\r
+\r
+The first half of collision resolution is to visit table indices via this\r
+recurrence:\r
+\r
+ j = ((5*j) + 1) mod 2**i\r
+\r
+For any initial j in range(2**i), repeating that 2**i times generates each\r
+int in range(2**i) exactly once (see any text on random-number generation for\r
+proof). By itself, this doesn't help much: like linear probing (setting\r
+j += 1, or j -= 1, on each loop trip), it scans the table entries in a fixed\r
+order. This would be bad, except that's not the only thing we do, and it's\r
+actually *good* in the common cases where hash keys are consecutive. In an\r
+example that's really too small to make this entirely clear, for a table of\r
+size 2**3 the order of indices is:\r
+\r
+ 0 -> 1 -> 6 -> 7 -> 4 -> 5 -> 2 -> 3 -> 0 [and here it's repeating]\r
+\r
+If two things come in at index 5, the first place we look after is index 2,\r
+not 6, so if another comes in at index 6 the collision at 5 didn't hurt it.\r
+Linear probing is deadly in this case because there the fixed probe order\r
+is the *same* as the order consecutive keys are likely to arrive. But it's\r
+extremely unlikely hash codes will follow a 5*j+1 recurrence by accident,\r
+and certain that consecutive hash codes do not.\r
+\r
+The other half of the strategy is to get the other bits of the hash code\r
+into play. This is done by initializing a (unsigned) vrbl "perturb" to the\r
+full hash code, and changing the recurrence to:\r
+\r
+ j = (5*j) + 1 + perturb;\r
+ perturb >>= PERTURB_SHIFT;\r
+ use j % 2**i as the next table index;\r
+\r
+Now the probe sequence depends (eventually) on every bit in the hash code,\r
+and the pseudo-scrambling property of recurring on 5*j+1 is more valuable,\r
+because it quickly magnifies small differences in the bits that didn't affect\r
+the initial index. Note that because perturb is unsigned, if the recurrence\r
+is executed often enough perturb eventually becomes and remains 0. At that\r
+point (very rarely reached) the recurrence is on (just) 5*j+1 again, and\r
+that's certain to find an empty slot eventually (since it generates every int\r
+in range(2**i), and we make sure there's always at least one empty slot).\r
+\r
+Selecting a good value for PERTURB_SHIFT is a balancing act. You want it\r
+small so that the high bits of the hash code continue to affect the probe\r
+sequence across iterations; but you want it large so that in really bad cases\r
+the high-order hash bits have an effect on early iterations. 5 was "the\r
+best" in minimizing total collisions across experiments Tim Peters ran (on\r
+both normal and pathological cases), but 4 and 6 weren't significantly worse.\r
+\r
+Historical: Reimer Behrends contributed the idea of using a polynomial-based\r
+approach, using repeated multiplication by x in GF(2**n) where an irreducible\r
+polynomial for each table size was chosen such that x was a primitive root.\r
+Christian Tismer later extended that to use division by x instead, as an\r
+efficient way to get the high bits of the hash code into play. This scheme\r
+also gave excellent collision statistics, but was more expensive: two\r
+if-tests were required inside the loop; computing "the next" index took about\r
+the same number of operations but without as much potential parallelism\r
+(e.g., computing 5*j can go on at the same time as computing 1+perturb in the\r
+above, and then shifting perturb can be done while the table index is being\r
+masked); and the PyDictObject struct required a member to hold the table's\r
+polynomial. In Tim's experiments the current scheme ran faster, produced\r
+equally good collision statistics, needed less code & used less memory.\r
+\r
+Theoretical Python 2.5 headache: hash codes are only C "long", but\r
+sizeof(Py_ssize_t) > sizeof(long) may be possible. In that case, and if a\r
+dict is genuinely huge, then only the slots directly reachable via indexing\r
+by a C long can be the first slot in a probe sequence. The probe sequence\r
+will still eventually reach every slot in the table, but the collision rate\r
+on initial probes may be much higher than this scheme was designed for.\r
+Getting a hash code as fat as Py_ssize_t is the only real cure. But in\r
+practice, this probably won't make a lick of difference for many years (at\r
+which point everyone will have terabytes of RAM on 64-bit boxes).\r
+*/\r
+\r
+/* Object used as dummy key to fill deleted entries */\r
+static PyObject *dummy = NULL; /* Initialized by first call to newPyDictObject() */\r
+\r
+#ifdef Py_REF_DEBUG\r
+PyObject *\r
+_PyDict_Dummy(void)\r
+{\r
+ return dummy;\r
+}\r
+#endif\r
+\r
+/* forward declarations */\r
+static PyDictEntry *\r
+lookdict_string(PyDictObject *mp, PyObject *key, long hash);\r
+\r
+#ifdef SHOW_CONVERSION_COUNTS\r
+static long created = 0L;\r
+static long converted = 0L;\r
+\r
+static void\r
+show_counts(void)\r
+{\r
+ fprintf(stderr, "created %ld string dicts\n", created);\r
+ fprintf(stderr, "converted %ld to normal dicts\n", converted);\r
+ fprintf(stderr, "%.2f%% conversion rate\n", (100.0*converted)/created);\r
+}\r
+#endif\r
+\r
+/* Debug statistic to compare allocations with reuse through the free list */\r
+#undef SHOW_ALLOC_COUNT\r
+#ifdef SHOW_ALLOC_COUNT\r
+static size_t count_alloc = 0;\r
+static size_t count_reuse = 0;\r
+\r
+static void\r
+show_alloc(void)\r
+{\r
+ fprintf(stderr, "Dict allocations: %" PY_FORMAT_SIZE_T "d\n",\r
+ count_alloc);\r
+ fprintf(stderr, "Dict reuse through freelist: %" PY_FORMAT_SIZE_T\r
+ "d\n", count_reuse);\r
+ fprintf(stderr, "%.2f%% reuse rate\n\n",\r
+ (100.0*count_reuse/(count_alloc+count_reuse)));\r
+}\r
+#endif\r
+\r
+/* Debug statistic to count GC tracking of dicts */\r
+#ifdef SHOW_TRACK_COUNT\r
+static Py_ssize_t count_untracked = 0;\r
+static Py_ssize_t count_tracked = 0;\r
+\r
+static void\r
+show_track(void)\r
+{\r
+ fprintf(stderr, "Dicts created: %" PY_FORMAT_SIZE_T "d\n",\r
+ count_tracked + count_untracked);\r
+ fprintf(stderr, "Dicts tracked by the GC: %" PY_FORMAT_SIZE_T\r
+ "d\n", count_tracked);\r
+ fprintf(stderr, "%.2f%% dict tracking rate\n\n",\r
+ (100.0*count_tracked/(count_untracked+count_tracked)));\r
+}\r
+#endif\r
+\r
+\r
+/* Initialization macros.\r
+ There are two ways to create a dict: PyDict_New() is the main C API\r
+ function, and the tp_new slot maps to dict_new(). In the latter case we\r
+ can save a little time over what PyDict_New does because it's guaranteed\r
+ that the PyDictObject struct is already zeroed out.\r
+ Everyone except dict_new() should use EMPTY_TO_MINSIZE (unless they have\r
+ an excellent reason not to).\r
+*/\r
+\r
+#define INIT_NONZERO_DICT_SLOTS(mp) do { \\r
+ (mp)->ma_table = (mp)->ma_smalltable; \\r
+ (mp)->ma_mask = PyDict_MINSIZE - 1; \\r
+ } while(0)\r
+\r
+#define EMPTY_TO_MINSIZE(mp) do { \\r
+ memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \\r
+ (mp)->ma_used = (mp)->ma_fill = 0; \\r
+ INIT_NONZERO_DICT_SLOTS(mp); \\r
+ } while(0)\r
+\r
+/* Dictionary reuse scheme to save calls to malloc, free, and memset */\r
+#ifndef PyDict_MAXFREELIST\r
+#define PyDict_MAXFREELIST 80\r
+#endif\r
+static PyDictObject *free_list[PyDict_MAXFREELIST];\r
+static int numfree = 0;\r
+\r
+void\r
+PyDict_Fini(void)\r
+{\r
+ PyDictObject *op;\r
+\r
+ while (numfree) {\r
+ op = free_list[--numfree];\r
+ assert(PyDict_CheckExact(op));\r
+ PyObject_GC_Del(op);\r
+ }\r
+}\r
+\r
+PyObject *\r
+PyDict_New(void)\r
+{\r
+ register PyDictObject *mp;\r
+ if (dummy == NULL) { /* Auto-initialize dummy */\r
+ dummy = PyString_FromString("<dummy key>");\r
+ if (dummy == NULL)\r
+ return NULL;\r
+#ifdef SHOW_CONVERSION_COUNTS\r
+ Py_AtExit(show_counts);\r
+#endif\r
+#ifdef SHOW_ALLOC_COUNT\r
+ Py_AtExit(show_alloc);\r
+#endif\r
+#ifdef SHOW_TRACK_COUNT\r
+ Py_AtExit(show_track);\r
+#endif\r
+ }\r
+ if (numfree) {\r
+ mp = free_list[--numfree];\r
+ assert (mp != NULL);\r
+ assert (Py_TYPE(mp) == &PyDict_Type);\r
+ _Py_NewReference((PyObject *)mp);\r
+ if (mp->ma_fill) {\r
+ EMPTY_TO_MINSIZE(mp);\r
+ } else {\r
+ /* At least set ma_table and ma_mask; these are wrong\r
+ if an empty but presized dict is added to freelist */\r
+ INIT_NONZERO_DICT_SLOTS(mp);\r
+ }\r
+ assert (mp->ma_used == 0);\r
+ assert (mp->ma_table == mp->ma_smalltable);\r
+ assert (mp->ma_mask == PyDict_MINSIZE - 1);\r
+#ifdef SHOW_ALLOC_COUNT\r
+ count_reuse++;\r
+#endif\r
+ } else {\r
+ mp = PyObject_GC_New(PyDictObject, &PyDict_Type);\r
+ if (mp == NULL)\r
+ return NULL;\r
+ EMPTY_TO_MINSIZE(mp);\r
+#ifdef SHOW_ALLOC_COUNT\r
+ count_alloc++;\r
+#endif\r
+ }\r
+ mp->ma_lookup = lookdict_string;\r
+#ifdef SHOW_TRACK_COUNT\r
+ count_untracked++;\r
+#endif\r
+#ifdef SHOW_CONVERSION_COUNTS\r
+ ++created;\r
+#endif\r
+ return (PyObject *)mp;\r
+}\r
+\r
+/*\r
+The basic lookup function used by all operations.\r
+This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.\r
+Open addressing is preferred over chaining since the link overhead for\r
+chaining would be substantial (100% with typical malloc overhead).\r
+\r
+The initial probe index is computed as hash mod the table size. Subsequent\r
+probe indices are computed as explained earlier.\r
+\r
+All arithmetic on hash should ignore overflow.\r
+\r
+(The details in this version are due to Tim Peters, building on many past\r
+contributions by Reimer Behrends, Jyrki Alakuijala, Vladimir Marangozov and\r
+Christian Tismer).\r
+\r
+lookdict() is general-purpose, and may return NULL if (and only if) a\r
+comparison raises an exception (this was new in Python 2.5).\r
+lookdict_string() below is specialized to string keys, comparison of which can\r
+never raise an exception; that function can never return NULL. For both, when\r
+the key isn't found a PyDictEntry* is returned for which the me_value field is\r
+NULL; this is the slot in the dict at which the key would have been found, and\r
+the caller can (if it wishes) add the <key, value> pair to the returned\r
+PyDictEntry*.\r
+*/\r
+static PyDictEntry *\r
+lookdict(PyDictObject *mp, PyObject *key, register long hash)\r
+{\r
+ register size_t i;\r
+ register size_t perturb;\r
+ register PyDictEntry *freeslot;\r
+ register size_t mask = (size_t)mp->ma_mask;\r
+ PyDictEntry *ep0 = mp->ma_table;\r
+ register PyDictEntry *ep;\r
+ register int cmp;\r
+ PyObject *startkey;\r
+\r
+ i = (size_t)hash & mask;\r
+ ep = &ep0[i];\r
+ if (ep->me_key == NULL || ep->me_key == key)\r
+ return ep;\r
+\r
+ if (ep->me_key == dummy)\r
+ freeslot = ep;\r
+ else {\r
+ if (ep->me_hash == hash) {\r
+ startkey = ep->me_key;\r
+ Py_INCREF(startkey);\r
+ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);\r
+ Py_DECREF(startkey);\r
+ if (cmp < 0)\r
+ return NULL;\r
+ if (ep0 == mp->ma_table && ep->me_key == startkey) {\r
+ if (cmp > 0)\r
+ return ep;\r
+ }\r
+ else {\r
+ /* The compare did major nasty stuff to the\r
+ * dict: start over.\r
+ * XXX A clever adversary could prevent this\r
+ * XXX from terminating.\r
+ */\r
+ return lookdict(mp, key, hash);\r
+ }\r
+ }\r
+ freeslot = NULL;\r
+ }\r
+\r
+ /* In the loop, me_key == dummy is by far (factor of 100s) the\r
+ least likely outcome, so test for that last. */\r
+ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {\r
+ i = (i << 2) + i + perturb + 1;\r
+ ep = &ep0[i & mask];\r
+ if (ep->me_key == NULL)\r
+ return freeslot == NULL ? ep : freeslot;\r
+ if (ep->me_key == key)\r
+ return ep;\r
+ if (ep->me_hash == hash && ep->me_key != dummy) {\r
+ startkey = ep->me_key;\r
+ Py_INCREF(startkey);\r
+ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);\r
+ Py_DECREF(startkey);\r
+ if (cmp < 0)\r
+ return NULL;\r
+ if (ep0 == mp->ma_table && ep->me_key == startkey) {\r
+ if (cmp > 0)\r
+ return ep;\r
+ }\r
+ else {\r
+ /* The compare did major nasty stuff to the\r
+ * dict: start over.\r
+ * XXX A clever adversary could prevent this\r
+ * XXX from terminating.\r
+ */\r
+ return lookdict(mp, key, hash);\r
+ }\r
+ }\r
+ else if (ep->me_key == dummy && freeslot == NULL)\r
+ freeslot = ep;\r
+ }\r
+ assert(0); /* NOT REACHED */\r
+ return 0;\r
+}\r
+\r
+/*\r
+ * Hacked up version of lookdict which can assume keys are always strings;\r
+ * this assumption allows testing for errors during PyObject_RichCompareBool()\r
+ * to be dropped; string-string comparisons never raise exceptions. This also\r
+ * means we don't need to go through PyObject_RichCompareBool(); we can always\r
+ * use _PyString_Eq() directly.\r
+ *\r
+ * This is valuable because dicts with only string keys are very common.\r
+ */\r
+static PyDictEntry *\r
+lookdict_string(PyDictObject *mp, PyObject *key, register long hash)\r
+{\r
+ register size_t i;\r
+ register size_t perturb;\r
+ register PyDictEntry *freeslot;\r
+ register size_t mask = (size_t)mp->ma_mask;\r
+ PyDictEntry *ep0 = mp->ma_table;\r
+ register PyDictEntry *ep;\r
+\r
+ /* Make sure this function doesn't have to handle non-string keys,\r
+ including subclasses of str; e.g., one reason to subclass\r
+ strings is to override __eq__, and for speed we don't cater to\r
+ that here. */\r
+ if (!PyString_CheckExact(key)) {\r
+#ifdef SHOW_CONVERSION_COUNTS\r
+ ++converted;\r
+#endif\r
+ mp->ma_lookup = lookdict;\r
+ return lookdict(mp, key, hash);\r
+ }\r
+ i = hash & mask;\r
+ ep = &ep0[i];\r
+ if (ep->me_key == NULL || ep->me_key == key)\r
+ return ep;\r
+ if (ep->me_key == dummy)\r
+ freeslot = ep;\r
+ else {\r
+ if (ep->me_hash == hash && _PyString_Eq(ep->me_key, key))\r
+ return ep;\r
+ freeslot = NULL;\r
+ }\r
+\r
+ /* In the loop, me_key == dummy is by far (factor of 100s) the\r
+ least likely outcome, so test for that last. */\r
+ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {\r
+ i = (i << 2) + i + perturb + 1;\r
+ ep = &ep0[i & mask];\r
+ if (ep->me_key == NULL)\r
+ return freeslot == NULL ? ep : freeslot;\r
+ if (ep->me_key == key\r
+ || (ep->me_hash == hash\r
+ && ep->me_key != dummy\r
+ && _PyString_Eq(ep->me_key, key)))\r
+ return ep;\r
+ if (ep->me_key == dummy && freeslot == NULL)\r
+ freeslot = ep;\r
+ }\r
+ assert(0); /* NOT REACHED */\r
+ return 0;\r
+}\r
+\r
+#ifdef SHOW_TRACK_COUNT\r
+#define INCREASE_TRACK_COUNT \\r
+ (count_tracked++, count_untracked--);\r
+#define DECREASE_TRACK_COUNT \\r
+ (count_tracked--, count_untracked++);\r
+#else\r
+#define INCREASE_TRACK_COUNT\r
+#define DECREASE_TRACK_COUNT\r
+#endif\r
+\r
+#define MAINTAIN_TRACKING(mp, key, value) \\r
+ do { \\r
+ if (!_PyObject_GC_IS_TRACKED(mp)) { \\r
+ if (_PyObject_GC_MAY_BE_TRACKED(key) || \\r
+ _PyObject_GC_MAY_BE_TRACKED(value)) { \\r
+ _PyObject_GC_TRACK(mp); \\r
+ INCREASE_TRACK_COUNT \\r
+ } \\r
+ } \\r
+ } while(0)\r
+\r
+void\r
+_PyDict_MaybeUntrack(PyObject *op)\r
+{\r
+ PyDictObject *mp;\r
+ PyObject *value;\r
+ Py_ssize_t mask, i;\r
+ PyDictEntry *ep;\r
+\r
+ if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))\r
+ return;\r
+\r
+ mp = (PyDictObject *) op;\r
+ ep = mp->ma_table;\r
+ mask = mp->ma_mask;\r
+ for (i = 0; i <= mask; i++) {\r
+ if ((value = ep[i].me_value) == NULL)\r
+ continue;\r
+ if (_PyObject_GC_MAY_BE_TRACKED(value) ||\r
+ _PyObject_GC_MAY_BE_TRACKED(ep[i].me_key))\r
+ return;\r
+ }\r
+ DECREASE_TRACK_COUNT\r
+ _PyObject_GC_UNTRACK(op);\r
+}\r
+\r
+/*\r
+Internal routine to insert a new item into the table when you have entry object.\r
+Used by insertdict.\r
+*/\r
+static int\r
+insertdict_by_entry(register PyDictObject *mp, PyObject *key, long hash,\r
+ PyDictEntry *ep, PyObject *value)\r
+{\r
+ PyObject *old_value;\r
+\r
+ MAINTAIN_TRACKING(mp, key, value);\r
+ if (ep->me_value != NULL) {\r
+ old_value = ep->me_value;\r
+ ep->me_value = value;\r
+ Py_DECREF(old_value); /* which **CAN** re-enter */\r
+ Py_DECREF(key);\r
+ }\r
+ else {\r
+ if (ep->me_key == NULL)\r
+ mp->ma_fill++;\r
+ else {\r
+ assert(ep->me_key == dummy);\r
+ Py_DECREF(dummy);\r
+ }\r
+ ep->me_key = key;\r
+ ep->me_hash = (Py_ssize_t)hash;\r
+ ep->me_value = value;\r
+ mp->ma_used++;\r
+ }\r
+ return 0;\r
+}\r
+\r
+\r
+/*\r
+Internal routine to insert a new item into the table.\r
+Used both by the internal resize routine and by the public insert routine.\r
+Eats a reference to key and one to value.\r
+Returns -1 if an error occurred, or 0 on success.\r
+*/\r
+static int\r
+insertdict(register PyDictObject *mp, PyObject *key, long hash, PyObject *value)\r
+{\r
+ register PyDictEntry *ep;\r
+\r
+ assert(mp->ma_lookup != NULL);\r
+ ep = mp->ma_lookup(mp, key, hash);\r
+ if (ep == NULL) {\r
+ Py_DECREF(key);\r
+ Py_DECREF(value);\r
+ return -1;\r
+ }\r
+ return insertdict_by_entry(mp, key, hash, ep, value);\r
+}\r
+\r
+/*\r
+Internal routine used by dictresize() to insert an item which is\r
+known to be absent from the dict. This routine also assumes that\r
+the dict contains no deleted entries. Besides the performance benefit,\r
+using insertdict() in dictresize() is dangerous (SF bug #1456209).\r
+Note that no refcounts are changed by this routine; if needed, the caller\r
+is responsible for incref'ing `key` and `value`.\r
+*/\r
+static void\r
+insertdict_clean(register PyDictObject *mp, PyObject *key, long hash,\r
+ PyObject *value)\r
+{\r
+ register size_t i;\r
+ register size_t perturb;\r
+ register size_t mask = (size_t)mp->ma_mask;\r
+ PyDictEntry *ep0 = mp->ma_table;\r
+ register PyDictEntry *ep;\r
+\r
+ MAINTAIN_TRACKING(mp, key, value);\r
+ i = hash & mask;\r
+ ep = &ep0[i];\r
+ for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) {\r
+ i = (i << 2) + i + perturb + 1;\r
+ ep = &ep0[i & mask];\r
+ }\r
+ assert(ep->me_value == NULL);\r
+ mp->ma_fill++;\r
+ ep->me_key = key;\r
+ ep->me_hash = (Py_ssize_t)hash;\r
+ ep->me_value = value;\r
+ mp->ma_used++;\r
+}\r
+\r
+/*\r
+Restructure the table by allocating a new table and reinserting all\r
+items again. When entries have been deleted, the new table may\r
+actually be smaller than the old one.\r
+*/\r
+static int\r
+dictresize(PyDictObject *mp, Py_ssize_t minused)\r
+{\r
+ Py_ssize_t newsize;\r
+ PyDictEntry *oldtable, *newtable, *ep;\r
+ Py_ssize_t i;\r
+ int is_oldtable_malloced;\r
+ PyDictEntry small_copy[PyDict_MINSIZE];\r
+\r
+ assert(minused >= 0);\r
+\r
+ /* Find the smallest table size > minused. */\r
+ for (newsize = PyDict_MINSIZE;\r
+ newsize <= minused && newsize > 0;\r
+ newsize <<= 1)\r
+ ;\r
+ if (newsize <= 0) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+\r
+ /* Get space for a new table. */\r
+ oldtable = mp->ma_table;\r
+ assert(oldtable != NULL);\r
+ is_oldtable_malloced = oldtable != mp->ma_smalltable;\r
+\r
+ if (newsize == PyDict_MINSIZE) {\r
+ /* A large table is shrinking, or we can't get any smaller. */\r
+ newtable = mp->ma_smalltable;\r
+ if (newtable == oldtable) {\r
+ if (mp->ma_fill == mp->ma_used) {\r
+ /* No dummies, so no point doing anything. */\r
+ return 0;\r
+ }\r
+ /* We're not going to resize it, but rebuild the\r
+ table anyway to purge old dummy entries.\r
+ Subtle: This is *necessary* if fill==size,\r
+ as lookdict needs at least one virgin slot to\r
+ terminate failing searches. If fill < size, it's\r
+ merely desirable, as dummies slow searches. */\r
+ assert(mp->ma_fill > mp->ma_used);\r
+ memcpy(small_copy, oldtable, sizeof(small_copy));\r
+ oldtable = small_copy;\r
+ }\r
+ }\r
+ else {\r
+ newtable = PyMem_NEW(PyDictEntry, newsize);\r
+ if (newtable == NULL) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ /* Make the dict empty, using the new table. */\r
+ assert(newtable != oldtable);\r
+ mp->ma_table = newtable;\r
+ mp->ma_mask = newsize - 1;\r
+ memset(newtable, 0, sizeof(PyDictEntry) * newsize);\r
+ mp->ma_used = 0;\r
+ i = mp->ma_fill;\r
+ mp->ma_fill = 0;\r
+\r
+ /* Copy the data over; this is refcount-neutral for active entries;\r
+ dummy entries aren't copied over, of course */\r
+ for (ep = oldtable; i > 0; ep++) {\r
+ if (ep->me_value != NULL) { /* active entry */\r
+ --i;\r
+ insertdict_clean(mp, ep->me_key, (long)ep->me_hash,\r
+ ep->me_value);\r
+ }\r
+ else if (ep->me_key != NULL) { /* dummy entry */\r
+ --i;\r
+ assert(ep->me_key == dummy);\r
+ Py_DECREF(ep->me_key);\r
+ }\r
+ /* else key == value == NULL: nothing to do */\r
+ }\r
+\r
+ if (is_oldtable_malloced)\r
+ PyMem_DEL(oldtable);\r
+ return 0;\r
+}\r
+\r
+/* Create a new dictionary pre-sized to hold an estimated number of elements.\r
+ Underestimates are okay because the dictionary will resize as necessary.\r
+ Overestimates just mean the dictionary will be more sparse than usual.\r
+*/\r
+\r
+PyObject *\r
+_PyDict_NewPresized(Py_ssize_t minused)\r
+{\r
+ PyObject *op = PyDict_New();\r
+\r
+ if (minused>5 && op != NULL && dictresize((PyDictObject *)op, minused) == -1) {\r
+ Py_DECREF(op);\r
+ return NULL;\r
+ }\r
+ return op;\r
+}\r
+\r
+/* Note that, for historical reasons, PyDict_GetItem() suppresses all errors\r
+ * that may occur (originally dicts supported only string keys, and exceptions\r
+ * weren't possible). So, while the original intent was that a NULL return\r
+ * meant the key wasn't present, in reality it can mean that, or that an error\r
+ * (suppressed) occurred while computing the key's hash, or that some error\r
+ * (suppressed) occurred when comparing keys in the dict's internal probe\r
+ * sequence. A nasty example of the latter is when a Python-coded comparison\r
+ * function hits a stack-depth error, which can cause this to return NULL\r
+ * even if the key is present.\r
+ */\r
+PyObject *\r
+PyDict_GetItem(PyObject *op, PyObject *key)\r
+{\r
+ long hash;\r
+ PyDictObject *mp = (PyDictObject *)op;\r
+ PyDictEntry *ep;\r
+ PyThreadState *tstate;\r
+ if (!PyDict_Check(op))\r
+ return NULL;\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1)\r
+ {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1) {\r
+ PyErr_Clear();\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ /* We can arrive here with a NULL tstate during initialization: try\r
+ running "python -Wi" for an example related to string interning.\r
+ Let's just hope that no exception occurs then... This must be\r
+ _PyThreadState_Current and not PyThreadState_GET() because in debug\r
+ mode, the latter complains if tstate is NULL. */\r
+ tstate = _PyThreadState_Current;\r
+ if (tstate != NULL && tstate->curexc_type != NULL) {\r
+ /* preserve the existing exception */\r
+ PyObject *err_type, *err_value, *err_tb;\r
+ PyErr_Fetch(&err_type, &err_value, &err_tb);\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ /* ignore errors */\r
+ PyErr_Restore(err_type, err_value, err_tb);\r
+ if (ep == NULL)\r
+ return NULL;\r
+ }\r
+ else {\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ if (ep == NULL) {\r
+ PyErr_Clear();\r
+ return NULL;\r
+ }\r
+ }\r
+ return ep->me_value;\r
+}\r
+\r
+static int\r
+dict_set_item_by_hash_or_entry(register PyObject *op, PyObject *key,\r
+ long hash, PyDictEntry *ep, PyObject *value)\r
+{\r
+ register PyDictObject *mp;\r
+ register Py_ssize_t n_used;\r
+\r
+ mp = (PyDictObject *)op;\r
+ assert(mp->ma_fill <= mp->ma_mask); /* at least one empty slot */\r
+ n_used = mp->ma_used;\r
+ Py_INCREF(value);\r
+ Py_INCREF(key);\r
+ if (ep == NULL) {\r
+ if (insertdict(mp, key, hash, value) != 0)\r
+ return -1;\r
+ }\r
+ else {\r
+ if (insertdict_by_entry(mp, key, hash, ep, value) != 0)\r
+ return -1;\r
+ }\r
+ /* If we added a key, we can safely resize. Otherwise just return!\r
+ * If fill >= 2/3 size, adjust size. Normally, this doubles or\r
+ * quaduples the size, but it's also possible for the dict to shrink\r
+ * (if ma_fill is much larger than ma_used, meaning a lot of dict\r
+ * keys have been * deleted).\r
+ *\r
+ * Quadrupling the size improves average dictionary sparseness\r
+ * (reducing collisions) at the cost of some memory and iteration\r
+ * speed (which loops over every possible entry). It also halves\r
+ * the number of expensive resize operations in a growing dictionary.\r
+ *\r
+ * Very large dictionaries (over 50K items) use doubling instead.\r
+ * This may help applications with severe memory constraints.\r
+ */\r
+ if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2))\r
+ return 0;\r
+ return dictresize(mp, (mp->ma_used > 50000 ? 2 : 4) * mp->ma_used);\r
+}\r
+\r
+/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the\r
+ * dictionary if it's merely replacing the value for an existing key.\r
+ * This means that it's safe to loop over a dictionary with PyDict_Next()\r
+ * and occasionally replace a value -- but you can't insert new keys or\r
+ * remove them.\r
+ */\r
+int\r
+PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)\r
+{\r
+ register long hash;\r
+\r
+ if (!PyDict_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ assert(key);\r
+ assert(value);\r
+ if (PyString_CheckExact(key)) {\r
+ hash = ((PyStringObject *)key)->ob_shash;\r
+ if (hash == -1)\r
+ hash = PyObject_Hash(key);\r
+ }\r
+ else {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return -1;\r
+ }\r
+ return dict_set_item_by_hash_or_entry(op, key, hash, NULL, value);\r
+}\r
+\r
+int\r
+PyDict_DelItem(PyObject *op, PyObject *key)\r
+{\r
+ register PyDictObject *mp;\r
+ register long hash;\r
+ register PyDictEntry *ep;\r
+ PyObject *old_value, *old_key;\r
+\r
+ if (!PyDict_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ assert(key);\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return -1;\r
+ }\r
+ mp = (PyDictObject *)op;\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ if (ep == NULL)\r
+ return -1;\r
+ if (ep->me_value == NULL) {\r
+ set_key_error(key);\r
+ return -1;\r
+ }\r
+ old_key = ep->me_key;\r
+ Py_INCREF(dummy);\r
+ ep->me_key = dummy;\r
+ old_value = ep->me_value;\r
+ ep->me_value = NULL;\r
+ mp->ma_used--;\r
+ Py_DECREF(old_value);\r
+ Py_DECREF(old_key);\r
+ return 0;\r
+}\r
+\r
+void\r
+PyDict_Clear(PyObject *op)\r
+{\r
+ PyDictObject *mp;\r
+ PyDictEntry *ep, *table;\r
+ int table_is_malloced;\r
+ Py_ssize_t fill;\r
+ PyDictEntry small_copy[PyDict_MINSIZE];\r
+#ifdef Py_DEBUG\r
+ Py_ssize_t i, n;\r
+#endif\r
+\r
+ if (!PyDict_Check(op))\r
+ return;\r
+ mp = (PyDictObject *)op;\r
+#ifdef Py_DEBUG\r
+ n = mp->ma_mask + 1;\r
+ i = 0;\r
+#endif\r
+\r
+ table = mp->ma_table;\r
+ assert(table != NULL);\r
+ table_is_malloced = table != mp->ma_smalltable;\r
+\r
+ /* This is delicate. During the process of clearing the dict,\r
+ * decrefs can cause the dict to mutate. To avoid fatal confusion\r
+ * (voice of experience), we have to make the dict empty before\r
+ * clearing the slots, and never refer to anything via mp->xxx while\r
+ * clearing.\r
+ */\r
+ fill = mp->ma_fill;\r
+ if (table_is_malloced)\r
+ EMPTY_TO_MINSIZE(mp);\r
+\r
+ else if (fill > 0) {\r
+ /* It's a small table with something that needs to be cleared.\r
+ * Afraid the only safe way is to copy the dict entries into\r
+ * another small table first.\r
+ */\r
+ memcpy(small_copy, table, sizeof(small_copy));\r
+ table = small_copy;\r
+ EMPTY_TO_MINSIZE(mp);\r
+ }\r
+ /* else it's a small table that's already empty */\r
+\r
+ /* Now we can finally clear things. If C had refcounts, we could\r
+ * assert that the refcount on table is 1 now, i.e. that this function\r
+ * has unique access to it, so decref side-effects can't alter it.\r
+ */\r
+ for (ep = table; fill > 0; ++ep) {\r
+#ifdef Py_DEBUG\r
+ assert(i < n);\r
+ ++i;\r
+#endif\r
+ if (ep->me_key) {\r
+ --fill;\r
+ Py_DECREF(ep->me_key);\r
+ Py_XDECREF(ep->me_value);\r
+ }\r
+#ifdef Py_DEBUG\r
+ else\r
+ assert(ep->me_value == NULL);\r
+#endif\r
+ }\r
+\r
+ if (table_is_malloced)\r
+ PyMem_DEL(table);\r
+}\r
+\r
+/*\r
+ * Iterate over a dict. Use like so:\r
+ *\r
+ * Py_ssize_t i;\r
+ * PyObject *key, *value;\r
+ * i = 0; # important! i should not otherwise be changed by you\r
+ * while (PyDict_Next(yourdict, &i, &key, &value)) {\r
+ * Refer to borrowed references in key and value.\r
+ * }\r
+ *\r
+ * CAUTION: In general, it isn't safe to use PyDict_Next in a loop that\r
+ * mutates the dict. One exception: it is safe if the loop merely changes\r
+ * the values associated with the keys (but doesn't insert new keys or\r
+ * delete keys), via PyDict_SetItem().\r
+ */\r
+int\r
+PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)\r
+{\r
+ register Py_ssize_t i;\r
+ register Py_ssize_t mask;\r
+ register PyDictEntry *ep;\r
+\r
+ if (!PyDict_Check(op))\r
+ return 0;\r
+ i = *ppos;\r
+ if (i < 0)\r
+ return 0;\r
+ ep = ((PyDictObject *)op)->ma_table;\r
+ mask = ((PyDictObject *)op)->ma_mask;\r
+ while (i <= mask && ep[i].me_value == NULL)\r
+ i++;\r
+ *ppos = i+1;\r
+ if (i > mask)\r
+ return 0;\r
+ if (pkey)\r
+ *pkey = ep[i].me_key;\r
+ if (pvalue)\r
+ *pvalue = ep[i].me_value;\r
+ return 1;\r
+}\r
+\r
+/* Internal version of PyDict_Next that returns a hash value in addition to the key and value.*/\r
+int\r
+_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, long *phash)\r
+{\r
+ register Py_ssize_t i;\r
+ register Py_ssize_t mask;\r
+ register PyDictEntry *ep;\r
+\r
+ if (!PyDict_Check(op))\r
+ return 0;\r
+ i = *ppos;\r
+ if (i < 0)\r
+ return 0;\r
+ ep = ((PyDictObject *)op)->ma_table;\r
+ mask = ((PyDictObject *)op)->ma_mask;\r
+ while (i <= mask && ep[i].me_value == NULL)\r
+ i++;\r
+ *ppos = i+1;\r
+ if (i > mask)\r
+ return 0;\r
+ *phash = (long)(ep[i].me_hash);\r
+ if (pkey)\r
+ *pkey = ep[i].me_key;\r
+ if (pvalue)\r
+ *pvalue = ep[i].me_value;\r
+ return 1;\r
+}\r
+\r
+/* Methods */\r
+\r
+static void\r
+dict_dealloc(register PyDictObject *mp)\r
+{\r
+ register PyDictEntry *ep;\r
+ Py_ssize_t fill = mp->ma_fill;\r
+ PyObject_GC_UnTrack(mp);\r
+ Py_TRASHCAN_SAFE_BEGIN(mp)\r
+ for (ep = mp->ma_table; fill > 0; ep++) {\r
+ if (ep->me_key) {\r
+ --fill;\r
+ Py_DECREF(ep->me_key);\r
+ Py_XDECREF(ep->me_value);\r
+ }\r
+ }\r
+ if (mp->ma_table != mp->ma_smalltable)\r
+ PyMem_DEL(mp->ma_table);\r
+ if (numfree < PyDict_MAXFREELIST && Py_TYPE(mp) == &PyDict_Type)\r
+ free_list[numfree++] = mp;\r
+ else\r
+ Py_TYPE(mp)->tp_free((PyObject *)mp);\r
+ Py_TRASHCAN_SAFE_END(mp)\r
+}\r
+\r
+static int\r
+dict_print(register PyDictObject *mp, register FILE *fp, register int flags)\r
+{\r
+ register Py_ssize_t i;\r
+ register Py_ssize_t any;\r
+ int status;\r
+\r
+ status = Py_ReprEnter((PyObject*)mp);\r
+ if (status != 0) {\r
+ if (status < 0)\r
+ return status;\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "{...}");\r
+ Py_END_ALLOW_THREADS\r
+ return 0;\r
+ }\r
+\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "{");\r
+ Py_END_ALLOW_THREADS\r
+ any = 0;\r
+ for (i = 0; i <= mp->ma_mask; i++) {\r
+ PyDictEntry *ep = mp->ma_table + i;\r
+ PyObject *pvalue = ep->me_value;\r
+ if (pvalue != NULL) {\r
+ /* Prevent PyObject_Repr from deleting value during\r
+ key format */\r
+ Py_INCREF(pvalue);\r
+ if (any++ > 0) {\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, ", ");\r
+ Py_END_ALLOW_THREADS\r
+ }\r
+ if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) {\r
+ Py_DECREF(pvalue);\r
+ Py_ReprLeave((PyObject*)mp);\r
+ return -1;\r
+ }\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, ": ");\r
+ Py_END_ALLOW_THREADS\r
+ if (PyObject_Print(pvalue, fp, 0) != 0) {\r
+ Py_DECREF(pvalue);\r
+ Py_ReprLeave((PyObject*)mp);\r
+ return -1;\r
+ }\r
+ Py_DECREF(pvalue);\r
+ }\r
+ }\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "}");\r
+ Py_END_ALLOW_THREADS\r
+ Py_ReprLeave((PyObject*)mp);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+dict_repr(PyDictObject *mp)\r
+{\r
+ Py_ssize_t i;\r
+ PyObject *s, *temp, *colon = NULL;\r
+ PyObject *pieces = NULL, *result = NULL;\r
+ PyObject *key, *value;\r
+\r
+ i = Py_ReprEnter((PyObject *)mp);\r
+ if (i != 0) {\r
+ return i > 0 ? PyString_FromString("{...}") : NULL;\r
+ }\r
+\r
+ if (mp->ma_used == 0) {\r
+ result = PyString_FromString("{}");\r
+ goto Done;\r
+ }\r
+\r
+ pieces = PyList_New(0);\r
+ if (pieces == NULL)\r
+ goto Done;\r
+\r
+ colon = PyString_FromString(": ");\r
+ if (colon == NULL)\r
+ goto Done;\r
+\r
+ /* Do repr() on each key+value pair, and insert ": " between them.\r
+ Note that repr may mutate the dict. */\r
+ i = 0;\r
+ while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {\r
+ int status;\r
+ /* Prevent repr from deleting value during key format. */\r
+ Py_INCREF(value);\r
+ s = PyObject_Repr(key);\r
+ PyString_Concat(&s, colon);\r
+ PyString_ConcatAndDel(&s, PyObject_Repr(value));\r
+ Py_DECREF(value);\r
+ if (s == NULL)\r
+ goto Done;\r
+ status = PyList_Append(pieces, s);\r
+ Py_DECREF(s); /* append created a new ref */\r
+ if (status < 0)\r
+ goto Done;\r
+ }\r
+\r
+ /* Add "{}" decorations to the first and last items. */\r
+ assert(PyList_GET_SIZE(pieces) > 0);\r
+ s = PyString_FromString("{");\r
+ if (s == NULL)\r
+ goto Done;\r
+ temp = PyList_GET_ITEM(pieces, 0);\r
+ PyString_ConcatAndDel(&s, temp);\r
+ PyList_SET_ITEM(pieces, 0, s);\r
+ if (s == NULL)\r
+ goto Done;\r
+\r
+ s = PyString_FromString("}");\r
+ if (s == NULL)\r
+ goto Done;\r
+ temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);\r
+ PyString_ConcatAndDel(&temp, s);\r
+ PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);\r
+ if (temp == NULL)\r
+ goto Done;\r
+\r
+ /* Paste them all together with ", " between. */\r
+ s = PyString_FromString(", ");\r
+ if (s == NULL)\r
+ goto Done;\r
+ result = _PyString_Join(s, pieces);\r
+ Py_DECREF(s);\r
+\r
+Done:\r
+ Py_XDECREF(pieces);\r
+ Py_XDECREF(colon);\r
+ Py_ReprLeave((PyObject *)mp);\r
+ return result;\r
+}\r
+\r
+static Py_ssize_t\r
+dict_length(PyDictObject *mp)\r
+{\r
+ return mp->ma_used;\r
+}\r
+\r
+static PyObject *\r
+dict_subscript(PyDictObject *mp, register PyObject *key)\r
+{\r
+ PyObject *v;\r
+ long hash;\r
+ PyDictEntry *ep;\r
+ assert(mp->ma_table != NULL);\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return NULL;\r
+ }\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ if (ep == NULL)\r
+ return NULL;\r
+ v = ep->me_value;\r
+ if (v == NULL) {\r
+ if (!PyDict_CheckExact(mp)) {\r
+ /* Look up __missing__ method if we're a subclass. */\r
+ PyObject *missing, *res;\r
+ static PyObject *missing_str = NULL;\r
+ missing = _PyObject_LookupSpecial((PyObject *)mp,\r
+ "__missing__",\r
+ &missing_str);\r
+ if (missing != NULL) {\r
+ res = PyObject_CallFunctionObjArgs(missing,\r
+ key, NULL);\r
+ Py_DECREF(missing);\r
+ return res;\r
+ }\r
+ else if (PyErr_Occurred())\r
+ return NULL;\r
+ }\r
+ set_key_error(key);\r
+ return NULL;\r
+ }\r
+ else\r
+ Py_INCREF(v);\r
+ return v;\r
+}\r
+\r
+static int\r
+dict_ass_sub(PyDictObject *mp, PyObject *v, PyObject *w)\r
+{\r
+ if (w == NULL)\r
+ return PyDict_DelItem((PyObject *)mp, v);\r
+ else\r
+ return PyDict_SetItem((PyObject *)mp, v, w);\r
+}\r
+\r
+static PyMappingMethods dict_as_mapping = {\r
+ (lenfunc)dict_length, /*mp_length*/\r
+ (binaryfunc)dict_subscript, /*mp_subscript*/\r
+ (objobjargproc)dict_ass_sub, /*mp_ass_subscript*/\r
+};\r
+\r
+static PyObject *\r
+dict_keys(register PyDictObject *mp)\r
+{\r
+ register PyObject *v;\r
+ register Py_ssize_t i, j;\r
+ PyDictEntry *ep;\r
+ Py_ssize_t mask, n;\r
+\r
+ again:\r
+ n = mp->ma_used;\r
+ v = PyList_New(n);\r
+ if (v == NULL)\r
+ return NULL;\r
+ if (n != mp->ma_used) {\r
+ /* Durnit. The allocations caused the dict to resize.\r
+ * Just start over, this shouldn't normally happen.\r
+ */\r
+ Py_DECREF(v);\r
+ goto again;\r
+ }\r
+ ep = mp->ma_table;\r
+ mask = mp->ma_mask;\r
+ for (i = 0, j = 0; i <= mask; i++) {\r
+ if (ep[i].me_value != NULL) {\r
+ PyObject *key = ep[i].me_key;\r
+ Py_INCREF(key);\r
+ PyList_SET_ITEM(v, j, key);\r
+ j++;\r
+ }\r
+ }\r
+ assert(j == n);\r
+ return v;\r
+}\r
+\r
+static PyObject *\r
+dict_values(register PyDictObject *mp)\r
+{\r
+ register PyObject *v;\r
+ register Py_ssize_t i, j;\r
+ PyDictEntry *ep;\r
+ Py_ssize_t mask, n;\r
+\r
+ again:\r
+ n = mp->ma_used;\r
+ v = PyList_New(n);\r
+ if (v == NULL)\r
+ return NULL;\r
+ if (n != mp->ma_used) {\r
+ /* Durnit. The allocations caused the dict to resize.\r
+ * Just start over, this shouldn't normally happen.\r
+ */\r
+ Py_DECREF(v);\r
+ goto again;\r
+ }\r
+ ep = mp->ma_table;\r
+ mask = mp->ma_mask;\r
+ for (i = 0, j = 0; i <= mask; i++) {\r
+ if (ep[i].me_value != NULL) {\r
+ PyObject *value = ep[i].me_value;\r
+ Py_INCREF(value);\r
+ PyList_SET_ITEM(v, j, value);\r
+ j++;\r
+ }\r
+ }\r
+ assert(j == n);\r
+ return v;\r
+}\r
+\r
+static PyObject *\r
+dict_items(register PyDictObject *mp)\r
+{\r
+ register PyObject *v;\r
+ register Py_ssize_t i, j, n;\r
+ Py_ssize_t mask;\r
+ PyObject *item, *key, *value;\r
+ PyDictEntry *ep;\r
+\r
+ /* Preallocate the list of tuples, to avoid allocations during\r
+ * the loop over the items, which could trigger GC, which\r
+ * could resize the dict. :-(\r
+ */\r
+ again:\r
+ n = mp->ma_used;\r
+ v = PyList_New(n);\r
+ if (v == NULL)\r
+ return NULL;\r
+ for (i = 0; i < n; i++) {\r
+ item = PyTuple_New(2);\r
+ if (item == NULL) {\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ PyList_SET_ITEM(v, i, item);\r
+ }\r
+ if (n != mp->ma_used) {\r
+ /* Durnit. The allocations caused the dict to resize.\r
+ * Just start over, this shouldn't normally happen.\r
+ */\r
+ Py_DECREF(v);\r
+ goto again;\r
+ }\r
+ /* Nothing we do below makes any function calls. */\r
+ ep = mp->ma_table;\r
+ mask = mp->ma_mask;\r
+ for (i = 0, j = 0; i <= mask; i++) {\r
+ if ((value=ep[i].me_value) != NULL) {\r
+ key = ep[i].me_key;\r
+ item = PyList_GET_ITEM(v, j);\r
+ Py_INCREF(key);\r
+ PyTuple_SET_ITEM(item, 0, key);\r
+ Py_INCREF(value);\r
+ PyTuple_SET_ITEM(item, 1, value);\r
+ j++;\r
+ }\r
+ }\r
+ assert(j == n);\r
+ return v;\r
+}\r
+\r
+static PyObject *\r
+dict_fromkeys(PyObject *cls, PyObject *args)\r
+{\r
+ PyObject *seq;\r
+ PyObject *value = Py_None;\r
+ PyObject *it; /* iter(seq) */\r
+ PyObject *key;\r
+ PyObject *d;\r
+ int status;\r
+\r
+ if (!PyArg_UnpackTuple(args, "fromkeys", 1, 2, &seq, &value))\r
+ return NULL;\r
+\r
+ d = PyObject_CallObject(cls, NULL);\r
+ if (d == NULL)\r
+ return NULL;\r
+\r
+ if (PyDict_CheckExact(d) && ((PyDictObject *)d)->ma_used == 0) {\r
+ if (PyDict_CheckExact(seq)) {\r
+ PyDictObject *mp = (PyDictObject *)d;\r
+ PyObject *oldvalue;\r
+ Py_ssize_t pos = 0;\r
+ PyObject *key;\r
+ long hash;\r
+\r
+ if (dictresize(mp, Py_SIZE(seq))) {\r
+ Py_DECREF(d);\r
+ return NULL;\r
+ }\r
+\r
+ while (_PyDict_Next(seq, &pos, &key, &oldvalue, &hash)) {\r
+ Py_INCREF(key);\r
+ Py_INCREF(value);\r
+ if (insertdict(mp, key, hash, value)) {\r
+ Py_DECREF(d);\r
+ return NULL;\r
+ }\r
+ }\r
+ return d;\r
+ }\r
+ if (PyAnySet_CheckExact(seq)) {\r
+ PyDictObject *mp = (PyDictObject *)d;\r
+ Py_ssize_t pos = 0;\r
+ PyObject *key;\r
+ long hash;\r
+\r
+ if (dictresize(mp, PySet_GET_SIZE(seq))) {\r
+ Py_DECREF(d);\r
+ return NULL;\r
+ }\r
+\r
+ while (_PySet_NextEntry(seq, &pos, &key, &hash)) {\r
+ Py_INCREF(key);\r
+ Py_INCREF(value);\r
+ if (insertdict(mp, key, hash, value)) {\r
+ Py_DECREF(d);\r
+ return NULL;\r
+ }\r
+ }\r
+ return d;\r
+ }\r
+ }\r
+\r
+ it = PyObject_GetIter(seq);\r
+ if (it == NULL){\r
+ Py_DECREF(d);\r
+ return NULL;\r
+ }\r
+\r
+ if (PyDict_CheckExact(d)) {\r
+ while ((key = PyIter_Next(it)) != NULL) {\r
+ status = PyDict_SetItem(d, key, value);\r
+ Py_DECREF(key);\r
+ if (status < 0)\r
+ goto Fail;\r
+ }\r
+ } else {\r
+ while ((key = PyIter_Next(it)) != NULL) {\r
+ status = PyObject_SetItem(d, key, value);\r
+ Py_DECREF(key);\r
+ if (status < 0)\r
+ goto Fail;\r
+ }\r
+ }\r
+\r
+ if (PyErr_Occurred())\r
+ goto Fail;\r
+ Py_DECREF(it);\r
+ return d;\r
+\r
+Fail:\r
+ Py_DECREF(it);\r
+ Py_DECREF(d);\r
+ return NULL;\r
+}\r
+\r
+static int\r
+dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, char *methname)\r
+{\r
+ PyObject *arg = NULL;\r
+ int result = 0;\r
+\r
+ if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg))\r
+ result = -1;\r
+\r
+ else if (arg != NULL) {\r
+ if (PyObject_HasAttrString(arg, "keys"))\r
+ result = PyDict_Merge(self, arg, 1);\r
+ else\r
+ result = PyDict_MergeFromSeq2(self, arg, 1);\r
+ }\r
+ if (result == 0 && kwds != NULL)\r
+ result = PyDict_Merge(self, kwds, 1);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+dict_update(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ if (dict_update_common(self, args, kwds, "update") != -1)\r
+ Py_RETURN_NONE;\r
+ return NULL;\r
+}\r
+\r
+/* Update unconditionally replaces existing items.\r
+ Merge has a 3rd argument 'override'; if set, it acts like Update,\r
+ otherwise it leaves existing items unchanged.\r
+\r
+ PyDict_{Update,Merge} update/merge from a mapping object.\r
+\r
+ PyDict_MergeFromSeq2 updates/merges from any iterable object\r
+ producing iterable objects of length 2.\r
+*/\r
+\r
+int\r
+PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override)\r
+{\r
+ PyObject *it; /* iter(seq2) */\r
+ Py_ssize_t i; /* index into seq2 of current element */\r
+ PyObject *item; /* seq2[i] */\r
+ PyObject *fast; /* item as a 2-tuple or 2-list */\r
+\r
+ assert(d != NULL);\r
+ assert(PyDict_Check(d));\r
+ assert(seq2 != NULL);\r
+\r
+ it = PyObject_GetIter(seq2);\r
+ if (it == NULL)\r
+ return -1;\r
+\r
+ for (i = 0; ; ++i) {\r
+ PyObject *key, *value;\r
+ Py_ssize_t n;\r
+\r
+ fast = NULL;\r
+ item = PyIter_Next(it);\r
+ if (item == NULL) {\r
+ if (PyErr_Occurred())\r
+ goto Fail;\r
+ break;\r
+ }\r
+\r
+ /* Convert item to sequence, and verify length 2. */\r
+ fast = PySequence_Fast(item, "");\r
+ if (fast == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_TypeError))\r
+ PyErr_Format(PyExc_TypeError,\r
+ "cannot convert dictionary update "\r
+ "sequence element #%zd to a sequence",\r
+ i);\r
+ goto Fail;\r
+ }\r
+ n = PySequence_Fast_GET_SIZE(fast);\r
+ if (n != 2) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "dictionary update sequence element #%zd "\r
+ "has length %zd; 2 is required",\r
+ i, n);\r
+ goto Fail;\r
+ }\r
+\r
+ /* Update/merge with this (key, value) pair. */\r
+ key = PySequence_Fast_GET_ITEM(fast, 0);\r
+ value = PySequence_Fast_GET_ITEM(fast, 1);\r
+ if (override || PyDict_GetItem(d, key) == NULL) {\r
+ int status = PyDict_SetItem(d, key, value);\r
+ if (status < 0)\r
+ goto Fail;\r
+ }\r
+ Py_DECREF(fast);\r
+ Py_DECREF(item);\r
+ }\r
+\r
+ i = 0;\r
+ goto Return;\r
+Fail:\r
+ Py_XDECREF(item);\r
+ Py_XDECREF(fast);\r
+ i = -1;\r
+Return:\r
+ Py_DECREF(it);\r
+ return Py_SAFE_DOWNCAST(i, Py_ssize_t, int);\r
+}\r
+\r
+int\r
+PyDict_Update(PyObject *a, PyObject *b)\r
+{\r
+ return PyDict_Merge(a, b, 1);\r
+}\r
+\r
+int\r
+PyDict_Merge(PyObject *a, PyObject *b, int override)\r
+{\r
+ register PyDictObject *mp, *other;\r
+ register Py_ssize_t i;\r
+ PyDictEntry *entry;\r
+\r
+ /* We accept for the argument either a concrete dictionary object,\r
+ * or an abstract "mapping" object. For the former, we can do\r
+ * things quite efficiently. For the latter, we only require that\r
+ * PyMapping_Keys() and PyObject_GetItem() be supported.\r
+ */\r
+ if (a == NULL || !PyDict_Check(a) || b == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ mp = (PyDictObject*)a;\r
+ if (PyDict_Check(b)) {\r
+ other = (PyDictObject*)b;\r
+ if (other == mp || other->ma_used == 0)\r
+ /* a.update(a) or a.update({}); nothing to do */\r
+ return 0;\r
+ if (mp->ma_used == 0)\r
+ /* Since the target dict is empty, PyDict_GetItem()\r
+ * always returns NULL. Setting override to 1\r
+ * skips the unnecessary test.\r
+ */\r
+ override = 1;\r
+ /* Do one big resize at the start, rather than\r
+ * incrementally resizing as we insert new items. Expect\r
+ * that there will be no (or few) overlapping keys.\r
+ */\r
+ if ((mp->ma_fill + other->ma_used)*3 >= (mp->ma_mask+1)*2) {\r
+ if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0)\r
+ return -1;\r
+ }\r
+ for (i = 0; i <= other->ma_mask; i++) {\r
+ entry = &other->ma_table[i];\r
+ if (entry->me_value != NULL &&\r
+ (override ||\r
+ PyDict_GetItem(a, entry->me_key) == NULL)) {\r
+ Py_INCREF(entry->me_key);\r
+ Py_INCREF(entry->me_value);\r
+ if (insertdict(mp, entry->me_key,\r
+ (long)entry->me_hash,\r
+ entry->me_value) != 0)\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ /* Do it the generic, slower way */\r
+ PyObject *keys = PyMapping_Keys(b);\r
+ PyObject *iter;\r
+ PyObject *key, *value;\r
+ int status;\r
+\r
+ if (keys == NULL)\r
+ /* Docstring says this is equivalent to E.keys() so\r
+ * if E doesn't have a .keys() method we want\r
+ * AttributeError to percolate up. Might as well\r
+ * do the same for any other error.\r
+ */\r
+ return -1;\r
+\r
+ iter = PyObject_GetIter(keys);\r
+ Py_DECREF(keys);\r
+ if (iter == NULL)\r
+ return -1;\r
+\r
+ for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {\r
+ if (!override && PyDict_GetItem(a, key) != NULL) {\r
+ Py_DECREF(key);\r
+ continue;\r
+ }\r
+ value = PyObject_GetItem(b, key);\r
+ if (value == NULL) {\r
+ Py_DECREF(iter);\r
+ Py_DECREF(key);\r
+ return -1;\r
+ }\r
+ status = PyDict_SetItem(a, key, value);\r
+ Py_DECREF(key);\r
+ Py_DECREF(value);\r
+ if (status < 0) {\r
+ Py_DECREF(iter);\r
+ return -1;\r
+ }\r
+ }\r
+ Py_DECREF(iter);\r
+ if (PyErr_Occurred())\r
+ /* Iterator completed, via error */\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+dict_copy(register PyDictObject *mp)\r
+{\r
+ return PyDict_Copy((PyObject*)mp);\r
+}\r
+\r
+PyObject *\r
+PyDict_Copy(PyObject *o)\r
+{\r
+ PyObject *copy;\r
+\r
+ if (o == NULL || !PyDict_Check(o)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ copy = PyDict_New();\r
+ if (copy == NULL)\r
+ return NULL;\r
+ if (PyDict_Merge(copy, o, 1) == 0)\r
+ return copy;\r
+ Py_DECREF(copy);\r
+ return NULL;\r
+}\r
+\r
+Py_ssize_t\r
+PyDict_Size(PyObject *mp)\r
+{\r
+ if (mp == NULL || !PyDict_Check(mp)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return ((PyDictObject *)mp)->ma_used;\r
+}\r
+\r
+PyObject *\r
+PyDict_Keys(PyObject *mp)\r
+{\r
+ if (mp == NULL || !PyDict_Check(mp)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return dict_keys((PyDictObject *)mp);\r
+}\r
+\r
+PyObject *\r
+PyDict_Values(PyObject *mp)\r
+{\r
+ if (mp == NULL || !PyDict_Check(mp)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return dict_values((PyDictObject *)mp);\r
+}\r
+\r
+PyObject *\r
+PyDict_Items(PyObject *mp)\r
+{\r
+ if (mp == NULL || !PyDict_Check(mp)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return dict_items((PyDictObject *)mp);\r
+}\r
+\r
+/* Subroutine which returns the smallest key in a for which b's value\r
+ is different or absent. The value is returned too, through the\r
+ pval argument. Both are NULL if no key in a is found for which b's status\r
+ differs. The refcounts on (and only on) non-NULL *pval and function return\r
+ values must be decremented by the caller (characterize() increments them\r
+ to ensure that mutating comparison and PyDict_GetItem calls can't delete\r
+ them before the caller is done looking at them). */\r
+\r
+static PyObject *\r
+characterize(PyDictObject *a, PyDictObject *b, PyObject **pval)\r
+{\r
+ PyObject *akey = NULL; /* smallest key in a s.t. a[akey] != b[akey] */\r
+ PyObject *aval = NULL; /* a[akey] */\r
+ Py_ssize_t i;\r
+ int cmp;\r
+\r
+ for (i = 0; i <= a->ma_mask; i++) {\r
+ PyObject *thiskey, *thisaval, *thisbval;\r
+ if (a->ma_table[i].me_value == NULL)\r
+ continue;\r
+ thiskey = a->ma_table[i].me_key;\r
+ Py_INCREF(thiskey); /* keep alive across compares */\r
+ if (akey != NULL) {\r
+ cmp = PyObject_RichCompareBool(akey, thiskey, Py_LT);\r
+ if (cmp < 0) {\r
+ Py_DECREF(thiskey);\r
+ goto Fail;\r
+ }\r
+ if (cmp > 0 ||\r
+ i > a->ma_mask ||\r
+ a->ma_table[i].me_value == NULL)\r
+ {\r
+ /* Not the *smallest* a key; or maybe it is\r
+ * but the compare shrunk the dict so we can't\r
+ * find its associated value anymore; or\r
+ * maybe it is but the compare deleted the\r
+ * a[thiskey] entry.\r
+ */\r
+ Py_DECREF(thiskey);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ /* Compare a[thiskey] to b[thiskey]; cmp <- true iff equal. */\r
+ thisaval = a->ma_table[i].me_value;\r
+ assert(thisaval);\r
+ Py_INCREF(thisaval); /* keep alive */\r
+ thisbval = PyDict_GetItem((PyObject *)b, thiskey);\r
+ if (thisbval == NULL)\r
+ cmp = 0;\r
+ else {\r
+ /* both dicts have thiskey: same values? */\r
+ cmp = PyObject_RichCompareBool(\r
+ thisaval, thisbval, Py_EQ);\r
+ if (cmp < 0) {\r
+ Py_DECREF(thiskey);\r
+ Py_DECREF(thisaval);\r
+ goto Fail;\r
+ }\r
+ }\r
+ if (cmp == 0) {\r
+ /* New winner. */\r
+ Py_XDECREF(akey);\r
+ Py_XDECREF(aval);\r
+ akey = thiskey;\r
+ aval = thisaval;\r
+ }\r
+ else {\r
+ Py_DECREF(thiskey);\r
+ Py_DECREF(thisaval);\r
+ }\r
+ }\r
+ *pval = aval;\r
+ return akey;\r
+\r
+Fail:\r
+ Py_XDECREF(akey);\r
+ Py_XDECREF(aval);\r
+ *pval = NULL;\r
+ return NULL;\r
+}\r
+\r
+static int\r
+dict_compare(PyDictObject *a, PyDictObject *b)\r
+{\r
+ PyObject *adiff, *bdiff, *aval, *bval;\r
+ int res;\r
+\r
+ /* Compare lengths first */\r
+ if (a->ma_used < b->ma_used)\r
+ return -1; /* a is shorter */\r
+ else if (a->ma_used > b->ma_used)\r
+ return 1; /* b is shorter */\r
+\r
+ /* Same length -- check all keys */\r
+ bdiff = bval = NULL;\r
+ adiff = characterize(a, b, &aval);\r
+ if (adiff == NULL) {\r
+ assert(!aval);\r
+ /* Either an error, or a is a subset with the same length so\r
+ * must be equal.\r
+ */\r
+ res = PyErr_Occurred() ? -1 : 0;\r
+ goto Finished;\r
+ }\r
+ bdiff = characterize(b, a, &bval);\r
+ if (bdiff == NULL && PyErr_Occurred()) {\r
+ assert(!bval);\r
+ res = -1;\r
+ goto Finished;\r
+ }\r
+ res = 0;\r
+ if (bdiff) {\r
+ /* bdiff == NULL "should be" impossible now, but perhaps\r
+ * the last comparison done by the characterize() on a had\r
+ * the side effect of making the dicts equal!\r
+ */\r
+ res = PyObject_Compare(adiff, bdiff);\r
+ }\r
+ if (res == 0 && bval != NULL)\r
+ res = PyObject_Compare(aval, bval);\r
+\r
+Finished:\r
+ Py_XDECREF(adiff);\r
+ Py_XDECREF(bdiff);\r
+ Py_XDECREF(aval);\r
+ Py_XDECREF(bval);\r
+ return res;\r
+}\r
+\r
+/* Return 1 if dicts equal, 0 if not, -1 if error.\r
+ * Gets out as soon as any difference is detected.\r
+ * Uses only Py_EQ comparison.\r
+ */\r
+static int\r
+dict_equal(PyDictObject *a, PyDictObject *b)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ if (a->ma_used != b->ma_used)\r
+ /* can't be equal if # of entries differ */\r
+ return 0;\r
+\r
+ /* Same # of entries -- check all of 'em. Exit early on any diff. */\r
+ for (i = 0; i <= a->ma_mask; i++) {\r
+ PyObject *aval = a->ma_table[i].me_value;\r
+ if (aval != NULL) {\r
+ int cmp;\r
+ PyObject *bval;\r
+ PyObject *key = a->ma_table[i].me_key;\r
+ /* temporarily bump aval's refcount to ensure it stays\r
+ alive until we're done with it */\r
+ Py_INCREF(aval);\r
+ /* ditto for key */\r
+ Py_INCREF(key);\r
+ bval = PyDict_GetItem((PyObject *)b, key);\r
+ Py_DECREF(key);\r
+ if (bval == NULL) {\r
+ Py_DECREF(aval);\r
+ return 0;\r
+ }\r
+ cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);\r
+ Py_DECREF(aval);\r
+ if (cmp <= 0) /* error or not equal */\r
+ return cmp;\r
+ }\r
+ }\r
+ return 1;\r
+ }\r
+\r
+static PyObject *\r
+dict_richcompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ int cmp;\r
+ PyObject *res;\r
+\r
+ if (!PyDict_Check(v) || !PyDict_Check(w)) {\r
+ res = Py_NotImplemented;\r
+ }\r
+ else if (op == Py_EQ || op == Py_NE) {\r
+ cmp = dict_equal((PyDictObject *)v, (PyDictObject *)w);\r
+ if (cmp < 0)\r
+ return NULL;\r
+ res = (cmp == (op == Py_EQ)) ? Py_True : Py_False;\r
+ }\r
+ else {\r
+ /* Py3K warning if comparison isn't == or != */\r
+ if (PyErr_WarnPy3k("dict inequality comparisons not supported "\r
+ "in 3.x", 1) < 0) {\r
+ return NULL;\r
+ }\r
+ res = Py_NotImplemented;\r
+ }\r
+ Py_INCREF(res);\r
+ return res;\r
+ }\r
+\r
+static PyObject *\r
+dict_contains(register PyDictObject *mp, PyObject *key)\r
+{\r
+ long hash;\r
+ PyDictEntry *ep;\r
+\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return NULL;\r
+ }\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ if (ep == NULL)\r
+ return NULL;\r
+ return PyBool_FromLong(ep->me_value != NULL);\r
+}\r
+\r
+static PyObject *\r
+dict_has_key(register PyDictObject *mp, PyObject *key)\r
+{\r
+ if (PyErr_WarnPy3k("dict.has_key() not supported in 3.x; "\r
+ "use the in operator", 1) < 0)\r
+ return NULL;\r
+ return dict_contains(mp, key);\r
+}\r
+\r
+static PyObject *\r
+dict_get(register PyDictObject *mp, PyObject *args)\r
+{\r
+ PyObject *key;\r
+ PyObject *failobj = Py_None;\r
+ PyObject *val = NULL;\r
+ long hash;\r
+ PyDictEntry *ep;\r
+\r
+ if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj))\r
+ return NULL;\r
+\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return NULL;\r
+ }\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ if (ep == NULL)\r
+ return NULL;\r
+ val = ep->me_value;\r
+ if (val == NULL)\r
+ val = failobj;\r
+ Py_INCREF(val);\r
+ return val;\r
+}\r
+\r
+\r
+static PyObject *\r
+dict_setdefault(register PyDictObject *mp, PyObject *args)\r
+{\r
+ PyObject *key;\r
+ PyObject *failobj = Py_None;\r
+ PyObject *val = NULL;\r
+ long hash;\r
+ PyDictEntry *ep;\r
+\r
+ if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj))\r
+ return NULL;\r
+\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return NULL;\r
+ }\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ if (ep == NULL)\r
+ return NULL;\r
+ val = ep->me_value;\r
+ if (val == NULL) {\r
+ if (dict_set_item_by_hash_or_entry((PyObject*)mp, key, hash, ep,\r
+ failobj) == 0)\r
+ val = failobj;\r
+ }\r
+ Py_XINCREF(val);\r
+ return val;\r
+}\r
+\r
+\r
+static PyObject *\r
+dict_clear(register PyDictObject *mp)\r
+{\r
+ PyDict_Clear((PyObject *)mp);\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+static PyObject *\r
+dict_pop(PyDictObject *mp, PyObject *args)\r
+{\r
+ long hash;\r
+ PyDictEntry *ep;\r
+ PyObject *old_value, *old_key;\r
+ PyObject *key, *deflt = NULL;\r
+\r
+ if(!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &deflt))\r
+ return NULL;\r
+ if (mp->ma_used == 0) {\r
+ if (deflt) {\r
+ Py_INCREF(deflt);\r
+ return deflt;\r
+ }\r
+ set_key_error(key);\r
+ return NULL;\r
+ }\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return NULL;\r
+ }\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ if (ep == NULL)\r
+ return NULL;\r
+ if (ep->me_value == NULL) {\r
+ if (deflt) {\r
+ Py_INCREF(deflt);\r
+ return deflt;\r
+ }\r
+ set_key_error(key);\r
+ return NULL;\r
+ }\r
+ old_key = ep->me_key;\r
+ Py_INCREF(dummy);\r
+ ep->me_key = dummy;\r
+ old_value = ep->me_value;\r
+ ep->me_value = NULL;\r
+ mp->ma_used--;\r
+ Py_DECREF(old_key);\r
+ return old_value;\r
+}\r
+\r
+static PyObject *\r
+dict_popitem(PyDictObject *mp)\r
+{\r
+ Py_ssize_t i = 0;\r
+ PyDictEntry *ep;\r
+ PyObject *res;\r
+\r
+ /* Allocate the result tuple before checking the size. Believe it\r
+ * or not, this allocation could trigger a garbage collection which\r
+ * could empty the dict, so if we checked the size first and that\r
+ * happened, the result would be an infinite loop (searching for an\r
+ * entry that no longer exists). Note that the usual popitem()\r
+ * idiom is "while d: k, v = d.popitem()". so needing to throw the\r
+ * tuple away if the dict *is* empty isn't a significant\r
+ * inefficiency -- possible, but unlikely in practice.\r
+ */\r
+ res = PyTuple_New(2);\r
+ if (res == NULL)\r
+ return NULL;\r
+ if (mp->ma_used == 0) {\r
+ Py_DECREF(res);\r
+ PyErr_SetString(PyExc_KeyError,\r
+ "popitem(): dictionary is empty");\r
+ return NULL;\r
+ }\r
+ /* Set ep to "the first" dict entry with a value. We abuse the hash\r
+ * field of slot 0 to hold a search finger:\r
+ * If slot 0 has a value, use slot 0.\r
+ * Else slot 0 is being used to hold a search finger,\r
+ * and we use its hash value as the first index to look.\r
+ */\r
+ ep = &mp->ma_table[0];\r
+ if (ep->me_value == NULL) {\r
+ i = ep->me_hash;\r
+ /* The hash field may be a real hash value, or it may be a\r
+ * legit search finger, or it may be a once-legit search\r
+ * finger that's out of bounds now because it wrapped around\r
+ * or the table shrunk -- simply make sure it's in bounds now.\r
+ */\r
+ if (i > mp->ma_mask || i < 1)\r
+ i = 1; /* skip slot 0 */\r
+ while ((ep = &mp->ma_table[i])->me_value == NULL) {\r
+ i++;\r
+ if (i > mp->ma_mask)\r
+ i = 1;\r
+ }\r
+ }\r
+ PyTuple_SET_ITEM(res, 0, ep->me_key);\r
+ PyTuple_SET_ITEM(res, 1, ep->me_value);\r
+ Py_INCREF(dummy);\r
+ ep->me_key = dummy;\r
+ ep->me_value = NULL;\r
+ mp->ma_used--;\r
+ assert(mp->ma_table[0].me_value == NULL);\r
+ mp->ma_table[0].me_hash = i + 1; /* next place to start */\r
+ return res;\r
+}\r
+\r
+static int\r
+dict_traverse(PyObject *op, visitproc visit, void *arg)\r
+{\r
+ Py_ssize_t i = 0;\r
+ PyObject *pk;\r
+ PyObject *pv;\r
+\r
+ while (PyDict_Next(op, &i, &pk, &pv)) {\r
+ Py_VISIT(pk);\r
+ Py_VISIT(pv);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+dict_tp_clear(PyObject *op)\r
+{\r
+ PyDict_Clear(op);\r
+ return 0;\r
+}\r
+\r
+\r
+extern PyTypeObject PyDictIterKey_Type; /* Forward */\r
+extern PyTypeObject PyDictIterValue_Type; /* Forward */\r
+extern PyTypeObject PyDictIterItem_Type; /* Forward */\r
+static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);\r
+\r
+static PyObject *\r
+dict_iterkeys(PyDictObject *dict)\r
+{\r
+ return dictiter_new(dict, &PyDictIterKey_Type);\r
+}\r
+\r
+static PyObject *\r
+dict_itervalues(PyDictObject *dict)\r
+{\r
+ return dictiter_new(dict, &PyDictIterValue_Type);\r
+}\r
+\r
+static PyObject *\r
+dict_iteritems(PyDictObject *dict)\r
+{\r
+ return dictiter_new(dict, &PyDictIterItem_Type);\r
+}\r
+\r
+static PyObject *\r
+dict_sizeof(PyDictObject *mp)\r
+{\r
+ Py_ssize_t res;\r
+\r
+ res = sizeof(PyDictObject);\r
+ if (mp->ma_table != mp->ma_smalltable)\r
+ res = res + (mp->ma_mask + 1) * sizeof(PyDictEntry);\r
+ return PyInt_FromSsize_t(res);\r
+}\r
+\r
+PyDoc_STRVAR(has_key__doc__,\r
+"D.has_key(k) -> True if D has a key k, else False");\r
+\r
+PyDoc_STRVAR(contains__doc__,\r
+"D.__contains__(k) -> True if D has a key k, else False");\r
+\r
+PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");\r
+\r
+PyDoc_STRVAR(sizeof__doc__,\r
+"D.__sizeof__() -> size of D in memory, in bytes");\r
+\r
+PyDoc_STRVAR(get__doc__,\r
+"D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.");\r
+\r
+PyDoc_STRVAR(setdefault_doc__,\r
+"D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D");\r
+\r
+PyDoc_STRVAR(pop__doc__,\r
+"D.pop(k[,d]) -> v, remove specified key and return the corresponding value.\n\\r
+If key is not found, d is returned if given, otherwise KeyError is raised");\r
+\r
+PyDoc_STRVAR(popitem__doc__,\r
+"D.popitem() -> (k, v), remove and return some (key, value) pair as a\n\\r
+2-tuple; but raise KeyError if D is empty.");\r
+\r
+PyDoc_STRVAR(keys__doc__,\r
+"D.keys() -> list of D's keys");\r
+\r
+PyDoc_STRVAR(items__doc__,\r
+"D.items() -> list of D's (key, value) pairs, as 2-tuples");\r
+\r
+PyDoc_STRVAR(values__doc__,\r
+"D.values() -> list of D's values");\r
+\r
+PyDoc_STRVAR(update__doc__,\r
+"D.update([E, ]**F) -> None. Update D from dict/iterable E and F.\n"\r
+"If E present and has a .keys() method, does: for k in E: D[k] = E[k]\n\\r
+If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v\n\\r
+In either case, this is followed by: for k in F: D[k] = F[k]");\r
+\r
+PyDoc_STRVAR(fromkeys__doc__,\r
+"dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.\n\\r
+v defaults to None.");\r
+\r
+PyDoc_STRVAR(clear__doc__,\r
+"D.clear() -> None. Remove all items from D.");\r
+\r
+PyDoc_STRVAR(copy__doc__,\r
+"D.copy() -> a shallow copy of D");\r
+\r
+PyDoc_STRVAR(iterkeys__doc__,\r
+"D.iterkeys() -> an iterator over the keys of D");\r
+\r
+PyDoc_STRVAR(itervalues__doc__,\r
+"D.itervalues() -> an iterator over the values of D");\r
+\r
+PyDoc_STRVAR(iteritems__doc__,\r
+"D.iteritems() -> an iterator over the (key, value) items of D");\r
+\r
+/* Forward */\r
+static PyObject *dictkeys_new(PyObject *);\r
+static PyObject *dictitems_new(PyObject *);\r
+static PyObject *dictvalues_new(PyObject *);\r
+\r
+PyDoc_STRVAR(viewkeys__doc__,\r
+ "D.viewkeys() -> a set-like object providing a view on D's keys");\r
+PyDoc_STRVAR(viewitems__doc__,\r
+ "D.viewitems() -> a set-like object providing a view on D's items");\r
+PyDoc_STRVAR(viewvalues__doc__,\r
+ "D.viewvalues() -> an object providing a view on D's values");\r
+\r
+static PyMethodDef mapp_methods[] = {\r
+ {"__contains__",(PyCFunction)dict_contains, METH_O | METH_COEXIST,\r
+ contains__doc__},\r
+ {"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST,\r
+ getitem__doc__},\r
+ {"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS,\r
+ sizeof__doc__},\r
+ {"has_key", (PyCFunction)dict_has_key, METH_O,\r
+ has_key__doc__},\r
+ {"get", (PyCFunction)dict_get, METH_VARARGS,\r
+ get__doc__},\r
+ {"setdefault", (PyCFunction)dict_setdefault, METH_VARARGS,\r
+ setdefault_doc__},\r
+ {"pop", (PyCFunction)dict_pop, METH_VARARGS,\r
+ pop__doc__},\r
+ {"popitem", (PyCFunction)dict_popitem, METH_NOARGS,\r
+ popitem__doc__},\r
+ {"keys", (PyCFunction)dict_keys, METH_NOARGS,\r
+ keys__doc__},\r
+ {"items", (PyCFunction)dict_items, METH_NOARGS,\r
+ items__doc__},\r
+ {"values", (PyCFunction)dict_values, METH_NOARGS,\r
+ values__doc__},\r
+ {"viewkeys", (PyCFunction)dictkeys_new, METH_NOARGS,\r
+ viewkeys__doc__},\r
+ {"viewitems", (PyCFunction)dictitems_new, METH_NOARGS,\r
+ viewitems__doc__},\r
+ {"viewvalues", (PyCFunction)dictvalues_new, METH_NOARGS,\r
+ viewvalues__doc__},\r
+ {"update", (PyCFunction)dict_update, METH_VARARGS | METH_KEYWORDS,\r
+ update__doc__},\r
+ {"fromkeys", (PyCFunction)dict_fromkeys, METH_VARARGS | METH_CLASS,\r
+ fromkeys__doc__},\r
+ {"clear", (PyCFunction)dict_clear, METH_NOARGS,\r
+ clear__doc__},\r
+ {"copy", (PyCFunction)dict_copy, METH_NOARGS,\r
+ copy__doc__},\r
+ {"iterkeys", (PyCFunction)dict_iterkeys, METH_NOARGS,\r
+ iterkeys__doc__},\r
+ {"itervalues", (PyCFunction)dict_itervalues, METH_NOARGS,\r
+ itervalues__doc__},\r
+ {"iteritems", (PyCFunction)dict_iteritems, METH_NOARGS,\r
+ iteritems__doc__},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+/* Return 1 if `key` is in dict `op`, 0 if not, and -1 on error. */\r
+int\r
+PyDict_Contains(PyObject *op, PyObject *key)\r
+{\r
+ long hash;\r
+ PyDictObject *mp = (PyDictObject *)op;\r
+ PyDictEntry *ep;\r
+\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return -1;\r
+ }\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ return ep == NULL ? -1 : (ep->me_value != NULL);\r
+}\r
+\r
+/* Internal version of PyDict_Contains used when the hash value is already known */\r
+int\r
+_PyDict_Contains(PyObject *op, PyObject *key, long hash)\r
+{\r
+ PyDictObject *mp = (PyDictObject *)op;\r
+ PyDictEntry *ep;\r
+\r
+ ep = (mp->ma_lookup)(mp, key, hash);\r
+ return ep == NULL ? -1 : (ep->me_value != NULL);\r
+}\r
+\r
+/* Hack to implement "key in dict" */\r
+static PySequenceMethods dict_as_sequence = {\r
+ 0, /* sq_length */\r
+ 0, /* sq_concat */\r
+ 0, /* sq_repeat */\r
+ 0, /* sq_item */\r
+ 0, /* sq_slice */\r
+ 0, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ PyDict_Contains, /* sq_contains */\r
+ 0, /* sq_inplace_concat */\r
+ 0, /* sq_inplace_repeat */\r
+};\r
+\r
+static PyObject *\r
+dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *self;\r
+\r
+ assert(type != NULL && type->tp_alloc != NULL);\r
+ self = type->tp_alloc(type, 0);\r
+ if (self != NULL) {\r
+ PyDictObject *d = (PyDictObject *)self;\r
+ /* It's guaranteed that tp->alloc zeroed out the struct. */\r
+ assert(d->ma_table == NULL && d->ma_fill == 0 && d->ma_used == 0);\r
+ INIT_NONZERO_DICT_SLOTS(d);\r
+ d->ma_lookup = lookdict_string;\r
+ /* The object has been implicitly tracked by tp_alloc */\r
+ if (type == &PyDict_Type)\r
+ _PyObject_GC_UNTRACK(d);\r
+#ifdef SHOW_CONVERSION_COUNTS\r
+ ++created;\r
+#endif\r
+#ifdef SHOW_TRACK_COUNT\r
+ if (_PyObject_GC_IS_TRACKED(d))\r
+ count_tracked++;\r
+ else\r
+ count_untracked++;\r
+#endif\r
+ }\r
+ return self;\r
+}\r
+\r
+static int\r
+dict_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ return dict_update_common(self, args, kwds, "dict");\r
+}\r
+\r
+static PyObject *\r
+dict_iter(PyDictObject *dict)\r
+{\r
+ return dictiter_new(dict, &PyDictIterKey_Type);\r
+}\r
+\r
+PyDoc_STRVAR(dictionary_doc,\r
+"dict() -> new empty dictionary\n"\r
+"dict(mapping) -> new dictionary initialized from a mapping object's\n"\r
+" (key, value) pairs\n"\r
+"dict(iterable) -> new dictionary initialized as if via:\n"\r
+" d = {}\n"\r
+" for k, v in iterable:\n"\r
+" d[k] = v\n"\r
+"dict(**kwargs) -> new dictionary initialized with the name=value pairs\n"\r
+" in the keyword argument list. For example: dict(one=1, two=2)");\r
+\r
+PyTypeObject PyDict_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "dict",\r
+ sizeof(PyDictObject),\r
+ 0,\r
+ (destructor)dict_dealloc, /* tp_dealloc */\r
+ (printfunc)dict_print, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)dict_compare, /* tp_compare */\r
+ (reprfunc)dict_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &dict_as_sequence, /* tp_as_sequence */\r
+ &dict_as_mapping, /* tp_as_mapping */\r
+ (hashfunc)PyObject_HashNotImplemented, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DICT_SUBCLASS, /* tp_flags */\r
+ dictionary_doc, /* tp_doc */\r
+ dict_traverse, /* tp_traverse */\r
+ dict_tp_clear, /* tp_clear */\r
+ dict_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ (getiterfunc)dict_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ mapp_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ dict_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ dict_new, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
+\r
+/* For backward compatibility with old dictionary interface */\r
+\r
+PyObject *\r
+PyDict_GetItemString(PyObject *v, const char *key)\r
+{\r
+ PyObject *kv, *rv;\r
+ kv = PyString_FromString(key);\r
+ if (kv == NULL)\r
+ return NULL;\r
+ rv = PyDict_GetItem(v, kv);\r
+ Py_DECREF(kv);\r
+ return rv;\r
+}\r
+\r
+int\r
+PyDict_SetItemString(PyObject *v, const char *key, PyObject *item)\r
+{\r
+ PyObject *kv;\r
+ int err;\r
+ kv = PyString_FromString(key);\r
+ if (kv == NULL)\r
+ return -1;\r
+ PyString_InternInPlace(&kv); /* XXX Should we really? */\r
+ err = PyDict_SetItem(v, kv, item);\r
+ Py_DECREF(kv);\r
+ return err;\r
+}\r
+\r
+int\r
+PyDict_DelItemString(PyObject *v, const char *key)\r
+{\r
+ PyObject *kv;\r
+ int err;\r
+ kv = PyString_FromString(key);\r
+ if (kv == NULL)\r
+ return -1;\r
+ err = PyDict_DelItem(v, kv);\r
+ Py_DECREF(kv);\r
+ return err;\r
+}\r
+\r
+/* Dictionary iterator types */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyDictObject *di_dict; /* Set to NULL when iterator is exhausted */\r
+ Py_ssize_t di_used;\r
+ Py_ssize_t di_pos;\r
+ PyObject* di_result; /* reusable result tuple for iteritems */\r
+ Py_ssize_t len;\r
+} dictiterobject;\r
+\r
+static PyObject *\r
+dictiter_new(PyDictObject *dict, PyTypeObject *itertype)\r
+{\r
+ dictiterobject *di;\r
+ di = PyObject_GC_New(dictiterobject, itertype);\r
+ if (di == NULL)\r
+ return NULL;\r
+ Py_INCREF(dict);\r
+ di->di_dict = dict;\r
+ di->di_used = dict->ma_used;\r
+ di->di_pos = 0;\r
+ di->len = dict->ma_used;\r
+ if (itertype == &PyDictIterItem_Type) {\r
+ di->di_result = PyTuple_Pack(2, Py_None, Py_None);\r
+ if (di->di_result == NULL) {\r
+ Py_DECREF(di);\r
+ return NULL;\r
+ }\r
+ }\r
+ else\r
+ di->di_result = NULL;\r
+ _PyObject_GC_TRACK(di);\r
+ return (PyObject *)di;\r
+}\r
+\r
+static void\r
+dictiter_dealloc(dictiterobject *di)\r
+{\r
+ Py_XDECREF(di->di_dict);\r
+ Py_XDECREF(di->di_result);\r
+ PyObject_GC_Del(di);\r
+}\r
+\r
+static int\r
+dictiter_traverse(dictiterobject *di, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(di->di_dict);\r
+ Py_VISIT(di->di_result);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+dictiter_len(dictiterobject *di)\r
+{\r
+ Py_ssize_t len = 0;\r
+ if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used)\r
+ len = di->len;\r
+ return PyInt_FromSize_t(len);\r
+}\r
+\r
+PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
+\r
+static PyMethodDef dictiter_methods[] = {\r
+ {"__length_hint__", (PyCFunction)dictiter_len, METH_NOARGS, length_hint_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyObject *dictiter_iternextkey(dictiterobject *di)\r
+{\r
+ PyObject *key;\r
+ register Py_ssize_t i, mask;\r
+ register PyDictEntry *ep;\r
+ PyDictObject *d = di->di_dict;\r
+\r
+ if (d == NULL)\r
+ return NULL;\r
+ assert (PyDict_Check(d));\r
+\r
+ if (di->di_used != d->ma_used) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "dictionary changed size during iteration");\r
+ di->di_used = -1; /* Make this state sticky */\r
+ return NULL;\r
+ }\r
+\r
+ i = di->di_pos;\r
+ if (i < 0)\r
+ goto fail;\r
+ ep = d->ma_table;\r
+ mask = d->ma_mask;\r
+ while (i <= mask && ep[i].me_value == NULL)\r
+ i++;\r
+ di->di_pos = i+1;\r
+ if (i > mask)\r
+ goto fail;\r
+ di->len--;\r
+ key = ep[i].me_key;\r
+ Py_INCREF(key);\r
+ return key;\r
+\r
+fail:\r
+ Py_DECREF(d);\r
+ di->di_dict = NULL;\r
+ return NULL;\r
+}\r
+\r
+PyTypeObject PyDictIterKey_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "dictionary-keyiterator", /* tp_name */\r
+ sizeof(dictiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)dictiter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)dictiter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)dictiter_iternextkey, /* tp_iternext */\r
+ dictiter_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *dictiter_iternextvalue(dictiterobject *di)\r
+{\r
+ PyObject *value;\r
+ register Py_ssize_t i, mask;\r
+ register PyDictEntry *ep;\r
+ PyDictObject *d = di->di_dict;\r
+\r
+ if (d == NULL)\r
+ return NULL;\r
+ assert (PyDict_Check(d));\r
+\r
+ if (di->di_used != d->ma_used) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "dictionary changed size during iteration");\r
+ di->di_used = -1; /* Make this state sticky */\r
+ return NULL;\r
+ }\r
+\r
+ i = di->di_pos;\r
+ mask = d->ma_mask;\r
+ if (i < 0 || i > mask)\r
+ goto fail;\r
+ ep = d->ma_table;\r
+ while ((value=ep[i].me_value) == NULL) {\r
+ i++;\r
+ if (i > mask)\r
+ goto fail;\r
+ }\r
+ di->di_pos = i+1;\r
+ di->len--;\r
+ Py_INCREF(value);\r
+ return value;\r
+\r
+fail:\r
+ Py_DECREF(d);\r
+ di->di_dict = NULL;\r
+ return NULL;\r
+}\r
+\r
+PyTypeObject PyDictIterValue_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "dictionary-valueiterator", /* tp_name */\r
+ sizeof(dictiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)dictiter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)dictiter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)dictiter_iternextvalue, /* tp_iternext */\r
+ dictiter_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *dictiter_iternextitem(dictiterobject *di)\r
+{\r
+ PyObject *key, *value, *result = di->di_result;\r
+ register Py_ssize_t i, mask;\r
+ register PyDictEntry *ep;\r
+ PyDictObject *d = di->di_dict;\r
+\r
+ if (d == NULL)\r
+ return NULL;\r
+ assert (PyDict_Check(d));\r
+\r
+ if (di->di_used != d->ma_used) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "dictionary changed size during iteration");\r
+ di->di_used = -1; /* Make this state sticky */\r
+ return NULL;\r
+ }\r
+\r
+ i = di->di_pos;\r
+ if (i < 0)\r
+ goto fail;\r
+ ep = d->ma_table;\r
+ mask = d->ma_mask;\r
+ while (i <= mask && ep[i].me_value == NULL)\r
+ i++;\r
+ di->di_pos = i+1;\r
+ if (i > mask)\r
+ goto fail;\r
+\r
+ if (result->ob_refcnt == 1) {\r
+ Py_INCREF(result);\r
+ Py_DECREF(PyTuple_GET_ITEM(result, 0));\r
+ Py_DECREF(PyTuple_GET_ITEM(result, 1));\r
+ } else {\r
+ result = PyTuple_New(2);\r
+ if (result == NULL)\r
+ return NULL;\r
+ }\r
+ di->len--;\r
+ key = ep[i].me_key;\r
+ value = ep[i].me_value;\r
+ Py_INCREF(key);\r
+ Py_INCREF(value);\r
+ PyTuple_SET_ITEM(result, 0, key);\r
+ PyTuple_SET_ITEM(result, 1, value);\r
+ return result;\r
+\r
+fail:\r
+ Py_DECREF(d);\r
+ di->di_dict = NULL;\r
+ return NULL;\r
+}\r
+\r
+PyTypeObject PyDictIterItem_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "dictionary-itemiterator", /* tp_name */\r
+ sizeof(dictiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)dictiter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)dictiter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)dictiter_iternextitem, /* tp_iternext */\r
+ dictiter_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+/***********************************************/\r
+/* View objects for keys(), items(), values(). */\r
+/***********************************************/\r
+\r
+/* The instance lay-out is the same for all three; but the type differs. */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyDictObject *dv_dict;\r
+} dictviewobject;\r
+\r
+\r
+static void\r
+dictview_dealloc(dictviewobject *dv)\r
+{\r
+ Py_XDECREF(dv->dv_dict);\r
+ PyObject_GC_Del(dv);\r
+}\r
+\r
+static int\r
+dictview_traverse(dictviewobject *dv, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(dv->dv_dict);\r
+ return 0;\r
+}\r
+\r
+static Py_ssize_t\r
+dictview_len(dictviewobject *dv)\r
+{\r
+ Py_ssize_t len = 0;\r
+ if (dv->dv_dict != NULL)\r
+ len = dv->dv_dict->ma_used;\r
+ return len;\r
+}\r
+\r
+static PyObject *\r
+dictview_new(PyObject *dict, PyTypeObject *type)\r
+{\r
+ dictviewobject *dv;\r
+ if (dict == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ if (!PyDict_Check(dict)) {\r
+ /* XXX Get rid of this restriction later */\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s() requires a dict argument, not '%s'",\r
+ type->tp_name, dict->ob_type->tp_name);\r
+ return NULL;\r
+ }\r
+ dv = PyObject_GC_New(dictviewobject, type);\r
+ if (dv == NULL)\r
+ return NULL;\r
+ Py_INCREF(dict);\r
+ dv->dv_dict = (PyDictObject *)dict;\r
+ _PyObject_GC_TRACK(dv);\r
+ return (PyObject *)dv;\r
+}\r
+\r
+/* TODO(guido): The views objects are not complete:\r
+\r
+ * support more set operations\r
+ * support arbitrary mappings?\r
+ - either these should be static or exported in dictobject.h\r
+ - if public then they should probably be in builtins\r
+*/\r
+\r
+/* Return 1 if self is a subset of other, iterating over self;\r
+ 0 if not; -1 if an error occurred. */\r
+static int\r
+all_contained_in(PyObject *self, PyObject *other)\r
+{\r
+ PyObject *iter = PyObject_GetIter(self);\r
+ int ok = 1;\r
+\r
+ if (iter == NULL)\r
+ return -1;\r
+ for (;;) {\r
+ PyObject *next = PyIter_Next(iter);\r
+ if (next == NULL) {\r
+ if (PyErr_Occurred())\r
+ ok = -1;\r
+ break;\r
+ }\r
+ ok = PySequence_Contains(other, next);\r
+ Py_DECREF(next);\r
+ if (ok <= 0)\r
+ break;\r
+ }\r
+ Py_DECREF(iter);\r
+ return ok;\r
+}\r
+\r
+static PyObject *\r
+dictview_richcompare(PyObject *self, PyObject *other, int op)\r
+{\r
+ Py_ssize_t len_self, len_other;\r
+ int ok;\r
+ PyObject *result;\r
+\r
+ assert(self != NULL);\r
+ assert(PyDictViewSet_Check(self));\r
+ assert(other != NULL);\r
+\r
+ if (!PyAnySet_Check(other) && !PyDictViewSet_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+\r
+ len_self = PyObject_Size(self);\r
+ if (len_self < 0)\r
+ return NULL;\r
+ len_other = PyObject_Size(other);\r
+ if (len_other < 0)\r
+ return NULL;\r
+\r
+ ok = 0;\r
+ switch(op) {\r
+\r
+ case Py_NE:\r
+ case Py_EQ:\r
+ if (len_self == len_other)\r
+ ok = all_contained_in(self, other);\r
+ if (op == Py_NE && ok >= 0)\r
+ ok = !ok;\r
+ break;\r
+\r
+ case Py_LT:\r
+ if (len_self < len_other)\r
+ ok = all_contained_in(self, other);\r
+ break;\r
+\r
+ case Py_LE:\r
+ if (len_self <= len_other)\r
+ ok = all_contained_in(self, other);\r
+ break;\r
+\r
+ case Py_GT:\r
+ if (len_self > len_other)\r
+ ok = all_contained_in(other, self);\r
+ break;\r
+\r
+ case Py_GE:\r
+ if (len_self >= len_other)\r
+ ok = all_contained_in(other, self);\r
+ break;\r
+\r
+ }\r
+ if (ok < 0)\r
+ return NULL;\r
+ result = ok ? Py_True : Py_False;\r
+ Py_INCREF(result);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+dictview_repr(dictviewobject *dv)\r
+{\r
+ PyObject *seq;\r
+ PyObject *seq_str;\r
+ PyObject *result;\r
+\r
+ seq = PySequence_List((PyObject *)dv);\r
+ if (seq == NULL)\r
+ return NULL;\r
+\r
+ seq_str = PyObject_Repr(seq);\r
+ if (seq_str == NULL) {\r
+ Py_DECREF(seq);\r
+ return NULL;\r
+ }\r
+ result = PyString_FromFormat("%s(%s)", Py_TYPE(dv)->tp_name,\r
+ PyString_AS_STRING(seq_str));\r
+ Py_DECREF(seq_str);\r
+ Py_DECREF(seq);\r
+ return result;\r
+}\r
+\r
+/*** dict_keys ***/\r
+\r
+static PyObject *\r
+dictkeys_iter(dictviewobject *dv)\r
+{\r
+ if (dv->dv_dict == NULL) {\r
+ Py_RETURN_NONE;\r
+ }\r
+ return dictiter_new(dv->dv_dict, &PyDictIterKey_Type);\r
+}\r
+\r
+static int\r
+dictkeys_contains(dictviewobject *dv, PyObject *obj)\r
+{\r
+ if (dv->dv_dict == NULL)\r
+ return 0;\r
+ return PyDict_Contains((PyObject *)dv->dv_dict, obj);\r
+}\r
+\r
+static PySequenceMethods dictkeys_as_sequence = {\r
+ (lenfunc)dictview_len, /* sq_length */\r
+ 0, /* sq_concat */\r
+ 0, /* sq_repeat */\r
+ 0, /* sq_item */\r
+ 0, /* sq_slice */\r
+ 0, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ (objobjproc)dictkeys_contains, /* sq_contains */\r
+};\r
+\r
+static PyObject*\r
+dictviews_sub(PyObject* self, PyObject *other)\r
+{\r
+ PyObject *result = PySet_New(self);\r
+ PyObject *tmp;\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ tmp = PyObject_CallMethod(result, "difference_update", "O", other);\r
+ if (tmp == NULL) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+\r
+ Py_DECREF(tmp);\r
+ return result;\r
+}\r
+\r
+static PyObject*\r
+dictviews_and(PyObject* self, PyObject *other)\r
+{\r
+ PyObject *result = PySet_New(self);\r
+ PyObject *tmp;\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ tmp = PyObject_CallMethod(result, "intersection_update", "O", other);\r
+ if (tmp == NULL) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+\r
+ Py_DECREF(tmp);\r
+ return result;\r
+}\r
+\r
+static PyObject*\r
+dictviews_or(PyObject* self, PyObject *other)\r
+{\r
+ PyObject *result = PySet_New(self);\r
+ PyObject *tmp;\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ tmp = PyObject_CallMethod(result, "update", "O", other);\r
+ if (tmp == NULL) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+\r
+ Py_DECREF(tmp);\r
+ return result;\r
+}\r
+\r
+static PyObject*\r
+dictviews_xor(PyObject* self, PyObject *other)\r
+{\r
+ PyObject *result = PySet_New(self);\r
+ PyObject *tmp;\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ tmp = PyObject_CallMethod(result, "symmetric_difference_update", "O",\r
+ other);\r
+ if (tmp == NULL) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+\r
+ Py_DECREF(tmp);\r
+ return result;\r
+}\r
+\r
+static PyNumberMethods dictviews_as_number = {\r
+ 0, /*nb_add*/\r
+ (binaryfunc)dictviews_sub, /*nb_subtract*/\r
+ 0, /*nb_multiply*/\r
+ 0, /*nb_divide*/\r
+ 0, /*nb_remainder*/\r
+ 0, /*nb_divmod*/\r
+ 0, /*nb_power*/\r
+ 0, /*nb_negative*/\r
+ 0, /*nb_positive*/\r
+ 0, /*nb_absolute*/\r
+ 0, /*nb_nonzero*/\r
+ 0, /*nb_invert*/\r
+ 0, /*nb_lshift*/\r
+ 0, /*nb_rshift*/\r
+ (binaryfunc)dictviews_and, /*nb_and*/\r
+ (binaryfunc)dictviews_xor, /*nb_xor*/\r
+ (binaryfunc)dictviews_or, /*nb_or*/\r
+};\r
+\r
+static PyMethodDef dictkeys_methods[] = {\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyDictKeys_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "dict_keys", /* tp_name */\r
+ sizeof(dictviewobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)dictview_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_reserved */\r
+ (reprfunc)dictview_repr, /* tp_repr */\r
+ &dictviews_as_number, /* tp_as_number */\r
+ &dictkeys_as_sequence, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_CHECKTYPES, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)dictview_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ dictview_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ (getiterfunc)dictkeys_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ dictkeys_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *\r
+dictkeys_new(PyObject *dict)\r
+{\r
+ return dictview_new(dict, &PyDictKeys_Type);\r
+}\r
+\r
+/*** dict_items ***/\r
+\r
+static PyObject *\r
+dictitems_iter(dictviewobject *dv)\r
+{\r
+ if (dv->dv_dict == NULL) {\r
+ Py_RETURN_NONE;\r
+ }\r
+ return dictiter_new(dv->dv_dict, &PyDictIterItem_Type);\r
+}\r
+\r
+static int\r
+dictitems_contains(dictviewobject *dv, PyObject *obj)\r
+{\r
+ PyObject *key, *value, *found;\r
+ if (dv->dv_dict == NULL)\r
+ return 0;\r
+ if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 2)\r
+ return 0;\r
+ key = PyTuple_GET_ITEM(obj, 0);\r
+ value = PyTuple_GET_ITEM(obj, 1);\r
+ found = PyDict_GetItem((PyObject *)dv->dv_dict, key);\r
+ if (found == NULL) {\r
+ if (PyErr_Occurred())\r
+ return -1;\r
+ return 0;\r
+ }\r
+ return PyObject_RichCompareBool(value, found, Py_EQ);\r
+}\r
+\r
+static PySequenceMethods dictitems_as_sequence = {\r
+ (lenfunc)dictview_len, /* sq_length */\r
+ 0, /* sq_concat */\r
+ 0, /* sq_repeat */\r
+ 0, /* sq_item */\r
+ 0, /* sq_slice */\r
+ 0, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ (objobjproc)dictitems_contains, /* sq_contains */\r
+};\r
+\r
+static PyMethodDef dictitems_methods[] = {\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyDictItems_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "dict_items", /* tp_name */\r
+ sizeof(dictviewobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)dictview_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_reserved */\r
+ (reprfunc)dictview_repr, /* tp_repr */\r
+ &dictviews_as_number, /* tp_as_number */\r
+ &dictitems_as_sequence, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_CHECKTYPES, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)dictview_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ dictview_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ (getiterfunc)dictitems_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ dictitems_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *\r
+dictitems_new(PyObject *dict)\r
+{\r
+ return dictview_new(dict, &PyDictItems_Type);\r
+}\r
+\r
+/*** dict_values ***/\r
+\r
+static PyObject *\r
+dictvalues_iter(dictviewobject *dv)\r
+{\r
+ if (dv->dv_dict == NULL) {\r
+ Py_RETURN_NONE;\r
+ }\r
+ return dictiter_new(dv->dv_dict, &PyDictIterValue_Type);\r
+}\r
+\r
+static PySequenceMethods dictvalues_as_sequence = {\r
+ (lenfunc)dictview_len, /* sq_length */\r
+ 0, /* sq_concat */\r
+ 0, /* sq_repeat */\r
+ 0, /* sq_item */\r
+ 0, /* sq_slice */\r
+ 0, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ (objobjproc)0, /* sq_contains */\r
+};\r
+\r
+static PyMethodDef dictvalues_methods[] = {\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyDictValues_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "dict_values", /* tp_name */\r
+ sizeof(dictviewobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)dictview_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_reserved */\r
+ (reprfunc)dictview_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &dictvalues_as_sequence, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)dictview_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ (getiterfunc)dictvalues_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ dictvalues_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *\r
+dictvalues_new(PyObject *dict)\r
+{\r
+ return dictview_new(dict, &PyDictValues_Type);\r
+}\r
--- /dev/null
+/* enumerate object */\r
+\r
+#include "Python.h"\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ Py_ssize_t en_index; /* current index of enumeration */\r
+ PyObject* en_sit; /* secondary iterator of enumeration */\r
+ PyObject* en_result; /* result tuple */\r
+ PyObject* en_longindex; /* index for sequences >= PY_SSIZE_T_MAX */\r
+} enumobject;\r
+\r
+static PyObject *\r
+enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ enumobject *en;\r
+ PyObject *seq = NULL;\r
+ PyObject *start = NULL;\r
+ static char *kwlist[] = {"sequence", "start", 0};\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:enumerate", kwlist,\r
+ &seq, &start))\r
+ return NULL;\r
+\r
+ en = (enumobject *)type->tp_alloc(type, 0);\r
+ if (en == NULL)\r
+ return NULL;\r
+ if (start != NULL) {\r
+ start = PyNumber_Index(start);\r
+ if (start == NULL) {\r
+ Py_DECREF(en);\r
+ return NULL;\r
+ }\r
+ assert(PyInt_Check(start) || PyLong_Check(start));\r
+ en->en_index = PyInt_AsSsize_t(start);\r
+ if (en->en_index == -1 && PyErr_Occurred()) {\r
+ PyErr_Clear();\r
+ en->en_index = PY_SSIZE_T_MAX;\r
+ en->en_longindex = start;\r
+ } else {\r
+ en->en_longindex = NULL;\r
+ Py_DECREF(start);\r
+ }\r
+ } else {\r
+ en->en_index = 0;\r
+ en->en_longindex = NULL;\r
+ }\r
+ en->en_sit = PyObject_GetIter(seq);\r
+ if (en->en_sit == NULL) {\r
+ Py_DECREF(en);\r
+ return NULL;\r
+ }\r
+ en->en_result = PyTuple_Pack(2, Py_None, Py_None);\r
+ if (en->en_result == NULL) {\r
+ Py_DECREF(en);\r
+ return NULL;\r
+ }\r
+ return (PyObject *)en;\r
+}\r
+\r
+static void\r
+enum_dealloc(enumobject *en)\r
+{\r
+ PyObject_GC_UnTrack(en);\r
+ Py_XDECREF(en->en_sit);\r
+ Py_XDECREF(en->en_result);\r
+ Py_XDECREF(en->en_longindex);\r
+ Py_TYPE(en)->tp_free(en);\r
+}\r
+\r
+static int\r
+enum_traverse(enumobject *en, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(en->en_sit);\r
+ Py_VISIT(en->en_result);\r
+ Py_VISIT(en->en_longindex);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+enum_next_long(enumobject *en, PyObject* next_item)\r
+{\r
+ static PyObject *one = NULL;\r
+ PyObject *result = en->en_result;\r
+ PyObject *next_index;\r
+ PyObject *stepped_up;\r
+\r
+ if (en->en_longindex == NULL) {\r
+ en->en_longindex = PyInt_FromSsize_t(PY_SSIZE_T_MAX);\r
+ if (en->en_longindex == NULL)\r
+ return NULL;\r
+ }\r
+ if (one == NULL) {\r
+ one = PyInt_FromLong(1);\r
+ if (one == NULL)\r
+ return NULL;\r
+ }\r
+ next_index = en->en_longindex;\r
+ assert(next_index != NULL);\r
+ stepped_up = PyNumber_Add(next_index, one);\r
+ if (stepped_up == NULL)\r
+ return NULL;\r
+ en->en_longindex = stepped_up;\r
+\r
+ if (result->ob_refcnt == 1) {\r
+ Py_INCREF(result);\r
+ Py_DECREF(PyTuple_GET_ITEM(result, 0));\r
+ Py_DECREF(PyTuple_GET_ITEM(result, 1));\r
+ } else {\r
+ result = PyTuple_New(2);\r
+ if (result == NULL) {\r
+ Py_DECREF(next_index);\r
+ Py_DECREF(next_item);\r
+ return NULL;\r
+ }\r
+ }\r
+ PyTuple_SET_ITEM(result, 0, next_index);\r
+ PyTuple_SET_ITEM(result, 1, next_item);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+enum_next(enumobject *en)\r
+{\r
+ PyObject *next_index;\r
+ PyObject *next_item;\r
+ PyObject *result = en->en_result;\r
+ PyObject *it = en->en_sit;\r
+\r
+ next_item = (*Py_TYPE(it)->tp_iternext)(it);\r
+ if (next_item == NULL)\r
+ return NULL;\r
+\r
+ if (en->en_index == PY_SSIZE_T_MAX)\r
+ return enum_next_long(en, next_item);\r
+\r
+ next_index = PyInt_FromSsize_t(en->en_index);\r
+ if (next_index == NULL) {\r
+ Py_DECREF(next_item);\r
+ return NULL;\r
+ }\r
+ en->en_index++;\r
+\r
+ if (result->ob_refcnt == 1) {\r
+ Py_INCREF(result);\r
+ Py_DECREF(PyTuple_GET_ITEM(result, 0));\r
+ Py_DECREF(PyTuple_GET_ITEM(result, 1));\r
+ } else {\r
+ result = PyTuple_New(2);\r
+ if (result == NULL) {\r
+ Py_DECREF(next_index);\r
+ Py_DECREF(next_item);\r
+ return NULL;\r
+ }\r
+ }\r
+ PyTuple_SET_ITEM(result, 0, next_index);\r
+ PyTuple_SET_ITEM(result, 1, next_item);\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(enum_doc,\r
+"enumerate(iterable[, start]) -> iterator for index, value of iterable\n"\r
+"\n"\r
+"Return an enumerate object. iterable must be another object that supports\n"\r
+"iteration. The enumerate object yields pairs containing a count (from\n"\r
+"start, which defaults to zero) and a value yielded by the iterable argument.\n"\r
+"enumerate is useful for obtaining an indexed list:\n"\r
+" (0, seq[0]), (1, seq[1]), (2, seq[2]), ...");\r
+\r
+PyTypeObject PyEnum_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "enumerate", /* tp_name */\r
+ sizeof(enumobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)enum_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ enum_doc, /* tp_doc */\r
+ (traverseproc)enum_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)enum_next, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ enum_new, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
+\r
+/* Reversed Object ***************************************************************/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ Py_ssize_t index;\r
+ PyObject* seq;\r
+} reversedobject;\r
+\r
+static PyObject *\r
+reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ Py_ssize_t n;\r
+ PyObject *seq, *reversed_meth;\r
+ static PyObject *reversed_cache = NULL;\r
+ reversedobject *ro;\r
+\r
+ if (type == &PyReversed_Type && !_PyArg_NoKeywords("reversed()", kwds))\r
+ return NULL;\r
+\r
+ if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq) )\r
+ return NULL;\r
+\r
+ if (PyInstance_Check(seq)) {\r
+ reversed_meth = PyObject_GetAttrString(seq, "__reversed__");\r
+ if (reversed_meth == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ PyErr_Clear();\r
+ else\r
+ return NULL;\r
+ }\r
+ }\r
+ else {\r
+ reversed_meth = _PyObject_LookupSpecial(seq, "__reversed__",\r
+ &reversed_cache);\r
+ if (reversed_meth == NULL && PyErr_Occurred())\r
+ return NULL;\r
+ }\r
+ if (reversed_meth != NULL) {\r
+ PyObject *res = PyObject_CallFunctionObjArgs(reversed_meth, NULL);\r
+ Py_DECREF(reversed_meth);\r
+ return res;\r
+ }\r
+\r
+ if (!PySequence_Check(seq)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "argument to reversed() must be a sequence");\r
+ return NULL;\r
+ }\r
+\r
+ n = PySequence_Size(seq);\r
+ if (n == -1)\r
+ return NULL;\r
+\r
+ ro = (reversedobject *)type->tp_alloc(type, 0);\r
+ if (ro == NULL)\r
+ return NULL;\r
+\r
+ ro->index = n-1;\r
+ Py_INCREF(seq);\r
+ ro->seq = seq;\r
+ return (PyObject *)ro;\r
+}\r
+\r
+static void\r
+reversed_dealloc(reversedobject *ro)\r
+{\r
+ PyObject_GC_UnTrack(ro);\r
+ Py_XDECREF(ro->seq);\r
+ Py_TYPE(ro)->tp_free(ro);\r
+}\r
+\r
+static int\r
+reversed_traverse(reversedobject *ro, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(ro->seq);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+reversed_next(reversedobject *ro)\r
+{\r
+ PyObject *item;\r
+ Py_ssize_t index = ro->index;\r
+\r
+ if (index >= 0) {\r
+ item = PySequence_GetItem(ro->seq, index);\r
+ if (item != NULL) {\r
+ ro->index--;\r
+ return item;\r
+ }\r
+ if (PyErr_ExceptionMatches(PyExc_IndexError) ||\r
+ PyErr_ExceptionMatches(PyExc_StopIteration))\r
+ PyErr_Clear();\r
+ }\r
+ ro->index = -1;\r
+ Py_CLEAR(ro->seq);\r
+ return NULL;\r
+}\r
+\r
+PyDoc_STRVAR(reversed_doc,\r
+"reversed(sequence) -> reverse iterator over values of the sequence\n"\r
+"\n"\r
+"Return a reverse iterator");\r
+\r
+static PyObject *\r
+reversed_len(reversedobject *ro)\r
+{\r
+ Py_ssize_t position, seqsize;\r
+\r
+ if (ro->seq == NULL)\r
+ return PyInt_FromLong(0);\r
+ seqsize = PySequence_Size(ro->seq);\r
+ if (seqsize == -1)\r
+ return NULL;\r
+ position = ro->index + 1;\r
+ return PyInt_FromSsize_t((seqsize < position) ? 0 : position);\r
+}\r
+\r
+PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
+\r
+static PyMethodDef reversediter_methods[] = {\r
+ {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyReversed_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "reversed", /* tp_name */\r
+ sizeof(reversedobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)reversed_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ reversed_doc, /* tp_doc */\r
+ (traverseproc)reversed_traverse,/* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)reversed_next, /* tp_iternext */\r
+ reversediter_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ reversed_new, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
--- /dev/null
+/*\r
+ * New exceptions.c written in Iceland by Richard Jones and Georg Brandl.\r
+ *\r
+ * Thanks go to Tim Peters and Michael Hudson for debugging.\r
+ */\r
+\r
+#define PY_SSIZE_T_CLEAN\r
+#include <Python.h>\r
+#include "structmember.h"\r
+#include "osdefs.h"\r
+\r
+#define EXC_MODULE_NAME "exceptions."\r
+\r
+/* NOTE: If the exception class hierarchy changes, don't forget to update\r
+ * Lib/test/exception_hierarchy.txt\r
+ */\r
+\r
+PyDoc_STRVAR(exceptions_doc, "Python's standard exception class hierarchy.\n\\r
+\n\\r
+Exceptions found here are defined both in the exceptions module and the\n\\r
+built-in namespace. It is recommended that user-defined exceptions\n\\r
+inherit from Exception. See the documentation for the exception\n\\r
+inheritance hierarchy.\n\\r
+");\r
+\r
+/*\r
+ * BaseException\r
+ */\r
+static PyObject *\r
+BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyBaseExceptionObject *self;\r
+\r
+ self = (PyBaseExceptionObject *)type->tp_alloc(type, 0);\r
+ if (!self)\r
+ return NULL;\r
+ /* the dict is created on the fly in PyObject_GenericSetAttr */\r
+ self->message = self->dict = NULL;\r
+\r
+ self->args = PyTuple_New(0);\r
+ if (!self->args) {\r
+ Py_DECREF(self);\r
+ return NULL;\r
+ }\r
+\r
+ self->message = PyString_FromString("");\r
+ if (!self->message) {\r
+ Py_DECREF(self);\r
+ return NULL;\r
+ }\r
+\r
+ return (PyObject *)self;\r
+}\r
+\r
+static int\r
+BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))\r
+ return -1;\r
+\r
+ Py_DECREF(self->args);\r
+ self->args = args;\r
+ Py_INCREF(self->args);\r
+\r
+ if (PyTuple_GET_SIZE(self->args) == 1) {\r
+ Py_CLEAR(self->message);\r
+ self->message = PyTuple_GET_ITEM(self->args, 0);\r
+ Py_INCREF(self->message);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+BaseException_clear(PyBaseExceptionObject *self)\r
+{\r
+ Py_CLEAR(self->dict);\r
+ Py_CLEAR(self->args);\r
+ Py_CLEAR(self->message);\r
+ return 0;\r
+}\r
+\r
+static void\r
+BaseException_dealloc(PyBaseExceptionObject *self)\r
+{\r
+ _PyObject_GC_UNTRACK(self);\r
+ BaseException_clear(self);\r
+ Py_TYPE(self)->tp_free((PyObject *)self);\r
+}\r
+\r
+static int\r
+BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(self->dict);\r
+ Py_VISIT(self->args);\r
+ Py_VISIT(self->message);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+BaseException_str(PyBaseExceptionObject *self)\r
+{\r
+ PyObject *out;\r
+\r
+ switch (PyTuple_GET_SIZE(self->args)) {\r
+ case 0:\r
+ out = PyString_FromString("");\r
+ break;\r
+ case 1:\r
+ out = PyObject_Str(PyTuple_GET_ITEM(self->args, 0));\r
+ break;\r
+ default:\r
+ out = PyObject_Str(self->args);\r
+ break;\r
+ }\r
+\r
+ return out;\r
+}\r
+\r
+#ifdef Py_USING_UNICODE\r
+static PyObject *\r
+BaseException_unicode(PyBaseExceptionObject *self)\r
+{\r
+ PyObject *out;\r
+\r
+ /* issue6108: if __str__ has been overridden in the subclass, unicode()\r
+ should return the message returned by __str__ as used to happen\r
+ before this method was implemented. */\r
+ if (Py_TYPE(self)->tp_str != (reprfunc)BaseException_str) {\r
+ PyObject *str;\r
+ /* Unlike PyObject_Str, tp_str can return unicode (i.e. return the\r
+ equivalent of unicode(e.__str__()) instead of unicode(str(e))). */\r
+ str = Py_TYPE(self)->tp_str((PyObject*)self);\r
+ if (str == NULL)\r
+ return NULL;\r
+ out = PyObject_Unicode(str);\r
+ Py_DECREF(str);\r
+ return out;\r
+ }\r
+\r
+ switch (PyTuple_GET_SIZE(self->args)) {\r
+ case 0:\r
+ out = PyUnicode_FromString("");\r
+ break;\r
+ case 1:\r
+ out = PyObject_Unicode(PyTuple_GET_ITEM(self->args, 0));\r
+ break;\r
+ default:\r
+ out = PyObject_Unicode(self->args);\r
+ break;\r
+ }\r
+\r
+ return out;\r
+}\r
+#endif\r
+\r
+static PyObject *\r
+BaseException_repr(PyBaseExceptionObject *self)\r
+{\r
+ PyObject *repr_suffix;\r
+ PyObject *repr;\r
+ char *name;\r
+ char *dot;\r
+\r
+ repr_suffix = PyObject_Repr(self->args);\r
+ if (!repr_suffix)\r
+ return NULL;\r
+\r
+ name = (char *)Py_TYPE(self)->tp_name;\r
+ dot = strrchr(name, '.');\r
+ if (dot != NULL) name = dot+1;\r
+\r
+ repr = PyString_FromString(name);\r
+ if (!repr) {\r
+ Py_DECREF(repr_suffix);\r
+ return NULL;\r
+ }\r
+\r
+ PyString_ConcatAndDel(&repr, repr_suffix);\r
+ return repr;\r
+}\r
+\r
+/* Pickling support */\r
+static PyObject *\r
+BaseException_reduce(PyBaseExceptionObject *self)\r
+{\r
+ if (self->args && self->dict)\r
+ return PyTuple_Pack(3, Py_TYPE(self), self->args, self->dict);\r
+ else\r
+ return PyTuple_Pack(2, Py_TYPE(self), self->args);\r
+}\r
+\r
+/*\r
+ * Needed for backward compatibility, since exceptions used to store\r
+ * all their attributes in the __dict__. Code is taken from cPickle's\r
+ * load_build function.\r
+ */\r
+static PyObject *\r
+BaseException_setstate(PyObject *self, PyObject *state)\r
+{\r
+ PyObject *d_key, *d_value;\r
+ Py_ssize_t i = 0;\r
+\r
+ if (state != Py_None) {\r
+ if (!PyDict_Check(state)) {\r
+ PyErr_SetString(PyExc_TypeError, "state is not a dictionary");\r
+ return NULL;\r
+ }\r
+ while (PyDict_Next(state, &i, &d_key, &d_value)) {\r
+ if (PyObject_SetAttr(self, d_key, d_value) < 0)\r
+ return NULL;\r
+ }\r
+ }\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+\r
+static PyMethodDef BaseException_methods[] = {\r
+ {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS },\r
+ {"__setstate__", (PyCFunction)BaseException_setstate, METH_O },\r
+#ifdef Py_USING_UNICODE\r
+ {"__unicode__", (PyCFunction)BaseException_unicode, METH_NOARGS },\r
+#endif\r
+ {NULL, NULL, 0, NULL},\r
+};\r
+\r
+\r
+\r
+static PyObject *\r
+BaseException_getitem(PyBaseExceptionObject *self, Py_ssize_t index)\r
+{\r
+ if (PyErr_WarnPy3k("__getitem__ not supported for exception "\r
+ "classes in 3.x; use args attribute", 1) < 0)\r
+ return NULL;\r
+ return PySequence_GetItem(self->args, index);\r
+}\r
+\r
+static PyObject *\r
+BaseException_getslice(PyBaseExceptionObject *self,\r
+ Py_ssize_t start, Py_ssize_t stop)\r
+{\r
+ if (PyErr_WarnPy3k("__getslice__ not supported for exception "\r
+ "classes in 3.x; use args attribute", 1) < 0)\r
+ return NULL;\r
+ return PySequence_GetSlice(self->args, start, stop);\r
+}\r
+\r
+static PySequenceMethods BaseException_as_sequence = {\r
+ 0, /* sq_length; */\r
+ 0, /* sq_concat; */\r
+ 0, /* sq_repeat; */\r
+ (ssizeargfunc)BaseException_getitem, /* sq_item; */\r
+ (ssizessizeargfunc)BaseException_getslice, /* sq_slice; */\r
+ 0, /* sq_ass_item; */\r
+ 0, /* sq_ass_slice; */\r
+ 0, /* sq_contains; */\r
+ 0, /* sq_inplace_concat; */\r
+ 0 /* sq_inplace_repeat; */\r
+};\r
+\r
+static PyObject *\r
+BaseException_get_dict(PyBaseExceptionObject *self)\r
+{\r
+ if (self->dict == NULL) {\r
+ self->dict = PyDict_New();\r
+ if (!self->dict)\r
+ return NULL;\r
+ }\r
+ Py_INCREF(self->dict);\r
+ return self->dict;\r
+}\r
+\r
+static int\r
+BaseException_set_dict(PyBaseExceptionObject *self, PyObject *val)\r
+{\r
+ if (val == NULL) {\r
+ PyErr_SetString(PyExc_TypeError, "__dict__ may not be deleted");\r
+ return -1;\r
+ }\r
+ if (!PyDict_Check(val)) {\r
+ PyErr_SetString(PyExc_TypeError, "__dict__ must be a dictionary");\r
+ return -1;\r
+ }\r
+ Py_CLEAR(self->dict);\r
+ Py_INCREF(val);\r
+ self->dict = val;\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+BaseException_get_args(PyBaseExceptionObject *self)\r
+{\r
+ if (self->args == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ Py_INCREF(self->args);\r
+ return self->args;\r
+}\r
+\r
+static int\r
+BaseException_set_args(PyBaseExceptionObject *self, PyObject *val)\r
+{\r
+ PyObject *seq;\r
+ if (val == NULL) {\r
+ PyErr_SetString(PyExc_TypeError, "args may not be deleted");\r
+ return -1;\r
+ }\r
+ seq = PySequence_Tuple(val);\r
+ if (!seq)\r
+ return -1;\r
+ Py_CLEAR(self->args);\r
+ self->args = seq;\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+BaseException_get_message(PyBaseExceptionObject *self)\r
+{\r
+ PyObject *msg;\r
+\r
+ /* if "message" is in self->dict, accessing a user-set message attribute */\r
+ if (self->dict &&\r
+ (msg = PyDict_GetItemString(self->dict, "message"))) {\r
+ Py_INCREF(msg);\r
+ return msg;\r
+ }\r
+\r
+ if (self->message == NULL) {\r
+ PyErr_SetString(PyExc_AttributeError, "message attribute was deleted");\r
+ return NULL;\r
+ }\r
+\r
+ /* accessing the deprecated "builtin" message attribute of Exception */\r
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,\r
+ "BaseException.message has been deprecated as "\r
+ "of Python 2.6", 1) < 0)\r
+ return NULL;\r
+\r
+ Py_INCREF(self->message);\r
+ return self->message;\r
+}\r
+\r
+static int\r
+BaseException_set_message(PyBaseExceptionObject *self, PyObject *val)\r
+{\r
+ /* if val is NULL, delete the message attribute */\r
+ if (val == NULL) {\r
+ if (self->dict && PyDict_GetItemString(self->dict, "message")) {\r
+ if (PyDict_DelItemString(self->dict, "message") < 0)\r
+ return -1;\r
+ }\r
+ Py_CLEAR(self->message);\r
+ return 0;\r
+ }\r
+\r
+ /* else set it in __dict__, but may need to create the dict first */\r
+ if (self->dict == NULL) {\r
+ self->dict = PyDict_New();\r
+ if (!self->dict)\r
+ return -1;\r
+ }\r
+ return PyDict_SetItemString(self->dict, "message", val);\r
+}\r
+\r
+static PyGetSetDef BaseException_getset[] = {\r
+ {"__dict__", (getter)BaseException_get_dict, (setter)BaseException_set_dict},\r
+ {"args", (getter)BaseException_get_args, (setter)BaseException_set_args},\r
+ {"message", (getter)BaseException_get_message,\r
+ (setter)BaseException_set_message},\r
+ {NULL},\r
+};\r
+\r
+\r
+static PyTypeObject _PyExc_BaseException = {\r
+ PyObject_HEAD_INIT(NULL)\r
+ 0, /*ob_size*/\r
+ EXC_MODULE_NAME "BaseException", /*tp_name*/\r
+ sizeof(PyBaseExceptionObject), /*tp_basicsize*/\r
+ 0, /*tp_itemsize*/\r
+ (destructor)BaseException_dealloc, /*tp_dealloc*/\r
+ 0, /*tp_print*/\r
+ 0, /*tp_getattr*/\r
+ 0, /*tp_setattr*/\r
+ 0, /* tp_compare; */\r
+ (reprfunc)BaseException_repr, /*tp_repr*/\r
+ 0, /*tp_as_number*/\r
+ &BaseException_as_sequence, /*tp_as_sequence*/\r
+ 0, /*tp_as_mapping*/\r
+ 0, /*tp_hash */\r
+ 0, /*tp_call*/\r
+ (reprfunc)BaseException_str, /*tp_str*/\r
+ PyObject_GenericGetAttr, /*tp_getattro*/\r
+ PyObject_GenericSetAttr, /*tp_setattro*/\r
+ 0, /*tp_as_buffer*/\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASE_EXC_SUBCLASS, /*tp_flags*/\r
+ PyDoc_STR("Common base class for all exceptions"), /* tp_doc */\r
+ (traverseproc)BaseException_traverse, /* tp_traverse */\r
+ (inquiry)BaseException_clear, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ BaseException_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ BaseException_getset, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ offsetof(PyBaseExceptionObject, dict), /* tp_dictoffset */\r
+ (initproc)BaseException_init, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ BaseException_new, /* tp_new */\r
+};\r
+/* the CPython API expects exceptions to be (PyObject *) - both a hold-over\r
+from the previous implmentation and also allowing Python objects to be used\r
+in the API */\r
+PyObject *PyExc_BaseException = (PyObject *)&_PyExc_BaseException;\r
+\r
+/* note these macros omit the last semicolon so the macro invocation may\r
+ * include it and not look strange.\r
+ */\r
+#define SimpleExtendsException(EXCBASE, EXCNAME, EXCDOC) \\r
+static PyTypeObject _PyExc_ ## EXCNAME = { \\r
+ PyObject_HEAD_INIT(NULL) \\r
+ 0, \\r
+ EXC_MODULE_NAME # EXCNAME, \\r
+ sizeof(PyBaseExceptionObject), \\r
+ 0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, \\r
+ 0, 0, 0, 0, 0, 0, 0, \\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \\r
+ PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \\r
+ (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \\r
+ 0, 0, 0, offsetof(PyBaseExceptionObject, dict), \\r
+ (initproc)BaseException_init, 0, BaseException_new,\\r
+}; \\r
+PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME\r
+\r
+#define MiddlingExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDOC) \\r
+static PyTypeObject _PyExc_ ## EXCNAME = { \\r
+ PyObject_HEAD_INIT(NULL) \\r
+ 0, \\r
+ EXC_MODULE_NAME # EXCNAME, \\r
+ sizeof(Py ## EXCSTORE ## Object), \\r
+ 0, (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \\r
+ 0, 0, 0, 0, 0, \\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \\r
+ PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \\r
+ (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \\r
+ 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \\r
+ (initproc)EXCSTORE ## _init, 0, BaseException_new,\\r
+}; \\r
+PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME\r
+\r
+#define ComplexExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDEALLOC, EXCMETHODS, EXCMEMBERS, EXCSTR, EXCDOC) \\r
+static PyTypeObject _PyExc_ ## EXCNAME = { \\r
+ PyObject_HEAD_INIT(NULL) \\r
+ 0, \\r
+ EXC_MODULE_NAME # EXCNAME, \\r
+ sizeof(Py ## EXCSTORE ## Object), 0, \\r
+ (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \\r
+ (reprfunc)EXCSTR, 0, 0, 0, \\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \\r
+ PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \\r
+ (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \\r
+ EXCMEMBERS, 0, &_ ## EXCBASE, \\r
+ 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \\r
+ (initproc)EXCSTORE ## _init, 0, BaseException_new,\\r
+}; \\r
+PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME\r
+\r
+\r
+/*\r
+ * Exception extends BaseException\r
+ */\r
+SimpleExtendsException(PyExc_BaseException, Exception,\r
+ "Common base class for all non-exit exceptions.");\r
+\r
+\r
+/*\r
+ * StandardError extends Exception\r
+ */\r
+SimpleExtendsException(PyExc_Exception, StandardError,\r
+ "Base class for all standard Python exceptions that do not represent\n"\r
+ "interpreter exiting.");\r
+\r
+\r
+/*\r
+ * TypeError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, TypeError,\r
+ "Inappropriate argument type.");\r
+\r
+\r
+/*\r
+ * StopIteration extends Exception\r
+ */\r
+SimpleExtendsException(PyExc_Exception, StopIteration,\r
+ "Signal the end from iterator.next().");\r
+\r
+\r
+/*\r
+ * GeneratorExit extends BaseException\r
+ */\r
+SimpleExtendsException(PyExc_BaseException, GeneratorExit,\r
+ "Request that a generator exit.");\r
+\r
+\r
+/*\r
+ * SystemExit extends BaseException\r
+ */\r
+\r
+static int\r
+SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ Py_ssize_t size = PyTuple_GET_SIZE(args);\r
+\r
+ if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)\r
+ return -1;\r
+\r
+ if (size == 0)\r
+ return 0;\r
+ Py_CLEAR(self->code);\r
+ if (size == 1)\r
+ self->code = PyTuple_GET_ITEM(args, 0);\r
+ else if (size > 1)\r
+ self->code = args;\r
+ Py_INCREF(self->code);\r
+ return 0;\r
+}\r
+\r
+static int\r
+SystemExit_clear(PySystemExitObject *self)\r
+{\r
+ Py_CLEAR(self->code);\r
+ return BaseException_clear((PyBaseExceptionObject *)self);\r
+}\r
+\r
+static void\r
+SystemExit_dealloc(PySystemExitObject *self)\r
+{\r
+ _PyObject_GC_UNTRACK(self);\r
+ SystemExit_clear(self);\r
+ Py_TYPE(self)->tp_free((PyObject *)self);\r
+}\r
+\r
+static int\r
+SystemExit_traverse(PySystemExitObject *self, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(self->code);\r
+ return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);\r
+}\r
+\r
+static PyMemberDef SystemExit_members[] = {\r
+ {"code", T_OBJECT, offsetof(PySystemExitObject, code), 0,\r
+ PyDoc_STR("exception code")},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+ComplexExtendsException(PyExc_BaseException, SystemExit, SystemExit,\r
+ SystemExit_dealloc, 0, SystemExit_members, 0,\r
+ "Request to exit from the interpreter.");\r
+\r
+/*\r
+ * KeyboardInterrupt extends BaseException\r
+ */\r
+SimpleExtendsException(PyExc_BaseException, KeyboardInterrupt,\r
+ "Program interrupted by user.");\r
+\r
+\r
+/*\r
+ * ImportError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, ImportError,\r
+ "Import can't find module, or can't find name in module.");\r
+\r
+\r
+/*\r
+ * EnvironmentError extends StandardError\r
+ */\r
+\r
+/* Where a function has a single filename, such as open() or some\r
+ * of the os module functions, PyErr_SetFromErrnoWithFilename() is\r
+ * called, giving a third argument which is the filename. But, so\r
+ * that old code using in-place unpacking doesn't break, e.g.:\r
+ *\r
+ * except IOError, (errno, strerror):\r
+ *\r
+ * we hack args so that it only contains two items. This also\r
+ * means we need our own __str__() which prints out the filename\r
+ * when it was supplied.\r
+ */\r
+static int\r
+EnvironmentError_init(PyEnvironmentErrorObject *self, PyObject *args,\r
+ PyObject *kwds)\r
+{\r
+ PyObject *myerrno = NULL, *strerror = NULL, *filename = NULL;\r
+ PyObject *subslice = NULL;\r
+\r
+ if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)\r
+ return -1;\r
+\r
+ if (PyTuple_GET_SIZE(args) <= 1 || PyTuple_GET_SIZE(args) > 3) {\r
+ return 0;\r
+ }\r
+\r
+ if (!PyArg_UnpackTuple(args, "EnvironmentError", 2, 3,\r
+ &myerrno, &strerror, &filename)) {\r
+ return -1;\r
+ }\r
+ Py_CLEAR(self->myerrno); /* replacing */\r
+ self->myerrno = myerrno;\r
+ Py_INCREF(self->myerrno);\r
+\r
+ Py_CLEAR(self->strerror); /* replacing */\r
+ self->strerror = strerror;\r
+ Py_INCREF(self->strerror);\r
+\r
+ /* self->filename will remain Py_None otherwise */\r
+ if (filename != NULL) {\r
+ Py_CLEAR(self->filename); /* replacing */\r
+ self->filename = filename;\r
+ Py_INCREF(self->filename);\r
+\r
+ subslice = PyTuple_GetSlice(args, 0, 2);\r
+ if (!subslice)\r
+ return -1;\r
+\r
+ Py_DECREF(self->args); /* replacing args */\r
+ self->args = subslice;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+EnvironmentError_clear(PyEnvironmentErrorObject *self)\r
+{\r
+ Py_CLEAR(self->myerrno);\r
+ Py_CLEAR(self->strerror);\r
+ Py_CLEAR(self->filename);\r
+ return BaseException_clear((PyBaseExceptionObject *)self);\r
+}\r
+\r
+static void\r
+EnvironmentError_dealloc(PyEnvironmentErrorObject *self)\r
+{\r
+ _PyObject_GC_UNTRACK(self);\r
+ EnvironmentError_clear(self);\r
+ Py_TYPE(self)->tp_free((PyObject *)self);\r
+}\r
+\r
+static int\r
+EnvironmentError_traverse(PyEnvironmentErrorObject *self, visitproc visit,\r
+ void *arg)\r
+{\r
+ Py_VISIT(self->myerrno);\r
+ Py_VISIT(self->strerror);\r
+ Py_VISIT(self->filename);\r
+ return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);\r
+}\r
+\r
+static PyObject *\r
+EnvironmentError_str(PyEnvironmentErrorObject *self)\r
+{\r
+ PyObject *rtnval = NULL;\r
+\r
+ if (self->filename) {\r
+ PyObject *fmt;\r
+ PyObject *repr;\r
+ PyObject *tuple;\r
+\r
+ fmt = PyString_FromString("[Errno %s] %s: %s");\r
+ if (!fmt)\r
+ return NULL;\r
+\r
+ repr = PyObject_Repr(self->filename);\r
+ if (!repr) {\r
+ Py_DECREF(fmt);\r
+ return NULL;\r
+ }\r
+ tuple = PyTuple_New(3);\r
+ if (!tuple) {\r
+ Py_DECREF(repr);\r
+ Py_DECREF(fmt);\r
+ return NULL;\r
+ }\r
+\r
+ if (self->myerrno) {\r
+ Py_INCREF(self->myerrno);\r
+ PyTuple_SET_ITEM(tuple, 0, self->myerrno);\r
+ }\r
+ else {\r
+ Py_INCREF(Py_None);\r
+ PyTuple_SET_ITEM(tuple, 0, Py_None);\r
+ }\r
+ if (self->strerror) {\r
+ Py_INCREF(self->strerror);\r
+ PyTuple_SET_ITEM(tuple, 1, self->strerror);\r
+ }\r
+ else {\r
+ Py_INCREF(Py_None);\r
+ PyTuple_SET_ITEM(tuple, 1, Py_None);\r
+ }\r
+\r
+ PyTuple_SET_ITEM(tuple, 2, repr);\r
+\r
+ rtnval = PyString_Format(fmt, tuple);\r
+\r
+ Py_DECREF(fmt);\r
+ Py_DECREF(tuple);\r
+ }\r
+ else if (self->myerrno && self->strerror) {\r
+ PyObject *fmt;\r
+ PyObject *tuple;\r
+\r
+ fmt = PyString_FromString("[Errno %s] %s");\r
+ if (!fmt)\r
+ return NULL;\r
+\r
+ tuple = PyTuple_New(2);\r
+ if (!tuple) {\r
+ Py_DECREF(fmt);\r
+ return NULL;\r
+ }\r
+\r
+ if (self->myerrno) {\r
+ Py_INCREF(self->myerrno);\r
+ PyTuple_SET_ITEM(tuple, 0, self->myerrno);\r
+ }\r
+ else {\r
+ Py_INCREF(Py_None);\r
+ PyTuple_SET_ITEM(tuple, 0, Py_None);\r
+ }\r
+ if (self->strerror) {\r
+ Py_INCREF(self->strerror);\r
+ PyTuple_SET_ITEM(tuple, 1, self->strerror);\r
+ }\r
+ else {\r
+ Py_INCREF(Py_None);\r
+ PyTuple_SET_ITEM(tuple, 1, Py_None);\r
+ }\r
+\r
+ rtnval = PyString_Format(fmt, tuple);\r
+\r
+ Py_DECREF(fmt);\r
+ Py_DECREF(tuple);\r
+ }\r
+ else\r
+ rtnval = BaseException_str((PyBaseExceptionObject *)self);\r
+\r
+ return rtnval;\r
+}\r
+\r
+static PyMemberDef EnvironmentError_members[] = {\r
+ {"errno", T_OBJECT, offsetof(PyEnvironmentErrorObject, myerrno), 0,\r
+ PyDoc_STR("exception errno")},\r
+ {"strerror", T_OBJECT, offsetof(PyEnvironmentErrorObject, strerror), 0,\r
+ PyDoc_STR("exception strerror")},\r
+ {"filename", T_OBJECT, offsetof(PyEnvironmentErrorObject, filename), 0,\r
+ PyDoc_STR("exception filename")},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+\r
+static PyObject *\r
+EnvironmentError_reduce(PyEnvironmentErrorObject *self)\r
+{\r
+ PyObject *args = self->args;\r
+ PyObject *res = NULL, *tmp;\r
+\r
+ /* self->args is only the first two real arguments if there was a\r
+ * file name given to EnvironmentError. */\r
+ if (PyTuple_GET_SIZE(args) == 2 && self->filename) {\r
+ args = PyTuple_New(3);\r
+ if (!args)\r
+ return NULL;\r
+\r
+ tmp = PyTuple_GET_ITEM(self->args, 0);\r
+ Py_INCREF(tmp);\r
+ PyTuple_SET_ITEM(args, 0, tmp);\r
+\r
+ tmp = PyTuple_GET_ITEM(self->args, 1);\r
+ Py_INCREF(tmp);\r
+ PyTuple_SET_ITEM(args, 1, tmp);\r
+\r
+ Py_INCREF(self->filename);\r
+ PyTuple_SET_ITEM(args, 2, self->filename);\r
+ } else\r
+ Py_INCREF(args);\r
+\r
+ if (self->dict)\r
+ res = PyTuple_Pack(3, Py_TYPE(self), args, self->dict);\r
+ else\r
+ res = PyTuple_Pack(2, Py_TYPE(self), args);\r
+ Py_DECREF(args);\r
+ return res;\r
+}\r
+\r
+\r
+static PyMethodDef EnvironmentError_methods[] = {\r
+ {"__reduce__", (PyCFunction)EnvironmentError_reduce, METH_NOARGS},\r
+ {NULL}\r
+};\r
+\r
+ComplexExtendsException(PyExc_StandardError, EnvironmentError,\r
+ EnvironmentError, EnvironmentError_dealloc,\r
+ EnvironmentError_methods, EnvironmentError_members,\r
+ EnvironmentError_str,\r
+ "Base class for I/O related errors.");\r
+\r
+\r
+/*\r
+ * IOError extends EnvironmentError\r
+ */\r
+MiddlingExtendsException(PyExc_EnvironmentError, IOError,\r
+ EnvironmentError, "I/O operation failed.");\r
+\r
+\r
+/*\r
+ * OSError extends EnvironmentError\r
+ */\r
+MiddlingExtendsException(PyExc_EnvironmentError, OSError,\r
+ EnvironmentError, "OS system call failed.");\r
+\r
+\r
+/*\r
+ * WindowsError extends OSError\r
+ */\r
+#ifdef MS_WINDOWS\r
+#include "errmap.h"\r
+\r
+static int\r
+WindowsError_clear(PyWindowsErrorObject *self)\r
+{\r
+ Py_CLEAR(self->myerrno);\r
+ Py_CLEAR(self->strerror);\r
+ Py_CLEAR(self->filename);\r
+ Py_CLEAR(self->winerror);\r
+ return BaseException_clear((PyBaseExceptionObject *)self);\r
+}\r
+\r
+static void\r
+WindowsError_dealloc(PyWindowsErrorObject *self)\r
+{\r
+ _PyObject_GC_UNTRACK(self);\r
+ WindowsError_clear(self);\r
+ Py_TYPE(self)->tp_free((PyObject *)self);\r
+}\r
+\r
+static int\r
+WindowsError_traverse(PyWindowsErrorObject *self, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(self->myerrno);\r
+ Py_VISIT(self->strerror);\r
+ Py_VISIT(self->filename);\r
+ Py_VISIT(self->winerror);\r
+ return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);\r
+}\r
+\r
+static int\r
+WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *o_errcode = NULL;\r
+ long errcode;\r
+ long posix_errno;\r
+\r
+ if (EnvironmentError_init((PyEnvironmentErrorObject *)self, args, kwds)\r
+ == -1)\r
+ return -1;\r
+\r
+ if (self->myerrno == NULL)\r
+ return 0;\r
+\r
+ /* Set errno to the POSIX errno, and winerror to the Win32\r
+ error code. */\r
+ errcode = PyInt_AsLong(self->myerrno);\r
+ if (errcode == -1 && PyErr_Occurred())\r
+ return -1;\r
+ posix_errno = winerror_to_errno(errcode);\r
+\r
+ Py_CLEAR(self->winerror);\r
+ self->winerror = self->myerrno;\r
+\r
+ o_errcode = PyInt_FromLong(posix_errno);\r
+ if (!o_errcode)\r
+ return -1;\r
+\r
+ self->myerrno = o_errcode;\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+static PyObject *\r
+WindowsError_str(PyWindowsErrorObject *self)\r
+{\r
+ PyObject *rtnval = NULL;\r
+\r
+ if (self->filename) {\r
+ PyObject *fmt;\r
+ PyObject *repr;\r
+ PyObject *tuple;\r
+\r
+ fmt = PyString_FromString("[Error %s] %s: %s");\r
+ if (!fmt)\r
+ return NULL;\r
+\r
+ repr = PyObject_Repr(self->filename);\r
+ if (!repr) {\r
+ Py_DECREF(fmt);\r
+ return NULL;\r
+ }\r
+ tuple = PyTuple_New(3);\r
+ if (!tuple) {\r
+ Py_DECREF(repr);\r
+ Py_DECREF(fmt);\r
+ return NULL;\r
+ }\r
+\r
+ if (self->winerror) {\r
+ Py_INCREF(self->winerror);\r
+ PyTuple_SET_ITEM(tuple, 0, self->winerror);\r
+ }\r
+ else {\r
+ Py_INCREF(Py_None);\r
+ PyTuple_SET_ITEM(tuple, 0, Py_None);\r
+ }\r
+ if (self->strerror) {\r
+ Py_INCREF(self->strerror);\r
+ PyTuple_SET_ITEM(tuple, 1, self->strerror);\r
+ }\r
+ else {\r
+ Py_INCREF(Py_None);\r
+ PyTuple_SET_ITEM(tuple, 1, Py_None);\r
+ }\r
+\r
+ PyTuple_SET_ITEM(tuple, 2, repr);\r
+\r
+ rtnval = PyString_Format(fmt, tuple);\r
+\r
+ Py_DECREF(fmt);\r
+ Py_DECREF(tuple);\r
+ }\r
+ else if (self->winerror && self->strerror) {\r
+ PyObject *fmt;\r
+ PyObject *tuple;\r
+\r
+ fmt = PyString_FromString("[Error %s] %s");\r
+ if (!fmt)\r
+ return NULL;\r
+\r
+ tuple = PyTuple_New(2);\r
+ if (!tuple) {\r
+ Py_DECREF(fmt);\r
+ return NULL;\r
+ }\r
+\r
+ if (self->winerror) {\r
+ Py_INCREF(self->winerror);\r
+ PyTuple_SET_ITEM(tuple, 0, self->winerror);\r
+ }\r
+ else {\r
+ Py_INCREF(Py_None);\r
+ PyTuple_SET_ITEM(tuple, 0, Py_None);\r
+ }\r
+ if (self->strerror) {\r
+ Py_INCREF(self->strerror);\r
+ PyTuple_SET_ITEM(tuple, 1, self->strerror);\r
+ }\r
+ else {\r
+ Py_INCREF(Py_None);\r
+ PyTuple_SET_ITEM(tuple, 1, Py_None);\r
+ }\r
+\r
+ rtnval = PyString_Format(fmt, tuple);\r
+\r
+ Py_DECREF(fmt);\r
+ Py_DECREF(tuple);\r
+ }\r
+ else\r
+ rtnval = EnvironmentError_str((PyEnvironmentErrorObject *)self);\r
+\r
+ return rtnval;\r
+}\r
+\r
+static PyMemberDef WindowsError_members[] = {\r
+ {"errno", T_OBJECT, offsetof(PyWindowsErrorObject, myerrno), 0,\r
+ PyDoc_STR("POSIX exception code")},\r
+ {"strerror", T_OBJECT, offsetof(PyWindowsErrorObject, strerror), 0,\r
+ PyDoc_STR("exception strerror")},\r
+ {"filename", T_OBJECT, offsetof(PyWindowsErrorObject, filename), 0,\r
+ PyDoc_STR("exception filename")},\r
+ {"winerror", T_OBJECT, offsetof(PyWindowsErrorObject, winerror), 0,\r
+ PyDoc_STR("Win32 exception code")},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+ComplexExtendsException(PyExc_OSError, WindowsError, WindowsError,\r
+ WindowsError_dealloc, 0, WindowsError_members,\r
+ WindowsError_str, "MS-Windows OS system call failed.");\r
+\r
+#endif /* MS_WINDOWS */\r
+\r
+\r
+/*\r
+ * VMSError extends OSError (I think)\r
+ */\r
+#ifdef __VMS\r
+MiddlingExtendsException(PyExc_OSError, VMSError, EnvironmentError,\r
+ "OpenVMS OS system call failed.");\r
+#endif\r
+\r
+\r
+/*\r
+ * EOFError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, EOFError,\r
+ "Read beyond end of file.");\r
+\r
+\r
+/*\r
+ * RuntimeError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, RuntimeError,\r
+ "Unspecified run-time error.");\r
+\r
+\r
+/*\r
+ * NotImplementedError extends RuntimeError\r
+ */\r
+SimpleExtendsException(PyExc_RuntimeError, NotImplementedError,\r
+ "Method or function hasn't been implemented yet.");\r
+\r
+/*\r
+ * NameError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, NameError,\r
+ "Name not found globally.");\r
+\r
+/*\r
+ * UnboundLocalError extends NameError\r
+ */\r
+SimpleExtendsException(PyExc_NameError, UnboundLocalError,\r
+ "Local name referenced but not bound to a value.");\r
+\r
+/*\r
+ * AttributeError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, AttributeError,\r
+ "Attribute not found.");\r
+\r
+\r
+/*\r
+ * SyntaxError extends StandardError\r
+ */\r
+\r
+static int\r
+SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *info = NULL;\r
+ Py_ssize_t lenargs = PyTuple_GET_SIZE(args);\r
+\r
+ if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)\r
+ return -1;\r
+\r
+ if (lenargs >= 1) {\r
+ Py_CLEAR(self->msg);\r
+ self->msg = PyTuple_GET_ITEM(args, 0);\r
+ Py_INCREF(self->msg);\r
+ }\r
+ if (lenargs == 2) {\r
+ info = PyTuple_GET_ITEM(args, 1);\r
+ info = PySequence_Tuple(info);\r
+ if (!info)\r
+ return -1;\r
+\r
+ if (PyTuple_GET_SIZE(info) != 4) {\r
+ /* not a very good error message, but it's what Python 2.4 gives */\r
+ PyErr_SetString(PyExc_IndexError, "tuple index out of range");\r
+ Py_DECREF(info);\r
+ return -1;\r
+ }\r
+\r
+ Py_CLEAR(self->filename);\r
+ self->filename = PyTuple_GET_ITEM(info, 0);\r
+ Py_INCREF(self->filename);\r
+\r
+ Py_CLEAR(self->lineno);\r
+ self->lineno = PyTuple_GET_ITEM(info, 1);\r
+ Py_INCREF(self->lineno);\r
+\r
+ Py_CLEAR(self->offset);\r
+ self->offset = PyTuple_GET_ITEM(info, 2);\r
+ Py_INCREF(self->offset);\r
+\r
+ Py_CLEAR(self->text);\r
+ self->text = PyTuple_GET_ITEM(info, 3);\r
+ Py_INCREF(self->text);\r
+\r
+ Py_DECREF(info);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+SyntaxError_clear(PySyntaxErrorObject *self)\r
+{\r
+ Py_CLEAR(self->msg);\r
+ Py_CLEAR(self->filename);\r
+ Py_CLEAR(self->lineno);\r
+ Py_CLEAR(self->offset);\r
+ Py_CLEAR(self->text);\r
+ Py_CLEAR(self->print_file_and_line);\r
+ return BaseException_clear((PyBaseExceptionObject *)self);\r
+}\r
+\r
+static void\r
+SyntaxError_dealloc(PySyntaxErrorObject *self)\r
+{\r
+ _PyObject_GC_UNTRACK(self);\r
+ SyntaxError_clear(self);\r
+ Py_TYPE(self)->tp_free((PyObject *)self);\r
+}\r
+\r
+static int\r
+SyntaxError_traverse(PySyntaxErrorObject *self, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(self->msg);\r
+ Py_VISIT(self->filename);\r
+ Py_VISIT(self->lineno);\r
+ Py_VISIT(self->offset);\r
+ Py_VISIT(self->text);\r
+ Py_VISIT(self->print_file_and_line);\r
+ return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);\r
+}\r
+\r
+/* This is called "my_basename" instead of just "basename" to avoid name\r
+ conflicts with glibc; basename is already prototyped if _GNU_SOURCE is\r
+ defined, and Python does define that. */\r
+static char *\r
+my_basename(char *name)\r
+{\r
+ char *cp = name;\r
+ char *result = name;\r
+\r
+ if (name == NULL)\r
+ return "???";\r
+ while (*cp != '\0') {\r
+ if (*cp == SEP)\r
+ result = cp + 1;\r
+ ++cp;\r
+ }\r
+ return result;\r
+}\r
+\r
+\r
+static PyObject *\r
+SyntaxError_str(PySyntaxErrorObject *self)\r
+{\r
+ PyObject *str;\r
+ PyObject *result;\r
+ int have_filename = 0;\r
+ int have_lineno = 0;\r
+ char *buffer = NULL;\r
+ Py_ssize_t bufsize;\r
+\r
+ if (self->msg)\r
+ str = PyObject_Str(self->msg);\r
+ else\r
+ str = PyObject_Str(Py_None);\r
+ if (!str)\r
+ return NULL;\r
+ /* Don't fiddle with non-string return (shouldn't happen anyway) */\r
+ if (!PyString_Check(str))\r
+ return str;\r
+\r
+ /* XXX -- do all the additional formatting with filename and\r
+ lineno here */\r
+\r
+ have_filename = (self->filename != NULL) &&\r
+ PyString_Check(self->filename);\r
+ have_lineno = (self->lineno != NULL) && PyInt_Check(self->lineno);\r
+\r
+ if (!have_filename && !have_lineno)\r
+ return str;\r
+\r
+ bufsize = PyString_GET_SIZE(str) + 64;\r
+ if (have_filename)\r
+ bufsize += PyString_GET_SIZE(self->filename);\r
+\r
+ buffer = PyMem_MALLOC(bufsize);\r
+ if (buffer == NULL)\r
+ return str;\r
+\r
+ if (have_filename && have_lineno)\r
+ PyOS_snprintf(buffer, bufsize, "%s (%s, line %ld)",\r
+ PyString_AS_STRING(str),\r
+ my_basename(PyString_AS_STRING(self->filename)),\r
+ PyInt_AsLong(self->lineno));\r
+ else if (have_filename)\r
+ PyOS_snprintf(buffer, bufsize, "%s (%s)",\r
+ PyString_AS_STRING(str),\r
+ my_basename(PyString_AS_STRING(self->filename)));\r
+ else /* only have_lineno */\r
+ PyOS_snprintf(buffer, bufsize, "%s (line %ld)",\r
+ PyString_AS_STRING(str),\r
+ PyInt_AsLong(self->lineno));\r
+\r
+ result = PyString_FromString(buffer);\r
+ PyMem_FREE(buffer);\r
+\r
+ if (result == NULL)\r
+ result = str;\r
+ else\r
+ Py_DECREF(str);\r
+ return result;\r
+}\r
+\r
+static PyMemberDef SyntaxError_members[] = {\r
+ {"msg", T_OBJECT, offsetof(PySyntaxErrorObject, msg), 0,\r
+ PyDoc_STR("exception msg")},\r
+ {"filename", T_OBJECT, offsetof(PySyntaxErrorObject, filename), 0,\r
+ PyDoc_STR("exception filename")},\r
+ {"lineno", T_OBJECT, offsetof(PySyntaxErrorObject, lineno), 0,\r
+ PyDoc_STR("exception lineno")},\r
+ {"offset", T_OBJECT, offsetof(PySyntaxErrorObject, offset), 0,\r
+ PyDoc_STR("exception offset")},\r
+ {"text", T_OBJECT, offsetof(PySyntaxErrorObject, text), 0,\r
+ PyDoc_STR("exception text")},\r
+ {"print_file_and_line", T_OBJECT,\r
+ offsetof(PySyntaxErrorObject, print_file_and_line), 0,\r
+ PyDoc_STR("exception print_file_and_line")},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+ComplexExtendsException(PyExc_StandardError, SyntaxError, SyntaxError,\r
+ SyntaxError_dealloc, 0, SyntaxError_members,\r
+ SyntaxError_str, "Invalid syntax.");\r
+\r
+\r
+/*\r
+ * IndentationError extends SyntaxError\r
+ */\r
+MiddlingExtendsException(PyExc_SyntaxError, IndentationError, SyntaxError,\r
+ "Improper indentation.");\r
+\r
+\r
+/*\r
+ * TabError extends IndentationError\r
+ */\r
+MiddlingExtendsException(PyExc_IndentationError, TabError, SyntaxError,\r
+ "Improper mixture of spaces and tabs.");\r
+\r
+\r
+/*\r
+ * LookupError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, LookupError,\r
+ "Base class for lookup errors.");\r
+\r
+\r
+/*\r
+ * IndexError extends LookupError\r
+ */\r
+SimpleExtendsException(PyExc_LookupError, IndexError,\r
+ "Sequence index out of range.");\r
+\r
+\r
+/*\r
+ * KeyError extends LookupError\r
+ */\r
+static PyObject *\r
+KeyError_str(PyBaseExceptionObject *self)\r
+{\r
+ /* If args is a tuple of exactly one item, apply repr to args[0].\r
+ This is done so that e.g. the exception raised by {}[''] prints\r
+ KeyError: ''\r
+ rather than the confusing\r
+ KeyError\r
+ alone. The downside is that if KeyError is raised with an explanatory\r
+ string, that string will be displayed in quotes. Too bad.\r
+ If args is anything else, use the default BaseException__str__().\r
+ */\r
+ if (PyTuple_GET_SIZE(self->args) == 1) {\r
+ return PyObject_Repr(PyTuple_GET_ITEM(self->args, 0));\r
+ }\r
+ return BaseException_str(self);\r
+}\r
+\r
+ComplexExtendsException(PyExc_LookupError, KeyError, BaseException,\r
+ 0, 0, 0, KeyError_str, "Mapping key not found.");\r
+\r
+\r
+/*\r
+ * ValueError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, ValueError,\r
+ "Inappropriate argument value (of correct type).");\r
+\r
+/*\r
+ * UnicodeError extends ValueError\r
+ */\r
+\r
+SimpleExtendsException(PyExc_ValueError, UnicodeError,\r
+ "Unicode related error.");\r
+\r
+#ifdef Py_USING_UNICODE\r
+static PyObject *\r
+get_string(PyObject *attr, const char *name)\r
+{\r
+ if (!attr) {\r
+ PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);\r
+ return NULL;\r
+ }\r
+\r
+ if (!PyString_Check(attr)) {\r
+ PyErr_Format(PyExc_TypeError, "%.200s attribute must be str", name);\r
+ return NULL;\r
+ }\r
+ Py_INCREF(attr);\r
+ return attr;\r
+}\r
+\r
+\r
+static int\r
+set_string(PyObject **attr, const char *value)\r
+{\r
+ PyObject *obj = PyString_FromString(value);\r
+ if (!obj)\r
+ return -1;\r
+ Py_CLEAR(*attr);\r
+ *attr = obj;\r
+ return 0;\r
+}\r
+\r
+\r
+static PyObject *\r
+get_unicode(PyObject *attr, const char *name)\r
+{\r
+ if (!attr) {\r
+ PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);\r
+ return NULL;\r
+ }\r
+\r
+ if (!PyUnicode_Check(attr)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%.200s attribute must be unicode", name);\r
+ return NULL;\r
+ }\r
+ Py_INCREF(attr);\r
+ return attr;\r
+}\r
+\r
+PyObject *\r
+PyUnicodeEncodeError_GetEncoding(PyObject *exc)\r
+{\r
+ return get_string(((PyUnicodeErrorObject *)exc)->encoding, "encoding");\r
+}\r
+\r
+PyObject *\r
+PyUnicodeDecodeError_GetEncoding(PyObject *exc)\r
+{\r
+ return get_string(((PyUnicodeErrorObject *)exc)->encoding, "encoding");\r
+}\r
+\r
+PyObject *\r
+PyUnicodeEncodeError_GetObject(PyObject *exc)\r
+{\r
+ return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object");\r
+}\r
+\r
+PyObject *\r
+PyUnicodeDecodeError_GetObject(PyObject *exc)\r
+{\r
+ return get_string(((PyUnicodeErrorObject *)exc)->object, "object");\r
+}\r
+\r
+PyObject *\r
+PyUnicodeTranslateError_GetObject(PyObject *exc)\r
+{\r
+ return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object");\r
+}\r
+\r
+int\r
+PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start)\r
+{\r
+ Py_ssize_t size;\r
+ PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object,\r
+ "object");\r
+ if (!obj)\r
+ return -1;\r
+ *start = ((PyUnicodeErrorObject *)exc)->start;\r
+ size = PyUnicode_GET_SIZE(obj);\r
+ if (*start<0)\r
+ *start = 0; /*XXX check for values <0*/\r
+ if (*start>=size)\r
+ *start = size-1;\r
+ Py_DECREF(obj);\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start)\r
+{\r
+ Py_ssize_t size;\r
+ PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object,\r
+ "object");\r
+ if (!obj)\r
+ return -1;\r
+ size = PyString_GET_SIZE(obj);\r
+ *start = ((PyUnicodeErrorObject *)exc)->start;\r
+ if (*start<0)\r
+ *start = 0;\r
+ if (*start>=size)\r
+ *start = size-1;\r
+ Py_DECREF(obj);\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyUnicodeTranslateError_GetStart(PyObject *exc, Py_ssize_t *start)\r
+{\r
+ return PyUnicodeEncodeError_GetStart(exc, start);\r
+}\r
+\r
+\r
+int\r
+PyUnicodeEncodeError_SetStart(PyObject *exc, Py_ssize_t start)\r
+{\r
+ ((PyUnicodeErrorObject *)exc)->start = start;\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyUnicodeDecodeError_SetStart(PyObject *exc, Py_ssize_t start)\r
+{\r
+ ((PyUnicodeErrorObject *)exc)->start = start;\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyUnicodeTranslateError_SetStart(PyObject *exc, Py_ssize_t start)\r
+{\r
+ ((PyUnicodeErrorObject *)exc)->start = start;\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end)\r
+{\r
+ Py_ssize_t size;\r
+ PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object,\r
+ "object");\r
+ if (!obj)\r
+ return -1;\r
+ *end = ((PyUnicodeErrorObject *)exc)->end;\r
+ size = PyUnicode_GET_SIZE(obj);\r
+ if (*end<1)\r
+ *end = 1;\r
+ if (*end>size)\r
+ *end = size;\r
+ Py_DECREF(obj);\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end)\r
+{\r
+ Py_ssize_t size;\r
+ PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object,\r
+ "object");\r
+ if (!obj)\r
+ return -1;\r
+ *end = ((PyUnicodeErrorObject *)exc)->end;\r
+ size = PyString_GET_SIZE(obj);\r
+ if (*end<1)\r
+ *end = 1;\r
+ if (*end>size)\r
+ *end = size;\r
+ Py_DECREF(obj);\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyUnicodeTranslateError_GetEnd(PyObject *exc, Py_ssize_t *start)\r
+{\r
+ return PyUnicodeEncodeError_GetEnd(exc, start);\r
+}\r
+\r
+\r
+int\r
+PyUnicodeEncodeError_SetEnd(PyObject *exc, Py_ssize_t end)\r
+{\r
+ ((PyUnicodeErrorObject *)exc)->end = end;\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyUnicodeDecodeError_SetEnd(PyObject *exc, Py_ssize_t end)\r
+{\r
+ ((PyUnicodeErrorObject *)exc)->end = end;\r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+PyUnicodeTranslateError_SetEnd(PyObject *exc, Py_ssize_t end)\r
+{\r
+ ((PyUnicodeErrorObject *)exc)->end = end;\r
+ return 0;\r
+}\r
+\r
+PyObject *\r
+PyUnicodeEncodeError_GetReason(PyObject *exc)\r
+{\r
+ return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason");\r
+}\r
+\r
+\r
+PyObject *\r
+PyUnicodeDecodeError_GetReason(PyObject *exc)\r
+{\r
+ return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason");\r
+}\r
+\r
+\r
+PyObject *\r
+PyUnicodeTranslateError_GetReason(PyObject *exc)\r
+{\r
+ return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason");\r
+}\r
+\r
+\r
+int\r
+PyUnicodeEncodeError_SetReason(PyObject *exc, const char *reason)\r
+{\r
+ return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason);\r
+}\r
+\r
+\r
+int\r
+PyUnicodeDecodeError_SetReason(PyObject *exc, const char *reason)\r
+{\r
+ return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason);\r
+}\r
+\r
+\r
+int\r
+PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason)\r
+{\r
+ return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason);\r
+}\r
+\r
+\r
+static int\r
+UnicodeError_init(PyUnicodeErrorObject *self, PyObject *args, PyObject *kwds,\r
+ PyTypeObject *objecttype)\r
+{\r
+ Py_CLEAR(self->encoding);\r
+ Py_CLEAR(self->object);\r
+ Py_CLEAR(self->reason);\r
+\r
+ if (!PyArg_ParseTuple(args, "O!O!nnO!",\r
+ &PyString_Type, &self->encoding,\r
+ objecttype, &self->object,\r
+ &self->start,\r
+ &self->end,\r
+ &PyString_Type, &self->reason)) {\r
+ self->encoding = self->object = self->reason = NULL;\r
+ return -1;\r
+ }\r
+\r
+ Py_INCREF(self->encoding);\r
+ Py_INCREF(self->object);\r
+ Py_INCREF(self->reason);\r
+\r
+ return 0;\r
+}\r
+\r
+static int\r
+UnicodeError_clear(PyUnicodeErrorObject *self)\r
+{\r
+ Py_CLEAR(self->encoding);\r
+ Py_CLEAR(self->object);\r
+ Py_CLEAR(self->reason);\r
+ return BaseException_clear((PyBaseExceptionObject *)self);\r
+}\r
+\r
+static void\r
+UnicodeError_dealloc(PyUnicodeErrorObject *self)\r
+{\r
+ _PyObject_GC_UNTRACK(self);\r
+ UnicodeError_clear(self);\r
+ Py_TYPE(self)->tp_free((PyObject *)self);\r
+}\r
+\r
+static int\r
+UnicodeError_traverse(PyUnicodeErrorObject *self, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(self->encoding);\r
+ Py_VISIT(self->object);\r
+ Py_VISIT(self->reason);\r
+ return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);\r
+}\r
+\r
+static PyMemberDef UnicodeError_members[] = {\r
+ {"encoding", T_OBJECT, offsetof(PyUnicodeErrorObject, encoding), 0,\r
+ PyDoc_STR("exception encoding")},\r
+ {"object", T_OBJECT, offsetof(PyUnicodeErrorObject, object), 0,\r
+ PyDoc_STR("exception object")},\r
+ {"start", T_PYSSIZET, offsetof(PyUnicodeErrorObject, start), 0,\r
+ PyDoc_STR("exception start")},\r
+ {"end", T_PYSSIZET, offsetof(PyUnicodeErrorObject, end), 0,\r
+ PyDoc_STR("exception end")},\r
+ {"reason", T_OBJECT, offsetof(PyUnicodeErrorObject, reason), 0,\r
+ PyDoc_STR("exception reason")},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+\r
+/*\r
+ * UnicodeEncodeError extends UnicodeError\r
+ */\r
+\r
+static int\r
+UnicodeEncodeError_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)\r
+ return -1;\r
+ return UnicodeError_init((PyUnicodeErrorObject *)self, args,\r
+ kwds, &PyUnicode_Type);\r
+}\r
+\r
+static PyObject *\r
+UnicodeEncodeError_str(PyObject *self)\r
+{\r
+ PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;\r
+ PyObject *result = NULL;\r
+ PyObject *reason_str = NULL;\r
+ PyObject *encoding_str = NULL;\r
+\r
+ if (!uself->object)\r
+ /* Not properly initialized. */\r
+ return PyUnicode_FromString("");\r
+\r
+ /* Get reason and encoding as strings, which they might not be if\r
+ they've been modified after we were contructed. */\r
+ reason_str = PyObject_Str(uself->reason);\r
+ if (reason_str == NULL)\r
+ goto done;\r
+ encoding_str = PyObject_Str(uself->encoding);\r
+ if (encoding_str == NULL)\r
+ goto done;\r
+\r
+ if (uself->start < PyUnicode_GET_SIZE(uself->object) && uself->end == uself->start+1) {\r
+ int badchar = (int)PyUnicode_AS_UNICODE(uself->object)[uself->start];\r
+ char badchar_str[20];\r
+ if (badchar <= 0xff)\r
+ PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar);\r
+ else if (badchar <= 0xffff)\r
+ PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar);\r
+ else\r
+ PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar);\r
+ result = PyString_FromFormat(\r
+ "'%.400s' codec can't encode character u'\\%s' in position %zd: %.400s",\r
+ PyString_AS_STRING(encoding_str),\r
+ badchar_str,\r
+ uself->start,\r
+ PyString_AS_STRING(reason_str));\r
+ }\r
+ else {\r
+ result = PyString_FromFormat(\r
+ "'%.400s' codec can't encode characters in position %zd-%zd: %.400s",\r
+ PyString_AS_STRING(encoding_str),\r
+ uself->start,\r
+ uself->end-1,\r
+ PyString_AS_STRING(reason_str));\r
+ }\r
+done:\r
+ Py_XDECREF(reason_str);\r
+ Py_XDECREF(encoding_str);\r
+ return result;\r
+}\r
+\r
+static PyTypeObject _PyExc_UnicodeEncodeError = {\r
+ PyObject_HEAD_INIT(NULL)\r
+ 0,\r
+ EXC_MODULE_NAME "UnicodeEncodeError",\r
+ sizeof(PyUnicodeErrorObject), 0,\r
+ (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ (reprfunc)UnicodeEncodeError_str, 0, 0, 0,\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,\r
+ PyDoc_STR("Unicode encoding error."), (traverseproc)UnicodeError_traverse,\r
+ (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,\r
+ 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),\r
+ (initproc)UnicodeEncodeError_init, 0, BaseException_new,\r
+};\r
+PyObject *PyExc_UnicodeEncodeError = (PyObject *)&_PyExc_UnicodeEncodeError;\r
+\r
+PyObject *\r
+PyUnicodeEncodeError_Create(\r
+ const char *encoding, const Py_UNICODE *object, Py_ssize_t length,\r
+ Py_ssize_t start, Py_ssize_t end, const char *reason)\r
+{\r
+ return PyObject_CallFunction(PyExc_UnicodeEncodeError, "su#nns",\r
+ encoding, object, length, start, end, reason);\r
+}\r
+\r
+\r
+/*\r
+ * UnicodeDecodeError extends UnicodeError\r
+ */\r
+\r
+static int\r
+UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)\r
+ return -1;\r
+ return UnicodeError_init((PyUnicodeErrorObject *)self, args,\r
+ kwds, &PyString_Type);\r
+}\r
+\r
+static PyObject *\r
+UnicodeDecodeError_str(PyObject *self)\r
+{\r
+ PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;\r
+ PyObject *result = NULL;\r
+ PyObject *reason_str = NULL;\r
+ PyObject *encoding_str = NULL;\r
+\r
+ if (!uself->object)\r
+ /* Not properly initialized. */\r
+ return PyUnicode_FromString("");\r
+\r
+ /* Get reason and encoding as strings, which they might not be if\r
+ they've been modified after we were contructed. */\r
+ reason_str = PyObject_Str(uself->reason);\r
+ if (reason_str == NULL)\r
+ goto done;\r
+ encoding_str = PyObject_Str(uself->encoding);\r
+ if (encoding_str == NULL)\r
+ goto done;\r
+\r
+ if (uself->start < PyUnicode_GET_SIZE(uself->object) && uself->end == uself->start+1) {\r
+ /* FromFormat does not support %02x, so format that separately */\r
+ char byte[4];\r
+ PyOS_snprintf(byte, sizeof(byte), "%02x",\r
+ ((int)PyString_AS_STRING(uself->object)[uself->start])&0xff);\r
+ result = PyString_FromFormat(\r
+ "'%.400s' codec can't decode byte 0x%s in position %zd: %.400s",\r
+ PyString_AS_STRING(encoding_str),\r
+ byte,\r
+ uself->start,\r
+ PyString_AS_STRING(reason_str));\r
+ }\r
+ else {\r
+ result = PyString_FromFormat(\r
+ "'%.400s' codec can't decode bytes in position %zd-%zd: %.400s",\r
+ PyString_AS_STRING(encoding_str),\r
+ uself->start,\r
+ uself->end-1,\r
+ PyString_AS_STRING(reason_str));\r
+ }\r
+done:\r
+ Py_XDECREF(reason_str);\r
+ Py_XDECREF(encoding_str);\r
+ return result;\r
+}\r
+\r
+static PyTypeObject _PyExc_UnicodeDecodeError = {\r
+ PyObject_HEAD_INIT(NULL)\r
+ 0,\r
+ EXC_MODULE_NAME "UnicodeDecodeError",\r
+ sizeof(PyUnicodeErrorObject), 0,\r
+ (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ (reprfunc)UnicodeDecodeError_str, 0, 0, 0,\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,\r
+ PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse,\r
+ (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,\r
+ 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),\r
+ (initproc)UnicodeDecodeError_init, 0, BaseException_new,\r
+};\r
+PyObject *PyExc_UnicodeDecodeError = (PyObject *)&_PyExc_UnicodeDecodeError;\r
+\r
+PyObject *\r
+PyUnicodeDecodeError_Create(\r
+ const char *encoding, const char *object, Py_ssize_t length,\r
+ Py_ssize_t start, Py_ssize_t end, const char *reason)\r
+{\r
+ return PyObject_CallFunction(PyExc_UnicodeDecodeError, "ss#nns",\r
+ encoding, object, length, start, end, reason);\r
+}\r
+\r
+\r
+/*\r
+ * UnicodeTranslateError extends UnicodeError\r
+ */\r
+\r
+static int\r
+UnicodeTranslateError_init(PyUnicodeErrorObject *self, PyObject *args,\r
+ PyObject *kwds)\r
+{\r
+ if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)\r
+ return -1;\r
+\r
+ Py_CLEAR(self->object);\r
+ Py_CLEAR(self->reason);\r
+\r
+ if (!PyArg_ParseTuple(args, "O!nnO!",\r
+ &PyUnicode_Type, &self->object,\r
+ &self->start,\r
+ &self->end,\r
+ &PyString_Type, &self->reason)) {\r
+ self->object = self->reason = NULL;\r
+ return -1;\r
+ }\r
+\r
+ Py_INCREF(self->object);\r
+ Py_INCREF(self->reason);\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+static PyObject *\r
+UnicodeTranslateError_str(PyObject *self)\r
+{\r
+ PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;\r
+ PyObject *result = NULL;\r
+ PyObject *reason_str = NULL;\r
+\r
+ if (!uself->object)\r
+ /* Not properly initialized. */\r
+ return PyUnicode_FromString("");\r
+\r
+ /* Get reason as a string, which it might not be if it's been\r
+ modified after we were contructed. */\r
+ reason_str = PyObject_Str(uself->reason);\r
+ if (reason_str == NULL)\r
+ goto done;\r
+\r
+ if (uself->start < PyUnicode_GET_SIZE(uself->object) && uself->end == uself->start+1) {\r
+ int badchar = (int)PyUnicode_AS_UNICODE(uself->object)[uself->start];\r
+ char badchar_str[20];\r
+ if (badchar <= 0xff)\r
+ PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar);\r
+ else if (badchar <= 0xffff)\r
+ PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar);\r
+ else\r
+ PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar);\r
+ result = PyString_FromFormat(\r
+ "can't translate character u'\\%s' in position %zd: %.400s",\r
+ badchar_str,\r
+ uself->start,\r
+ PyString_AS_STRING(reason_str));\r
+ } else {\r
+ result = PyString_FromFormat(\r
+ "can't translate characters in position %zd-%zd: %.400s",\r
+ uself->start,\r
+ uself->end-1,\r
+ PyString_AS_STRING(reason_str));\r
+ }\r
+done:\r
+ Py_XDECREF(reason_str);\r
+ return result;\r
+}\r
+\r
+static PyTypeObject _PyExc_UnicodeTranslateError = {\r
+ PyObject_HEAD_INIT(NULL)\r
+ 0,\r
+ EXC_MODULE_NAME "UnicodeTranslateError",\r
+ sizeof(PyUnicodeErrorObject), 0,\r
+ (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ (reprfunc)UnicodeTranslateError_str, 0, 0, 0,\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,\r
+ PyDoc_STR("Unicode translation error."), (traverseproc)UnicodeError_traverse,\r
+ (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,\r
+ 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),\r
+ (initproc)UnicodeTranslateError_init, 0, BaseException_new,\r
+};\r
+PyObject *PyExc_UnicodeTranslateError = (PyObject *)&_PyExc_UnicodeTranslateError;\r
+\r
+PyObject *\r
+PyUnicodeTranslateError_Create(\r
+ const Py_UNICODE *object, Py_ssize_t length,\r
+ Py_ssize_t start, Py_ssize_t end, const char *reason)\r
+{\r
+ return PyObject_CallFunction(PyExc_UnicodeTranslateError, "u#nns",\r
+ object, length, start, end, reason);\r
+}\r
+#endif\r
+\r
+\r
+/*\r
+ * AssertionError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, AssertionError,\r
+ "Assertion failed.");\r
+\r
+\r
+/*\r
+ * ArithmeticError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, ArithmeticError,\r
+ "Base class for arithmetic errors.");\r
+\r
+\r
+/*\r
+ * FloatingPointError extends ArithmeticError\r
+ */\r
+SimpleExtendsException(PyExc_ArithmeticError, FloatingPointError,\r
+ "Floating point operation failed.");\r
+\r
+\r
+/*\r
+ * OverflowError extends ArithmeticError\r
+ */\r
+SimpleExtendsException(PyExc_ArithmeticError, OverflowError,\r
+ "Result too large to be represented.");\r
+\r
+\r
+/*\r
+ * ZeroDivisionError extends ArithmeticError\r
+ */\r
+SimpleExtendsException(PyExc_ArithmeticError, ZeroDivisionError,\r
+ "Second argument to a division or modulo operation was zero.");\r
+\r
+\r
+/*\r
+ * SystemError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, SystemError,\r
+ "Internal error in the Python interpreter.\n"\r
+ "\n"\r
+ "Please report this to the Python maintainer, along with the traceback,\n"\r
+ "the Python version, and the hardware/OS platform and version.");\r
+\r
+\r
+/*\r
+ * ReferenceError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, ReferenceError,\r
+ "Weak ref proxy used after referent went away.");\r
+\r
+\r
+/*\r
+ * MemoryError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, MemoryError, "Out of memory.");\r
+\r
+/*\r
+ * BufferError extends StandardError\r
+ */\r
+SimpleExtendsException(PyExc_StandardError, BufferError, "Buffer error.");\r
+\r
+\r
+/* Warning category docstrings */\r
+\r
+/*\r
+ * Warning extends Exception\r
+ */\r
+SimpleExtendsException(PyExc_Exception, Warning,\r
+ "Base class for warning categories.");\r
+\r
+\r
+/*\r
+ * UserWarning extends Warning\r
+ */\r
+SimpleExtendsException(PyExc_Warning, UserWarning,\r
+ "Base class for warnings generated by user code.");\r
+\r
+\r
+/*\r
+ * DeprecationWarning extends Warning\r
+ */\r
+SimpleExtendsException(PyExc_Warning, DeprecationWarning,\r
+ "Base class for warnings about deprecated features.");\r
+\r
+\r
+/*\r
+ * PendingDeprecationWarning extends Warning\r
+ */\r
+SimpleExtendsException(PyExc_Warning, PendingDeprecationWarning,\r
+ "Base class for warnings about features which will be deprecated\n"\r
+ "in the future.");\r
+\r
+\r
+/*\r
+ * SyntaxWarning extends Warning\r
+ */\r
+SimpleExtendsException(PyExc_Warning, SyntaxWarning,\r
+ "Base class for warnings about dubious syntax.");\r
+\r
+\r
+/*\r
+ * RuntimeWarning extends Warning\r
+ */\r
+SimpleExtendsException(PyExc_Warning, RuntimeWarning,\r
+ "Base class for warnings about dubious runtime behavior.");\r
+\r
+\r
+/*\r
+ * FutureWarning extends Warning\r
+ */\r
+SimpleExtendsException(PyExc_Warning, FutureWarning,\r
+ "Base class for warnings about constructs that will change semantically\n"\r
+ "in the future.");\r
+\r
+\r
+/*\r
+ * ImportWarning extends Warning\r
+ */\r
+SimpleExtendsException(PyExc_Warning, ImportWarning,\r
+ "Base class for warnings about probable mistakes in module imports");\r
+\r
+\r
+/*\r
+ * UnicodeWarning extends Warning\r
+ */\r
+SimpleExtendsException(PyExc_Warning, UnicodeWarning,\r
+ "Base class for warnings about Unicode related problems, mostly\n"\r
+ "related to conversion problems.");\r
+\r
+/*\r
+ * BytesWarning extends Warning\r
+ */\r
+SimpleExtendsException(PyExc_Warning, BytesWarning,\r
+ "Base class for warnings about bytes and buffer related problems, mostly\n"\r
+ "related to conversion from str or comparing to str.");\r
+\r
+/* Pre-computed MemoryError instance. Best to create this as early as\r
+ * possible and not wait until a MemoryError is actually raised!\r
+ */\r
+PyObject *PyExc_MemoryErrorInst=NULL;\r
+\r
+/* Pre-computed RuntimeError instance for when recursion depth is reached.\r
+ Meant to be used when normalizing the exception for exceeding the recursion\r
+ depth will cause its own infinite recursion.\r
+*/\r
+PyObject *PyExc_RecursionErrorInst = NULL;\r
+\r
+/* module global functions */\r
+static PyMethodDef functions[] = {\r
+ /* Sentinel */\r
+ {NULL, NULL}\r
+};\r
+\r
+#define PRE_INIT(TYPE) if (PyType_Ready(&_PyExc_ ## TYPE) < 0) \\r
+ Py_FatalError("exceptions bootstrapping error.");\r
+\r
+#define POST_INIT(TYPE) Py_INCREF(PyExc_ ## TYPE); \\r
+ PyModule_AddObject(m, # TYPE, PyExc_ ## TYPE); \\r
+ if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) \\r
+ Py_FatalError("Module dictionary insertion problem.");\r
+\r
+\r
+PyMODINIT_FUNC\r
+_PyExc_Init(void)\r
+{\r
+ PyObject *m, *bltinmod, *bdict;\r
+\r
+ PRE_INIT(BaseException)\r
+ PRE_INIT(Exception)\r
+ PRE_INIT(StandardError)\r
+ PRE_INIT(TypeError)\r
+ PRE_INIT(StopIteration)\r
+ PRE_INIT(GeneratorExit)\r
+ PRE_INIT(SystemExit)\r
+ PRE_INIT(KeyboardInterrupt)\r
+ PRE_INIT(ImportError)\r
+ PRE_INIT(EnvironmentError)\r
+ PRE_INIT(IOError)\r
+ PRE_INIT(OSError)\r
+#ifdef MS_WINDOWS\r
+ PRE_INIT(WindowsError)\r
+#endif\r
+#ifdef __VMS\r
+ PRE_INIT(VMSError)\r
+#endif\r
+ PRE_INIT(EOFError)\r
+ PRE_INIT(RuntimeError)\r
+ PRE_INIT(NotImplementedError)\r
+ PRE_INIT(NameError)\r
+ PRE_INIT(UnboundLocalError)\r
+ PRE_INIT(AttributeError)\r
+ PRE_INIT(SyntaxError)\r
+ PRE_INIT(IndentationError)\r
+ PRE_INIT(TabError)\r
+ PRE_INIT(LookupError)\r
+ PRE_INIT(IndexError)\r
+ PRE_INIT(KeyError)\r
+ PRE_INIT(ValueError)\r
+ PRE_INIT(UnicodeError)\r
+#ifdef Py_USING_UNICODE\r
+ PRE_INIT(UnicodeEncodeError)\r
+ PRE_INIT(UnicodeDecodeError)\r
+ PRE_INIT(UnicodeTranslateError)\r
+#endif\r
+ PRE_INIT(AssertionError)\r
+ PRE_INIT(ArithmeticError)\r
+ PRE_INIT(FloatingPointError)\r
+ PRE_INIT(OverflowError)\r
+ PRE_INIT(ZeroDivisionError)\r
+ PRE_INIT(SystemError)\r
+ PRE_INIT(ReferenceError)\r
+ PRE_INIT(MemoryError)\r
+ PRE_INIT(BufferError)\r
+ PRE_INIT(Warning)\r
+ PRE_INIT(UserWarning)\r
+ PRE_INIT(DeprecationWarning)\r
+ PRE_INIT(PendingDeprecationWarning)\r
+ PRE_INIT(SyntaxWarning)\r
+ PRE_INIT(RuntimeWarning)\r
+ PRE_INIT(FutureWarning)\r
+ PRE_INIT(ImportWarning)\r
+ PRE_INIT(UnicodeWarning)\r
+ PRE_INIT(BytesWarning)\r
+\r
+ m = Py_InitModule4("exceptions", functions, exceptions_doc,\r
+ (PyObject *)NULL, PYTHON_API_VERSION);\r
+ if (m == NULL)\r
+ return;\r
+\r
+ bltinmod = PyImport_ImportModule("__builtin__");\r
+ if (bltinmod == NULL)\r
+ Py_FatalError("exceptions bootstrapping error.");\r
+ bdict = PyModule_GetDict(bltinmod);\r
+ if (bdict == NULL)\r
+ Py_FatalError("exceptions bootstrapping error.");\r
+\r
+ POST_INIT(BaseException)\r
+ POST_INIT(Exception)\r
+ POST_INIT(StandardError)\r
+ POST_INIT(TypeError)\r
+ POST_INIT(StopIteration)\r
+ POST_INIT(GeneratorExit)\r
+ POST_INIT(SystemExit)\r
+ POST_INIT(KeyboardInterrupt)\r
+ POST_INIT(ImportError)\r
+ POST_INIT(EnvironmentError)\r
+ POST_INIT(IOError)\r
+ POST_INIT(OSError)\r
+#ifdef MS_WINDOWS\r
+ POST_INIT(WindowsError)\r
+#endif\r
+#ifdef __VMS\r
+ POST_INIT(VMSError)\r
+#endif\r
+ POST_INIT(EOFError)\r
+ POST_INIT(RuntimeError)\r
+ POST_INIT(NotImplementedError)\r
+ POST_INIT(NameError)\r
+ POST_INIT(UnboundLocalError)\r
+ POST_INIT(AttributeError)\r
+ POST_INIT(SyntaxError)\r
+ POST_INIT(IndentationError)\r
+ POST_INIT(TabError)\r
+ POST_INIT(LookupError)\r
+ POST_INIT(IndexError)\r
+ POST_INIT(KeyError)\r
+ POST_INIT(ValueError)\r
+ POST_INIT(UnicodeError)\r
+#ifdef Py_USING_UNICODE\r
+ POST_INIT(UnicodeEncodeError)\r
+ POST_INIT(UnicodeDecodeError)\r
+ POST_INIT(UnicodeTranslateError)\r
+#endif\r
+ POST_INIT(AssertionError)\r
+ POST_INIT(ArithmeticError)\r
+ POST_INIT(FloatingPointError)\r
+ POST_INIT(OverflowError)\r
+ POST_INIT(ZeroDivisionError)\r
+ POST_INIT(SystemError)\r
+ POST_INIT(ReferenceError)\r
+ POST_INIT(MemoryError)\r
+ POST_INIT(BufferError)\r
+ POST_INIT(Warning)\r
+ POST_INIT(UserWarning)\r
+ POST_INIT(DeprecationWarning)\r
+ POST_INIT(PendingDeprecationWarning)\r
+ POST_INIT(SyntaxWarning)\r
+ POST_INIT(RuntimeWarning)\r
+ POST_INIT(FutureWarning)\r
+ POST_INIT(ImportWarning)\r
+ POST_INIT(UnicodeWarning)\r
+ POST_INIT(BytesWarning)\r
+\r
+ PyExc_MemoryErrorInst = BaseException_new(&_PyExc_MemoryError, NULL, NULL);\r
+ if (!PyExc_MemoryErrorInst)\r
+ Py_FatalError("Cannot pre-allocate MemoryError instance");\r
+\r
+ PyExc_RecursionErrorInst = BaseException_new(&_PyExc_RuntimeError, NULL, NULL);\r
+ if (!PyExc_RecursionErrorInst)\r
+ Py_FatalError("Cannot pre-allocate RuntimeError instance for "\r
+ "recursion errors");\r
+ else {\r
+ PyBaseExceptionObject *err_inst =\r
+ (PyBaseExceptionObject *)PyExc_RecursionErrorInst;\r
+ PyObject *args_tuple;\r
+ PyObject *exc_message;\r
+ exc_message = PyString_FromString("maximum recursion depth exceeded");\r
+ if (!exc_message)\r
+ Py_FatalError("cannot allocate argument for RuntimeError "\r
+ "pre-allocation");\r
+ args_tuple = PyTuple_Pack(1, exc_message);\r
+ if (!args_tuple)\r
+ Py_FatalError("cannot allocate tuple for RuntimeError "\r
+ "pre-allocation");\r
+ Py_DECREF(exc_message);\r
+ if (BaseException_init(err_inst, args_tuple, NULL))\r
+ Py_FatalError("init of pre-allocated RuntimeError failed");\r
+ Py_DECREF(args_tuple);\r
+ }\r
+ Py_DECREF(bltinmod);\r
+}\r
+\r
+void\r
+_PyExc_Fini(void)\r
+{\r
+ Py_CLEAR(PyExc_MemoryErrorInst);\r
+ Py_CLEAR(PyExc_RecursionErrorInst);\r
+}\r
--- /dev/null
+/* File object implementation */\r
+\r
+#define PY_SSIZE_T_CLEAN\r
+#include "Python.h"\r
+#include "structmember.h"\r
+\r
+#ifdef HAVE_SYS_TYPES_H\r
+#include <sys/types.h>\r
+#endif /* HAVE_SYS_TYPES_H */\r
+\r
+#ifdef MS_WINDOWS\r
+#define fileno _fileno\r
+/* can simulate truncate with Win32 API functions; see file_truncate */\r
+#define HAVE_FTRUNCATE\r
+#define WIN32_LEAN_AND_MEAN\r
+#include <windows.h>\r
+#endif\r
+\r
+#if defined(PYOS_OS2) && defined(PYCC_GCC)\r
+#include <io.h>\r
+#endif\r
+\r
+#define BUF(v) PyString_AS_STRING((PyStringObject *)v)\r
+\r
+#ifdef HAVE_ERRNO_H\r
+#include <errno.h>\r
+#endif\r
+\r
+#ifdef HAVE_GETC_UNLOCKED\r
+#define GETC(f) getc_unlocked(f)\r
+#define FLOCKFILE(f) flockfile(f)\r
+#define FUNLOCKFILE(f) funlockfile(f)\r
+#else\r
+#define GETC(f) getc(f)\r
+#define FLOCKFILE(f)\r
+#define FUNLOCKFILE(f)\r
+#endif\r
+\r
+/* Bits in f_newlinetypes */\r
+#define NEWLINE_UNKNOWN 0 /* No newline seen, yet */\r
+#define NEWLINE_CR 1 /* \r newline seen */\r
+#define NEWLINE_LF 2 /* \n newline seen */\r
+#define NEWLINE_CRLF 4 /* \r\n newline seen */\r
+\r
+/*\r
+ * These macros release the GIL while preventing the f_close() function being\r
+ * called in the interval between them. For that purpose, a running total of\r
+ * the number of currently running unlocked code sections is kept in\r
+ * the unlocked_count field of the PyFileObject. The close() method raises\r
+ * an IOError if that field is non-zero. See issue #815646, #595601.\r
+ */\r
+\r
+#define FILE_BEGIN_ALLOW_THREADS(fobj) \\r
+{ \\r
+ fobj->unlocked_count++; \\r
+ Py_BEGIN_ALLOW_THREADS\r
+\r
+#define FILE_END_ALLOW_THREADS(fobj) \\r
+ Py_END_ALLOW_THREADS \\r
+ fobj->unlocked_count--; \\r
+ assert(fobj->unlocked_count >= 0); \\r
+}\r
+\r
+#define FILE_ABORT_ALLOW_THREADS(fobj) \\r
+ Py_BLOCK_THREADS \\r
+ fobj->unlocked_count--; \\r
+ assert(fobj->unlocked_count >= 0);\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+FILE *\r
+PyFile_AsFile(PyObject *f)\r
+{\r
+ if (f == NULL || !PyFile_Check(f))\r
+ return NULL;\r
+ else\r
+ return ((PyFileObject *)f)->f_fp;\r
+}\r
+\r
+void PyFile_IncUseCount(PyFileObject *fobj)\r
+{\r
+ fobj->unlocked_count++;\r
+}\r
+\r
+void PyFile_DecUseCount(PyFileObject *fobj)\r
+{\r
+ fobj->unlocked_count--;\r
+ assert(fobj->unlocked_count >= 0);\r
+}\r
+\r
+PyObject *\r
+PyFile_Name(PyObject *f)\r
+{\r
+ if (f == NULL || !PyFile_Check(f))\r
+ return NULL;\r
+ else\r
+ return ((PyFileObject *)f)->f_name;\r
+}\r
+\r
+/* This is a safe wrapper around PyObject_Print to print to the FILE\r
+ of a PyFileObject. PyObject_Print releases the GIL but knows nothing\r
+ about PyFileObject. */\r
+static int\r
+file_PyObject_Print(PyObject *op, PyFileObject *f, int flags)\r
+{\r
+ int result;\r
+ PyFile_IncUseCount(f);\r
+ result = PyObject_Print(op, f->f_fp, flags);\r
+ PyFile_DecUseCount(f);\r
+ return result;\r
+}\r
+\r
+/* On Unix, fopen will succeed for directories.\r
+ In Python, there should be no file objects referring to\r
+ directories, so we need a check. */\r
+\r
+static PyFileObject*\r
+dircheck(PyFileObject* f)\r
+{\r
+#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)\r
+ struct stat buf;\r
+ if (f->f_fp == NULL)\r
+ return f;\r
+ if (fstat(fileno(f->f_fp), &buf) == 0 &&\r
+ S_ISDIR(buf.st_mode)) {\r
+ char *msg = strerror(EISDIR);\r
+ PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(isO)",\r
+ EISDIR, msg, f->f_name);\r
+ PyErr_SetObject(PyExc_IOError, exc);\r
+ Py_XDECREF(exc);\r
+ return NULL;\r
+ }\r
+#endif\r
+ return f;\r
+}\r
+\r
+\r
+static PyObject *\r
+fill_file_fields(PyFileObject *f, FILE *fp, PyObject *name, char *mode,\r
+ int (*close)(FILE *))\r
+{\r
+ assert(name != NULL);\r
+ assert(f != NULL);\r
+ assert(PyFile_Check(f));\r
+ assert(f->f_fp == NULL);\r
+\r
+ Py_DECREF(f->f_name);\r
+ Py_DECREF(f->f_mode);\r
+ Py_DECREF(f->f_encoding);\r
+ Py_DECREF(f->f_errors);\r
+\r
+ Py_INCREF(name);\r
+ f->f_name = name;\r
+\r
+ f->f_mode = PyString_FromString(mode);\r
+\r
+ f->f_close = close;\r
+ f->f_softspace = 0;\r
+ f->f_binary = strchr(mode,'b') != NULL;\r
+ f->f_buf = NULL;\r
+ f->f_univ_newline = (strchr(mode, 'U') != NULL);\r
+ f->f_newlinetypes = NEWLINE_UNKNOWN;\r
+ f->f_skipnextlf = 0;\r
+ Py_INCREF(Py_None);\r
+ f->f_encoding = Py_None;\r
+ Py_INCREF(Py_None);\r
+ f->f_errors = Py_None;\r
+ f->readable = f->writable = 0;\r
+ if (strchr(mode, 'r') != NULL || f->f_univ_newline)\r
+ f->readable = 1;\r
+ if (strchr(mode, 'w') != NULL || strchr(mode, 'a') != NULL)\r
+ f->writable = 1;\r
+ if (strchr(mode, '+') != NULL)\r
+ f->readable = f->writable = 1;\r
+\r
+ if (f->f_mode == NULL)\r
+ return NULL;\r
+ f->f_fp = fp;\r
+ f = dircheck(f);\r
+ return (PyObject *) f;\r
+}\r
+\r
+#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)\r
+#define Py_VERIFY_WINNT\r
+/* The CRT on windows compiled with Visual Studio 2005 and higher may\r
+ * assert if given invalid mode strings. This is all fine and well\r
+ * in static languages like C where the mode string is typcially hard\r
+ * coded. But in Python, were we pass in the mode string from the user,\r
+ * we need to verify it first manually\r
+ */\r
+static int _PyVerify_Mode_WINNT(const char *mode)\r
+{\r
+ /* See if mode string is valid on Windows to avoid hard assertions */\r
+ /* remove leading spacese */\r
+ int singles = 0;\r
+ int pairs = 0;\r
+ int encoding = 0;\r
+ const char *s, *c;\r
+\r
+ while(*mode == ' ') /* strip initial spaces */\r
+ ++mode;\r
+ if (!strchr("rwa", *mode)) /* must start with one of these */\r
+ return 0;\r
+ while (*++mode) {\r
+ if (*mode == ' ' || *mode == 'N') /* ignore spaces and N */\r
+ continue;\r
+ s = "+TD"; /* each of this can appear only once */\r
+ c = strchr(s, *mode);\r
+ if (c) {\r
+ ptrdiff_t idx = s-c;\r
+ if (singles & (1<<idx))\r
+ return 0;\r
+ singles |= (1<<idx);\r
+ continue;\r
+ }\r
+ s = "btcnSR"; /* only one of each letter in the pairs allowed */\r
+ c = strchr(s, *mode);\r
+ if (c) {\r
+ ptrdiff_t idx = (s-c)/2;\r
+ if (pairs & (1<<idx))\r
+ return 0;\r
+ pairs |= (1<<idx);\r
+ continue;\r
+ }\r
+ if (*mode == ',') {\r
+ encoding = 1;\r
+ break;\r
+ }\r
+ return 0; /* found an invalid char */\r
+ }\r
+\r
+ if (encoding) {\r
+ char *e[] = {"UTF-8", "UTF-16LE", "UNICODE"};\r
+ while (*mode == ' ')\r
+ ++mode;\r
+ /* find 'ccs =' */\r
+ if (strncmp(mode, "ccs", 3))\r
+ return 0;\r
+ mode += 3;\r
+ while (*mode == ' ')\r
+ ++mode;\r
+ if (*mode != '=')\r
+ return 0;\r
+ while (*mode == ' ')\r
+ ++mode;\r
+ for(encoding = 0; encoding<_countof(e); ++encoding) {\r
+ size_t l = strlen(e[encoding]);\r
+ if (!strncmp(mode, e[encoding], l)) {\r
+ mode += l; /* found a valid encoding */\r
+ break;\r
+ }\r
+ }\r
+ if (encoding == _countof(e))\r
+ return 0;\r
+ }\r
+ /* skip trailing spaces */\r
+ while (*mode == ' ')\r
+ ++mode;\r
+\r
+ return *mode == '\0'; /* must be at the end of the string */\r
+}\r
+#endif\r
+\r
+/* check for known incorrect mode strings - problem is, platforms are\r
+ free to accept any mode characters they like and are supposed to\r
+ ignore stuff they don't understand... write or append mode with\r
+ universal newline support is expressly forbidden by PEP 278.\r
+ Additionally, remove the 'U' from the mode string as platforms\r
+ won't know what it is. Non-zero return signals an exception */\r
+int\r
+_PyFile_SanitizeMode(char *mode)\r
+{\r
+ char *upos;\r
+ size_t len = strlen(mode);\r
+\r
+ if (!len) {\r
+ PyErr_SetString(PyExc_ValueError, "empty mode string");\r
+ return -1;\r
+ }\r
+\r
+ upos = strchr(mode, 'U');\r
+ if (upos) {\r
+ memmove(upos, upos+1, len-(upos-mode)); /* incl null char */\r
+\r
+ if (mode[0] == 'w' || mode[0] == 'a') {\r
+ PyErr_Format(PyExc_ValueError, "universal newline "\r
+ "mode can only be used with modes "\r
+ "starting with 'r'");\r
+ return -1;\r
+ }\r
+\r
+ if (mode[0] != 'r') {\r
+ memmove(mode+1, mode, strlen(mode)+1);\r
+ mode[0] = 'r';\r
+ }\r
+\r
+ if (!strchr(mode, 'b')) {\r
+ memmove(mode+2, mode+1, strlen(mode));\r
+ mode[1] = 'b';\r
+ }\r
+ } else if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') {\r
+ PyErr_Format(PyExc_ValueError, "mode string must begin with "\r
+ "one of 'r', 'w', 'a' or 'U', not '%.200s'", mode);\r
+ return -1;\r
+ }\r
+#ifdef Py_VERIFY_WINNT\r
+ /* additional checks on NT with visual studio 2005 and higher */\r
+ if (!_PyVerify_Mode_WINNT(mode)) {\r
+ PyErr_Format(PyExc_ValueError, "Invalid mode ('%.50s')", mode);\r
+ return -1;\r
+ }\r
+#endif\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+open_the_file(PyFileObject *f, char *name, char *mode)\r
+{\r
+ char *newmode;\r
+ assert(f != NULL);\r
+ assert(PyFile_Check(f));\r
+#ifdef MS_WINDOWS\r
+ /* windows ignores the passed name in order to support Unicode */\r
+ assert(f->f_name != NULL);\r
+#else\r
+ assert(name != NULL);\r
+#endif\r
+ assert(mode != NULL);\r
+ assert(f->f_fp == NULL);\r
+\r
+ /* probably need to replace 'U' by 'rb' */\r
+ newmode = PyMem_MALLOC(strlen(mode) + 3);\r
+ if (!newmode) {\r
+ PyErr_NoMemory();\r
+ return NULL;\r
+ }\r
+ strcpy(newmode, mode);\r
+\r
+ if (_PyFile_SanitizeMode(newmode)) {\r
+ f = NULL;\r
+ goto cleanup;\r
+ }\r
+\r
+ /* rexec.py can't stop a user from getting the file() constructor --\r
+ all they have to do is get *any* file object f, and then do\r
+ type(f). Here we prevent them from doing damage with it. */\r
+ if (PyEval_GetRestricted()) {\r
+ PyErr_SetString(PyExc_IOError,\r
+ "file() constructor not accessible in restricted mode");\r
+ f = NULL;\r
+ goto cleanup;\r
+ }\r
+ errno = 0;\r
+\r
+#ifdef MS_WINDOWS\r
+ if (PyUnicode_Check(f->f_name)) {\r
+ PyObject *wmode;\r
+ wmode = PyUnicode_DecodeASCII(newmode, strlen(newmode), NULL);\r
+ if (f->f_name && wmode) {\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ /* PyUnicode_AS_UNICODE OK without thread\r
+ lock as it is a simple dereference. */\r
+ f->f_fp = _wfopen(PyUnicode_AS_UNICODE(f->f_name),\r
+ PyUnicode_AS_UNICODE(wmode));\r
+ FILE_END_ALLOW_THREADS(f)\r
+ }\r
+ Py_XDECREF(wmode);\r
+ }\r
+#endif\r
+ if (NULL == f->f_fp && NULL != name) {\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ f->f_fp = fopen(name, newmode);\r
+ FILE_END_ALLOW_THREADS(f)\r
+ }\r
+\r
+ if (f->f_fp == NULL) {\r
+#if defined _MSC_VER && (_MSC_VER < 1400 || !defined(__STDC_SECURE_LIB__))\r
+ /* MSVC 6 (Microsoft) leaves errno at 0 for bad mode strings,\r
+ * across all Windows flavors. When it sets EINVAL varies\r
+ * across Windows flavors, the exact conditions aren't\r
+ * documented, and the answer lies in the OS's implementation\r
+ * of Win32's CreateFile function (whose source is secret).\r
+ * Seems the best we can do is map EINVAL to ENOENT.\r
+ * Starting with Visual Studio .NET 2005, EINVAL is correctly\r
+ * set by our CRT error handler (set in exceptions.c.)\r
+ */\r
+ if (errno == 0) /* bad mode string */\r
+ errno = EINVAL;\r
+ else if (errno == EINVAL) /* unknown, but not a mode string */\r
+ errno = ENOENT;\r
+#endif\r
+ /* EINVAL is returned when an invalid filename or\r
+ * an invalid mode is supplied. */\r
+ if (errno == EINVAL) {\r
+ PyObject *v;\r
+ char message[100];\r
+ PyOS_snprintf(message, 100,\r
+ "invalid mode ('%.50s') or filename", mode);\r
+ v = Py_BuildValue("(isO)", errno, message, f->f_name);\r
+ if (v != NULL) {\r
+ PyErr_SetObject(PyExc_IOError, v);\r
+ Py_DECREF(v);\r
+ }\r
+ }\r
+ else\r
+ PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, f->f_name);\r
+ f = NULL;\r
+ }\r
+ if (f != NULL)\r
+ f = dircheck(f);\r
+\r
+cleanup:\r
+ PyMem_FREE(newmode);\r
+\r
+ return (PyObject *)f;\r
+}\r
+\r
+static PyObject *\r
+close_the_file(PyFileObject *f)\r
+{\r
+ int sts = 0;\r
+ int (*local_close)(FILE *);\r
+ FILE *local_fp = f->f_fp;\r
+ char *local_setbuf = f->f_setbuf;\r
+ if (local_fp != NULL) {\r
+ local_close = f->f_close;\r
+ if (local_close != NULL && f->unlocked_count > 0) {\r
+ if (f->ob_refcnt > 0) {\r
+ PyErr_SetString(PyExc_IOError,\r
+ "close() called during concurrent "\r
+ "operation on the same file object.");\r
+ } else {\r
+ /* This should not happen unless someone is\r
+ * carelessly playing with the PyFileObject\r
+ * struct fields and/or its associated FILE\r
+ * pointer. */\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "PyFileObject locking error in "\r
+ "destructor (refcnt <= 0 at close).");\r
+ }\r
+ return NULL;\r
+ }\r
+ /* NULL out the FILE pointer before releasing the GIL, because\r
+ * it will not be valid anymore after the close() function is\r
+ * called. */\r
+ f->f_fp = NULL;\r
+ if (local_close != NULL) {\r
+ /* Issue #9295: must temporarily reset f_setbuf so that another\r
+ thread doesn't free it when running file_close() concurrently.\r
+ Otherwise this close() will crash when flushing the buffer. */\r
+ f->f_setbuf = NULL;\r
+ Py_BEGIN_ALLOW_THREADS\r
+ errno = 0;\r
+ sts = (*local_close)(local_fp);\r
+ Py_END_ALLOW_THREADS\r
+ f->f_setbuf = local_setbuf;\r
+ if (sts == EOF)\r
+ return PyErr_SetFromErrno(PyExc_IOError);\r
+ if (sts != 0)\r
+ return PyInt_FromLong((long)sts);\r
+ }\r
+ }\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyObject *\r
+PyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *))\r
+{\r
+ PyFileObject *f;\r
+ PyObject *o_name;\r
+\r
+ f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type, NULL, NULL);\r
+ if (f == NULL)\r
+ return NULL;\r
+ o_name = PyString_FromString(name);\r
+ if (o_name == NULL) {\r
+ if (close != NULL && fp != NULL)\r
+ close(fp);\r
+ Py_DECREF(f);\r
+ return NULL;\r
+ }\r
+ if (fill_file_fields(f, fp, o_name, mode, close) == NULL) {\r
+ Py_DECREF(f);\r
+ Py_DECREF(o_name);\r
+ return NULL;\r
+ }\r
+ Py_DECREF(o_name);\r
+ return (PyObject *)f;\r
+}\r
+\r
+PyObject *\r
+PyFile_FromString(char *name, char *mode)\r
+{\r
+ extern int fclose(FILE *);\r
+ PyFileObject *f;\r
+\r
+ f = (PyFileObject *)PyFile_FromFile((FILE *)NULL, name, mode, fclose);\r
+ if (f != NULL) {\r
+ if (open_the_file(f, name, mode) == NULL) {\r
+ Py_DECREF(f);\r
+ f = NULL;\r
+ }\r
+ }\r
+ return (PyObject *)f;\r
+}\r
+\r
+void\r
+PyFile_SetBufSize(PyObject *f, int bufsize)\r
+{\r
+ PyFileObject *file = (PyFileObject *)f;\r
+ if (bufsize >= 0) {\r
+ int type;\r
+ switch (bufsize) {\r
+ case 0:\r
+ type = _IONBF;\r
+ break;\r
+#ifdef HAVE_SETVBUF\r
+ case 1:\r
+ type = _IOLBF;\r
+ bufsize = BUFSIZ;\r
+ break;\r
+#endif\r
+ default:\r
+ type = _IOFBF;\r
+#ifndef HAVE_SETVBUF\r
+ bufsize = BUFSIZ;\r
+#endif\r
+ break;\r
+ }\r
+ fflush(file->f_fp);\r
+ if (type == _IONBF) {\r
+ PyMem_Free(file->f_setbuf);\r
+ file->f_setbuf = NULL;\r
+ } else {\r
+ file->f_setbuf = (char *)PyMem_Realloc(file->f_setbuf,\r
+ bufsize);\r
+ }\r
+#ifdef HAVE_SETVBUF\r
+ setvbuf(file->f_fp, file->f_setbuf, type, bufsize);\r
+#else /* !HAVE_SETVBUF */\r
+ setbuf(file->f_fp, file->f_setbuf);\r
+#endif /* !HAVE_SETVBUF */\r
+ }\r
+}\r
+\r
+/* Set the encoding used to output Unicode strings.\r
+ Return 1 on success, 0 on failure. */\r
+\r
+int\r
+PyFile_SetEncoding(PyObject *f, const char *enc)\r
+{\r
+ return PyFile_SetEncodingAndErrors(f, enc, NULL);\r
+}\r
+\r
+int\r
+PyFile_SetEncodingAndErrors(PyObject *f, const char *enc, char* errors)\r
+{\r
+ PyFileObject *file = (PyFileObject*)f;\r
+ PyObject *str, *oerrors;\r
+\r
+ assert(PyFile_Check(f));\r
+ str = PyString_FromString(enc);\r
+ if (!str)\r
+ return 0;\r
+ if (errors) {\r
+ oerrors = PyString_FromString(errors);\r
+ if (!oerrors) {\r
+ Py_DECREF(str);\r
+ return 0;\r
+ }\r
+ } else {\r
+ oerrors = Py_None;\r
+ Py_INCREF(Py_None);\r
+ }\r
+ Py_DECREF(file->f_encoding);\r
+ file->f_encoding = str;\r
+ Py_DECREF(file->f_errors);\r
+ file->f_errors = oerrors;\r
+ return 1;\r
+}\r
+\r
+static PyObject *\r
+err_closed(void)\r
+{\r
+ PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+err_mode(char *action)\r
+{\r
+ PyErr_Format(PyExc_IOError, "File not open for %s", action);\r
+ return NULL;\r
+}\r
+\r
+/* Refuse regular file I/O if there's data in the iteration-buffer.\r
+ * Mixing them would cause data to arrive out of order, as the read*\r
+ * methods don't use the iteration buffer. */\r
+static PyObject *\r
+err_iterbuffered(void)\r
+{\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Mixing iteration and read methods would lose data");\r
+ return NULL;\r
+}\r
+\r
+static void drop_readahead(PyFileObject *);\r
+\r
+/* Methods */\r
+\r
+static void\r
+file_dealloc(PyFileObject *f)\r
+{\r
+ PyObject *ret;\r
+ if (f->weakreflist != NULL)\r
+ PyObject_ClearWeakRefs((PyObject *) f);\r
+ ret = close_the_file(f);\r
+ if (!ret) {\r
+ PySys_WriteStderr("close failed in file object destructor:\n");\r
+ PyErr_Print();\r
+ }\r
+ else {\r
+ Py_DECREF(ret);\r
+ }\r
+ PyMem_Free(f->f_setbuf);\r
+ Py_XDECREF(f->f_name);\r
+ Py_XDECREF(f->f_mode);\r
+ Py_XDECREF(f->f_encoding);\r
+ Py_XDECREF(f->f_errors);\r
+ drop_readahead(f);\r
+ Py_TYPE(f)->tp_free((PyObject *)f);\r
+}\r
+\r
+static PyObject *\r
+file_repr(PyFileObject *f)\r
+{\r
+ PyObject *ret = NULL;\r
+ PyObject *name = NULL;\r
+ if (PyUnicode_Check(f->f_name)) {\r
+#ifdef Py_USING_UNICODE\r
+ const char *name_str;\r
+ name = PyUnicode_AsUnicodeEscapeString(f->f_name);\r
+ name_str = name ? PyString_AsString(name) : "?";\r
+ ret = PyString_FromFormat("<%s file u'%s', mode '%s' at %p>",\r
+ f->f_fp == NULL ? "closed" : "open",\r
+ name_str,\r
+ PyString_AsString(f->f_mode),\r
+ f);\r
+ Py_XDECREF(name);\r
+ return ret;\r
+#endif\r
+ } else {\r
+ name = PyObject_Repr(f->f_name);\r
+ if (name == NULL)\r
+ return NULL;\r
+ ret = PyString_FromFormat("<%s file %s, mode '%s' at %p>",\r
+ f->f_fp == NULL ? "closed" : "open",\r
+ PyString_AsString(name),\r
+ PyString_AsString(f->f_mode),\r
+ f);\r
+ Py_XDECREF(name);\r
+ return ret;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+file_close(PyFileObject *f)\r
+{\r
+ PyObject *sts = close_the_file(f);\r
+ if (sts) {\r
+ PyMem_Free(f->f_setbuf);\r
+ f->f_setbuf = NULL;\r
+ }\r
+ return sts;\r
+}\r
+\r
+\r
+/* Our very own off_t-like type, 64-bit if possible */\r
+#if !defined(HAVE_LARGEFILE_SUPPORT)\r
+typedef off_t Py_off_t;\r
+#elif SIZEOF_OFF_T >= 8\r
+typedef off_t Py_off_t;\r
+#elif SIZEOF_FPOS_T >= 8\r
+typedef fpos_t Py_off_t;\r
+#else\r
+#error "Large file support, but neither off_t nor fpos_t is large enough."\r
+#endif\r
+\r
+\r
+/* a portable fseek() function\r
+ return 0 on success, non-zero on failure (with errno set) */\r
+static int\r
+_portable_fseek(FILE *fp, Py_off_t offset, int whence)\r
+{\r
+#if !defined(HAVE_LARGEFILE_SUPPORT)\r
+ return fseek(fp, offset, whence);\r
+#elif defined(HAVE_FSEEKO) && SIZEOF_OFF_T >= 8\r
+ return fseeko(fp, offset, whence);\r
+#elif defined(HAVE_FSEEK64)\r
+ return fseek64(fp, offset, whence);\r
+#elif defined(__BEOS__)\r
+ return _fseek(fp, offset, whence);\r
+#elif SIZEOF_FPOS_T >= 8\r
+ /* lacking a 64-bit capable fseek(), use a 64-bit capable fsetpos()\r
+ and fgetpos() to implement fseek()*/\r
+ fpos_t pos;\r
+ switch (whence) {\r
+ case SEEK_END:\r
+#ifdef MS_WINDOWS\r
+ fflush(fp);\r
+ if (_lseeki64(fileno(fp), 0, 2) == -1)\r
+ return -1;\r
+#else\r
+ if (fseek(fp, 0, SEEK_END) != 0)\r
+ return -1;\r
+#endif\r
+ /* fall through */\r
+ case SEEK_CUR:\r
+ if (fgetpos(fp, &pos) != 0)\r
+ return -1;\r
+ offset += pos;\r
+ break;\r
+ /* case SEEK_SET: break; */\r
+ }\r
+ return fsetpos(fp, &offset);\r
+#else\r
+#error "Large file support, but no way to fseek."\r
+#endif\r
+}\r
+\r
+\r
+/* a portable ftell() function\r
+ Return -1 on failure with errno set appropriately, current file\r
+ position on success */\r
+static Py_off_t\r
+_portable_ftell(FILE* fp)\r
+{\r
+#if !defined(HAVE_LARGEFILE_SUPPORT)\r
+ return ftell(fp);\r
+#elif defined(HAVE_FTELLO) && SIZEOF_OFF_T >= 8\r
+ return ftello(fp);\r
+#elif defined(HAVE_FTELL64)\r
+ return ftell64(fp);\r
+#elif SIZEOF_FPOS_T >= 8\r
+ fpos_t pos;\r
+ if (fgetpos(fp, &pos) != 0)\r
+ return -1;\r
+ return pos;\r
+#else\r
+#error "Large file support, but no way to ftell."\r
+#endif\r
+}\r
+\r
+\r
+static PyObject *\r
+file_seek(PyFileObject *f, PyObject *args)\r
+{\r
+ int whence;\r
+ int ret;\r
+ Py_off_t offset;\r
+ PyObject *offobj, *off_index;\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ drop_readahead(f);\r
+ whence = 0;\r
+ if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &whence))\r
+ return NULL;\r
+ off_index = PyNumber_Index(offobj);\r
+ if (!off_index) {\r
+ if (!PyFloat_Check(offobj))\r
+ return NULL;\r
+ /* Deprecated in 2.6 */\r
+ PyErr_Clear();\r
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,\r
+ "integer argument expected, got float",\r
+ 1) < 0)\r
+ return NULL;\r
+ off_index = offobj;\r
+ Py_INCREF(offobj);\r
+ }\r
+#if !defined(HAVE_LARGEFILE_SUPPORT)\r
+ offset = PyInt_AsLong(off_index);\r
+#else\r
+ offset = PyLong_Check(off_index) ?\r
+ PyLong_AsLongLong(off_index) : PyInt_AsLong(off_index);\r
+#endif\r
+ Py_DECREF(off_index);\r
+ if (PyErr_Occurred())\r
+ return NULL;\r
+\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ ret = _portable_fseek(f->f_fp, offset, whence);\r
+ FILE_END_ALLOW_THREADS(f)\r
+\r
+ if (ret != 0) {\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(f->f_fp);\r
+ return NULL;\r
+ }\r
+ f->f_skipnextlf = 0;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+\r
+#ifdef HAVE_FTRUNCATE\r
+static PyObject *\r
+file_truncate(PyFileObject *f, PyObject *args)\r
+{\r
+ Py_off_t newsize;\r
+ PyObject *newsizeobj = NULL;\r
+ Py_off_t initialpos;\r
+ int ret;\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ if (!f->writable)\r
+ return err_mode("writing");\r
+ if (!PyArg_UnpackTuple(args, "truncate", 0, 1, &newsizeobj))\r
+ return NULL;\r
+\r
+ /* Get current file position. If the file happens to be open for\r
+ * update and the last operation was an input operation, C doesn't\r
+ * define what the later fflush() will do, but we promise truncate()\r
+ * won't change the current position (and fflush() *does* change it\r
+ * then at least on Windows). The easiest thing is to capture\r
+ * current pos now and seek back to it at the end.\r
+ */\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ initialpos = _portable_ftell(f->f_fp);\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (initialpos == -1)\r
+ goto onioerror;\r
+\r
+ /* Set newsize to current postion if newsizeobj NULL, else to the\r
+ * specified value.\r
+ */\r
+ if (newsizeobj != NULL) {\r
+#if !defined(HAVE_LARGEFILE_SUPPORT)\r
+ newsize = PyInt_AsLong(newsizeobj);\r
+#else\r
+ newsize = PyLong_Check(newsizeobj) ?\r
+ PyLong_AsLongLong(newsizeobj) :\r
+ PyInt_AsLong(newsizeobj);\r
+#endif\r
+ if (PyErr_Occurred())\r
+ return NULL;\r
+ }\r
+ else /* default to current position */\r
+ newsize = initialpos;\r
+\r
+ /* Flush the stream. We're mixing stream-level I/O with lower-level\r
+ * I/O, and a flush may be necessary to synch both platform views\r
+ * of the current file state.\r
+ */\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ ret = fflush(f->f_fp);\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (ret != 0)\r
+ goto onioerror;\r
+\r
+#ifdef MS_WINDOWS\r
+ /* MS _chsize doesn't work if newsize doesn't fit in 32 bits,\r
+ so don't even try using it. */\r
+ {\r
+ HANDLE hFile;\r
+\r
+ /* Have to move current pos to desired endpoint on Windows. */\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ ret = _portable_fseek(f->f_fp, newsize, SEEK_SET) != 0;\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (ret)\r
+ goto onioerror;\r
+\r
+ /* Truncate. Note that this may grow the file! */\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp));\r
+ ret = hFile == (HANDLE)-1;\r
+ if (ret == 0) {\r
+ ret = SetEndOfFile(hFile) == 0;\r
+ if (ret)\r
+ errno = EACCES;\r
+ }\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (ret)\r
+ goto onioerror;\r
+ }\r
+#else\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ ret = ftruncate(fileno(f->f_fp), newsize);\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (ret != 0)\r
+ goto onioerror;\r
+#endif /* !MS_WINDOWS */\r
+\r
+ /* Restore original file position. */\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ ret = _portable_fseek(f->f_fp, initialpos, SEEK_SET) != 0;\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (ret)\r
+ goto onioerror;\r
+\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+\r
+onioerror:\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(f->f_fp);\r
+ return NULL;\r
+}\r
+#endif /* HAVE_FTRUNCATE */\r
+\r
+static PyObject *\r
+file_tell(PyFileObject *f)\r
+{\r
+ Py_off_t pos;\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ pos = _portable_ftell(f->f_fp);\r
+ FILE_END_ALLOW_THREADS(f)\r
+\r
+ if (pos == -1) {\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(f->f_fp);\r
+ return NULL;\r
+ }\r
+ if (f->f_skipnextlf) {\r
+ int c;\r
+ c = GETC(f->f_fp);\r
+ if (c == '\n') {\r
+ f->f_newlinetypes |= NEWLINE_CRLF;\r
+ pos++;\r
+ f->f_skipnextlf = 0;\r
+ } else if (c != EOF) ungetc(c, f->f_fp);\r
+ }\r
+#if !defined(HAVE_LARGEFILE_SUPPORT)\r
+ return PyInt_FromLong(pos);\r
+#else\r
+ return PyLong_FromLongLong(pos);\r
+#endif\r
+}\r
+\r
+static PyObject *\r
+file_fileno(PyFileObject *f)\r
+{\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ return PyInt_FromLong((long) fileno(f->f_fp));\r
+}\r
+\r
+static PyObject *\r
+file_flush(PyFileObject *f)\r
+{\r
+ int res;\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ res = fflush(f->f_fp);\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (res != 0) {\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(f->f_fp);\r
+ return NULL;\r
+ }\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+file_isatty(PyFileObject *f)\r
+{\r
+ long res;\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ res = isatty((int)fileno(f->f_fp));\r
+ FILE_END_ALLOW_THREADS(f)\r
+ return PyBool_FromLong(res);\r
+}\r
+\r
+\r
+#if BUFSIZ < 8192\r
+#define SMALLCHUNK 8192\r
+#else\r
+#define SMALLCHUNK BUFSIZ\r
+#endif\r
+\r
+static size_t\r
+new_buffersize(PyFileObject *f, size_t currentsize)\r
+{\r
+#ifdef HAVE_FSTAT\r
+ off_t pos, end;\r
+ struct stat st;\r
+ if (fstat(fileno(f->f_fp), &st) == 0) {\r
+ end = st.st_size;\r
+ /* The following is not a bug: we really need to call lseek()\r
+ *and* ftell(). The reason is that some stdio libraries\r
+ mistakenly flush their buffer when ftell() is called and\r
+ the lseek() call it makes fails, thereby throwing away\r
+ data that cannot be recovered in any way. To avoid this,\r
+ we first test lseek(), and only call ftell() if lseek()\r
+ works. We can't use the lseek() value either, because we\r
+ need to take the amount of buffered data into account.\r
+ (Yet another reason why stdio stinks. :-) */\r
+ pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR);\r
+ if (pos >= 0) {\r
+ pos = ftell(f->f_fp);\r
+ }\r
+ if (pos < 0)\r
+ clearerr(f->f_fp);\r
+ if (end > pos && pos >= 0)\r
+ return currentsize + end - pos + 1;\r
+ /* Add 1 so if the file were to grow we'd notice. */\r
+ }\r
+#endif\r
+ /* Expand the buffer by an amount proportional to the current size,\r
+ giving us amortized linear-time behavior. Use a less-than-double\r
+ growth factor to avoid excessive allocation. */\r
+ return currentsize + (currentsize >> 3) + 6;\r
+}\r
+\r
+#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN\r
+#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK || (x) == EAGAIN)\r
+#else\r
+#ifdef EWOULDBLOCK\r
+#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK)\r
+#else\r
+#ifdef EAGAIN\r
+#define BLOCKED_ERRNO(x) ((x) == EAGAIN)\r
+#else\r
+#define BLOCKED_ERRNO(x) 0\r
+#endif\r
+#endif\r
+#endif\r
+\r
+static PyObject *\r
+file_read(PyFileObject *f, PyObject *args)\r
+{\r
+ long bytesrequested = -1;\r
+ size_t bytesread, buffersize, chunksize;\r
+ PyObject *v;\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ if (!f->readable)\r
+ return err_mode("reading");\r
+ /* refuse to mix with f.next() */\r
+ if (f->f_buf != NULL &&\r
+ (f->f_bufend - f->f_bufptr) > 0 &&\r
+ f->f_buf[0] != '\0')\r
+ return err_iterbuffered();\r
+ if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))\r
+ return NULL;\r
+ if (bytesrequested < 0)\r
+ buffersize = new_buffersize(f, (size_t)0);\r
+ else\r
+ buffersize = bytesrequested;\r
+ if (buffersize > PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "requested number of bytes is more than a Python string can hold");\r
+ return NULL;\r
+ }\r
+ v = PyString_FromStringAndSize((char *)NULL, buffersize);\r
+ if (v == NULL)\r
+ return NULL;\r
+ bytesread = 0;\r
+ for (;;) {\r
+ int interrupted;\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ chunksize = Py_UniversalNewlineFread(BUF(v) + bytesread,\r
+ buffersize - bytesread, f->f_fp, (PyObject *)f);\r
+ interrupted = ferror(f->f_fp) && errno == EINTR;\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (interrupted) {\r
+ clearerr(f->f_fp);\r
+ if (PyErr_CheckSignals()) {\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ }\r
+ if (chunksize == 0) {\r
+ if (interrupted)\r
+ continue;\r
+ if (!ferror(f->f_fp))\r
+ break;\r
+ clearerr(f->f_fp);\r
+ /* When in non-blocking mode, data shouldn't\r
+ * be discarded if a blocking signal was\r
+ * received. That will also happen if\r
+ * chunksize != 0, but bytesread < buffersize. */\r
+ if (bytesread > 0 && BLOCKED_ERRNO(errno))\r
+ break;\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ bytesread += chunksize;\r
+ if (bytesread < buffersize && !interrupted) {\r
+ clearerr(f->f_fp);\r
+ break;\r
+ }\r
+ if (bytesrequested < 0) {\r
+ buffersize = new_buffersize(f, buffersize);\r
+ if (_PyString_Resize(&v, buffersize) < 0)\r
+ return NULL;\r
+ } else {\r
+ /* Got what was requested. */\r
+ break;\r
+ }\r
+ }\r
+ if (bytesread != buffersize && _PyString_Resize(&v, bytesread))\r
+ return NULL;\r
+ return v;\r
+}\r
+\r
+static PyObject *\r
+file_readinto(PyFileObject *f, PyObject *args)\r
+{\r
+ char *ptr;\r
+ Py_ssize_t ntodo;\r
+ Py_ssize_t ndone, nnow;\r
+ Py_buffer pbuf;\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ if (!f->readable)\r
+ return err_mode("reading");\r
+ /* refuse to mix with f.next() */\r
+ if (f->f_buf != NULL &&\r
+ (f->f_bufend - f->f_bufptr) > 0 &&\r
+ f->f_buf[0] != '\0')\r
+ return err_iterbuffered();\r
+ if (!PyArg_ParseTuple(args, "w*", &pbuf))\r
+ return NULL;\r
+ ptr = pbuf.buf;\r
+ ntodo = pbuf.len;\r
+ ndone = 0;\r
+ while (ntodo > 0) {\r
+ int interrupted;\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ nnow = Py_UniversalNewlineFread(ptr+ndone, ntodo, f->f_fp,\r
+ (PyObject *)f);\r
+ interrupted = ferror(f->f_fp) && errno == EINTR;\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (interrupted) {\r
+ clearerr(f->f_fp);\r
+ if (PyErr_CheckSignals()) {\r
+ PyBuffer_Release(&pbuf);\r
+ return NULL;\r
+ }\r
+ }\r
+ if (nnow == 0) {\r
+ if (interrupted)\r
+ continue;\r
+ if (!ferror(f->f_fp))\r
+ break;\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(f->f_fp);\r
+ PyBuffer_Release(&pbuf);\r
+ return NULL;\r
+ }\r
+ ndone += nnow;\r
+ ntodo -= nnow;\r
+ }\r
+ PyBuffer_Release(&pbuf);\r
+ return PyInt_FromSsize_t(ndone);\r
+}\r
+\r
+/**************************************************************************\r
+Routine to get next line using platform fgets().\r
+\r
+Under MSVC 6:\r
+\r
++ MS threadsafe getc is very slow (multiple layers of function calls before+\r
+ after each character, to lock+unlock the stream).\r
++ The stream-locking functions are MS-internal -- can't access them from user\r
+ code.\r
++ There's nothing Tim could find in the MS C or platform SDK libraries that\r
+ can worm around this.\r
++ MS fgets locks/unlocks only once per line; it's the only hook we have.\r
+\r
+So we use fgets for speed(!), despite that it's painful.\r
+\r
+MS realloc is also slow.\r
+\r
+Reports from other platforms on this method vs getc_unlocked (which MS doesn't\r
+have):\r
+ Linux a wash\r
+ Solaris a wash\r
+ Tru64 Unix getline_via_fgets significantly faster\r
+\r
+CAUTION: The C std isn't clear about this: in those cases where fgets\r
+writes something into the buffer, can it write into any position beyond the\r
+required trailing null byte? MSVC 6 fgets does not, and no platform is (yet)\r
+known on which it does; and it would be a strange way to code fgets. Still,\r
+getline_via_fgets may not work correctly if it does. The std test\r
+test_bufio.py should fail if platform fgets() routinely writes beyond the\r
+trailing null byte. #define DONT_USE_FGETS_IN_GETLINE to disable this code.\r
+**************************************************************************/\r
+\r
+/* Use this routine if told to, or by default on non-get_unlocked()\r
+ * platforms unless told not to. Yikes! Let's spell that out:\r
+ * On a platform with getc_unlocked():\r
+ * By default, use getc_unlocked().\r
+ * If you want to use fgets() instead, #define USE_FGETS_IN_GETLINE.\r
+ * On a platform without getc_unlocked():\r
+ * By default, use fgets().\r
+ * If you don't want to use fgets(), #define DONT_USE_FGETS_IN_GETLINE.\r
+ */\r
+#if !defined(USE_FGETS_IN_GETLINE) && !defined(HAVE_GETC_UNLOCKED)\r
+#define USE_FGETS_IN_GETLINE\r
+#endif\r
+\r
+#if defined(DONT_USE_FGETS_IN_GETLINE) && defined(USE_FGETS_IN_GETLINE)\r
+#undef USE_FGETS_IN_GETLINE\r
+#endif\r
+\r
+#ifdef USE_FGETS_IN_GETLINE\r
+static PyObject*\r
+getline_via_fgets(PyFileObject *f, FILE *fp)\r
+{\r
+/* INITBUFSIZE is the maximum line length that lets us get away with the fast\r
+ * no-realloc, one-fgets()-call path. Boosting it isn't free, because we have\r
+ * to fill this much of the buffer with a known value in order to figure out\r
+ * how much of the buffer fgets() overwrites. So if INITBUFSIZE is larger\r
+ * than "most" lines, we waste time filling unused buffer slots. 100 is\r
+ * surely adequate for most peoples' email archives, chewing over source code,\r
+ * etc -- "regular old text files".\r
+ * MAXBUFSIZE is the maximum line length that lets us get away with the less\r
+ * fast (but still zippy) no-realloc, two-fgets()-call path. See above for\r
+ * cautions about boosting that. 300 was chosen because the worst real-life\r
+ * text-crunching job reported on Python-Dev was a mail-log crawler where over\r
+ * half the lines were 254 chars.\r
+ */\r
+#define INITBUFSIZE 100\r
+#define MAXBUFSIZE 300\r
+ char* p; /* temp */\r
+ char buf[MAXBUFSIZE];\r
+ PyObject* v; /* the string object result */\r
+ char* pvfree; /* address of next free slot */\r
+ char* pvend; /* address one beyond last free slot */\r
+ size_t nfree; /* # of free buffer slots; pvend-pvfree */\r
+ size_t total_v_size; /* total # of slots in buffer */\r
+ size_t increment; /* amount to increment the buffer */\r
+ size_t prev_v_size;\r
+\r
+ /* Optimize for normal case: avoid _PyString_Resize if at all\r
+ * possible via first reading into stack buffer "buf".\r
+ */\r
+ total_v_size = INITBUFSIZE; /* start small and pray */\r
+ pvfree = buf;\r
+ for (;;) {\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ pvend = buf + total_v_size;\r
+ nfree = pvend - pvfree;\r
+ memset(pvfree, '\n', nfree);\r
+ assert(nfree < INT_MAX); /* Should be atmost MAXBUFSIZE */\r
+ p = fgets(pvfree, (int)nfree, fp);\r
+ FILE_END_ALLOW_THREADS(f)\r
+\r
+ if (p == NULL) {\r
+ clearerr(fp);\r
+ if (PyErr_CheckSignals())\r
+ return NULL;\r
+ v = PyString_FromStringAndSize(buf, pvfree - buf);\r
+ return v;\r
+ }\r
+ /* fgets read *something* */\r
+ p = memchr(pvfree, '\n', nfree);\r
+ if (p != NULL) {\r
+ /* Did the \n come from fgets or from us?\r
+ * Since fgets stops at the first \n, and then writes\r
+ * \0, if it's from fgets a \0 must be next. But if\r
+ * that's so, it could not have come from us, since\r
+ * the \n's we filled the buffer with have only more\r
+ * \n's to the right.\r
+ */\r
+ if (p+1 < pvend && *(p+1) == '\0') {\r
+ /* It's from fgets: we win! In particular,\r
+ * we haven't done any mallocs yet, and can\r
+ * build the final result on the first try.\r
+ */\r
+ ++p; /* include \n from fgets */\r
+ }\r
+ else {\r
+ /* Must be from us: fgets didn't fill the\r
+ * buffer and didn't find a newline, so it\r
+ * must be the last and newline-free line of\r
+ * the file.\r
+ */\r
+ assert(p > pvfree && *(p-1) == '\0');\r
+ --p; /* don't include \0 from fgets */\r
+ }\r
+ v = PyString_FromStringAndSize(buf, p - buf);\r
+ return v;\r
+ }\r
+ /* yuck: fgets overwrote all the newlines, i.e. the entire\r
+ * buffer. So this line isn't over yet, or maybe it is but\r
+ * we're exactly at EOF. If we haven't already, try using the\r
+ * rest of the stack buffer.\r
+ */\r
+ assert(*(pvend-1) == '\0');\r
+ if (pvfree == buf) {\r
+ pvfree = pvend - 1; /* overwrite trailing null */\r
+ total_v_size = MAXBUFSIZE;\r
+ }\r
+ else\r
+ break;\r
+ }\r
+\r
+ /* The stack buffer isn't big enough; malloc a string object and read\r
+ * into its buffer.\r
+ */\r
+ total_v_size = MAXBUFSIZE << 1;\r
+ v = PyString_FromStringAndSize((char*)NULL, (int)total_v_size);\r
+ if (v == NULL)\r
+ return v;\r
+ /* copy over everything except the last null byte */\r
+ memcpy(BUF(v), buf, MAXBUFSIZE-1);\r
+ pvfree = BUF(v) + MAXBUFSIZE - 1;\r
+\r
+ /* Keep reading stuff into v; if it ever ends successfully, break\r
+ * after setting p one beyond the end of the line. The code here is\r
+ * very much like the code above, except reads into v's buffer; see\r
+ * the code above for detailed comments about the logic.\r
+ */\r
+ for (;;) {\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ pvend = BUF(v) + total_v_size;\r
+ nfree = pvend - pvfree;\r
+ memset(pvfree, '\n', nfree);\r
+ assert(nfree < INT_MAX);\r
+ p = fgets(pvfree, (int)nfree, fp);\r
+ FILE_END_ALLOW_THREADS(f)\r
+\r
+ if (p == NULL) {\r
+ clearerr(fp);\r
+ if (PyErr_CheckSignals()) {\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ p = pvfree;\r
+ break;\r
+ }\r
+ p = memchr(pvfree, '\n', nfree);\r
+ if (p != NULL) {\r
+ if (p+1 < pvend && *(p+1) == '\0') {\r
+ /* \n came from fgets */\r
+ ++p;\r
+ break;\r
+ }\r
+ /* \n came from us; last line of file, no newline */\r
+ assert(p > pvfree && *(p-1) == '\0');\r
+ --p;\r
+ break;\r
+ }\r
+ /* expand buffer and try again */\r
+ assert(*(pvend-1) == '\0');\r
+ increment = total_v_size >> 2; /* mild exponential growth */\r
+ prev_v_size = total_v_size;\r
+ total_v_size += increment;\r
+ /* check for overflow */\r
+ if (total_v_size <= prev_v_size ||\r
+ total_v_size > PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "line is longer than a Python string can hold");\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ if (_PyString_Resize(&v, (int)total_v_size) < 0)\r
+ return NULL;\r
+ /* overwrite the trailing null byte */\r
+ pvfree = BUF(v) + (prev_v_size - 1);\r
+ }\r
+ if (BUF(v) + total_v_size != p && _PyString_Resize(&v, p - BUF(v)))\r
+ return NULL;\r
+ return v;\r
+#undef INITBUFSIZE\r
+#undef MAXBUFSIZE\r
+}\r
+#endif /* ifdef USE_FGETS_IN_GETLINE */\r
+\r
+/* Internal routine to get a line.\r
+ Size argument interpretation:\r
+ > 0: max length;\r
+ <= 0: read arbitrary line\r
+*/\r
+\r
+static PyObject *\r
+get_line(PyFileObject *f, int n)\r
+{\r
+ FILE *fp = f->f_fp;\r
+ int c;\r
+ char *buf, *end;\r
+ size_t total_v_size; /* total # of slots in buffer */\r
+ size_t used_v_size; /* # used slots in buffer */\r
+ size_t increment; /* amount to increment the buffer */\r
+ PyObject *v;\r
+ int newlinetypes = f->f_newlinetypes;\r
+ int skipnextlf = f->f_skipnextlf;\r
+ int univ_newline = f->f_univ_newline;\r
+\r
+#if defined(USE_FGETS_IN_GETLINE)\r
+ if (n <= 0 && !univ_newline )\r
+ return getline_via_fgets(f, fp);\r
+#endif\r
+ total_v_size = n > 0 ? n : 100;\r
+ v = PyString_FromStringAndSize((char *)NULL, total_v_size);\r
+ if (v == NULL)\r
+ return NULL;\r
+ buf = BUF(v);\r
+ end = buf + total_v_size;\r
+\r
+ for (;;) {\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ FLOCKFILE(fp);\r
+ if (univ_newline) {\r
+ c = 'x'; /* Shut up gcc warning */\r
+ while ( buf != end && (c = GETC(fp)) != EOF ) {\r
+ if (skipnextlf ) {\r
+ skipnextlf = 0;\r
+ if (c == '\n') {\r
+ /* Seeing a \n here with\r
+ * skipnextlf true means we\r
+ * saw a \r before.\r
+ */\r
+ newlinetypes |= NEWLINE_CRLF;\r
+ c = GETC(fp);\r
+ if (c == EOF) break;\r
+ } else {\r
+ newlinetypes |= NEWLINE_CR;\r
+ }\r
+ }\r
+ if (c == '\r') {\r
+ skipnextlf = 1;\r
+ c = '\n';\r
+ } else if ( c == '\n')\r
+ newlinetypes |= NEWLINE_LF;\r
+ *buf++ = c;\r
+ if (c == '\n') break;\r
+ }\r
+ if (c == EOF) {\r
+ if (ferror(fp) && errno == EINTR) {\r
+ FUNLOCKFILE(fp);\r
+ FILE_ABORT_ALLOW_THREADS(f)\r
+ f->f_newlinetypes = newlinetypes;\r
+ f->f_skipnextlf = skipnextlf;\r
+\r
+ if (PyErr_CheckSignals()) {\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ /* We executed Python signal handlers and got no exception.\r
+ * Now back to reading the line where we left off. */\r
+ clearerr(fp);\r
+ continue;\r
+ }\r
+ if (skipnextlf)\r
+ newlinetypes |= NEWLINE_CR;\r
+ }\r
+ } else /* If not universal newlines use the normal loop */\r
+ while ((c = GETC(fp)) != EOF &&\r
+ (*buf++ = c) != '\n' &&\r
+ buf != end)\r
+ ;\r
+ FUNLOCKFILE(fp);\r
+ FILE_END_ALLOW_THREADS(f)\r
+ f->f_newlinetypes = newlinetypes;\r
+ f->f_skipnextlf = skipnextlf;\r
+ if (c == '\n')\r
+ break;\r
+ if (c == EOF) {\r
+ if (ferror(fp)) {\r
+ if (errno == EINTR) {\r
+ if (PyErr_CheckSignals()) {\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ /* We executed Python signal handlers and got no exception.\r
+ * Now back to reading the line where we left off. */\r
+ clearerr(fp);\r
+ continue;\r
+ }\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(fp);\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ clearerr(fp);\r
+ if (PyErr_CheckSignals()) {\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ break;\r
+ }\r
+ /* Must be because buf == end */\r
+ if (n > 0)\r
+ break;\r
+ used_v_size = total_v_size;\r
+ increment = total_v_size >> 2; /* mild exponential growth */\r
+ total_v_size += increment;\r
+ if (total_v_size > PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "line is longer than a Python string can hold");\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ if (_PyString_Resize(&v, total_v_size) < 0)\r
+ return NULL;\r
+ buf = BUF(v) + used_v_size;\r
+ end = BUF(v) + total_v_size;\r
+ }\r
+\r
+ used_v_size = buf - BUF(v);\r
+ if (used_v_size != total_v_size && _PyString_Resize(&v, used_v_size))\r
+ return NULL;\r
+ return v;\r
+}\r
+\r
+/* External C interface */\r
+\r
+PyObject *\r
+PyFile_GetLine(PyObject *f, int n)\r
+{\r
+ PyObject *result;\r
+\r
+ if (f == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+\r
+ if (PyFile_Check(f)) {\r
+ PyFileObject *fo = (PyFileObject *)f;\r
+ if (fo->f_fp == NULL)\r
+ return err_closed();\r
+ if (!fo->readable)\r
+ return err_mode("reading");\r
+ /* refuse to mix with f.next() */\r
+ if (fo->f_buf != NULL &&\r
+ (fo->f_bufend - fo->f_bufptr) > 0 &&\r
+ fo->f_buf[0] != '\0')\r
+ return err_iterbuffered();\r
+ result = get_line(fo, n);\r
+ }\r
+ else {\r
+ PyObject *reader;\r
+ PyObject *args;\r
+\r
+ reader = PyObject_GetAttrString(f, "readline");\r
+ if (reader == NULL)\r
+ return NULL;\r
+ if (n <= 0)\r
+ args = PyTuple_New(0);\r
+ else\r
+ args = Py_BuildValue("(i)", n);\r
+ if (args == NULL) {\r
+ Py_DECREF(reader);\r
+ return NULL;\r
+ }\r
+ result = PyEval_CallObject(reader, args);\r
+ Py_DECREF(reader);\r
+ Py_DECREF(args);\r
+ if (result != NULL && !PyString_Check(result) &&\r
+ !PyUnicode_Check(result)) {\r
+ Py_DECREF(result);\r
+ result = NULL;\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "object.readline() returned non-string");\r
+ }\r
+ }\r
+\r
+ if (n < 0 && result != NULL && PyString_Check(result)) {\r
+ char *s = PyString_AS_STRING(result);\r
+ Py_ssize_t len = PyString_GET_SIZE(result);\r
+ if (len == 0) {\r
+ Py_DECREF(result);\r
+ result = NULL;\r
+ PyErr_SetString(PyExc_EOFError,\r
+ "EOF when reading a line");\r
+ }\r
+ else if (s[len-1] == '\n') {\r
+ if (result->ob_refcnt == 1) {\r
+ if (_PyString_Resize(&result, len-1))\r
+ return NULL;\r
+ }\r
+ else {\r
+ PyObject *v;\r
+ v = PyString_FromStringAndSize(s, len-1);\r
+ Py_DECREF(result);\r
+ result = v;\r
+ }\r
+ }\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ if (n < 0 && result != NULL && PyUnicode_Check(result)) {\r
+ Py_UNICODE *s = PyUnicode_AS_UNICODE(result);\r
+ Py_ssize_t len = PyUnicode_GET_SIZE(result);\r
+ if (len == 0) {\r
+ Py_DECREF(result);\r
+ result = NULL;\r
+ PyErr_SetString(PyExc_EOFError,\r
+ "EOF when reading a line");\r
+ }\r
+ else if (s[len-1] == '\n') {\r
+ if (result->ob_refcnt == 1)\r
+ PyUnicode_Resize(&result, len-1);\r
+ else {\r
+ PyObject *v;\r
+ v = PyUnicode_FromUnicode(s, len-1);\r
+ Py_DECREF(result);\r
+ result = v;\r
+ }\r
+ }\r
+ }\r
+#endif\r
+ return result;\r
+}\r
+\r
+/* Python method */\r
+\r
+static PyObject *\r
+file_readline(PyFileObject *f, PyObject *args)\r
+{\r
+ int n = -1;\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ if (!f->readable)\r
+ return err_mode("reading");\r
+ /* refuse to mix with f.next() */\r
+ if (f->f_buf != NULL &&\r
+ (f->f_bufend - f->f_bufptr) > 0 &&\r
+ f->f_buf[0] != '\0')\r
+ return err_iterbuffered();\r
+ if (!PyArg_ParseTuple(args, "|i:readline", &n))\r
+ return NULL;\r
+ if (n == 0)\r
+ return PyString_FromString("");\r
+ if (n < 0)\r
+ n = 0;\r
+ return get_line(f, n);\r
+}\r
+\r
+static PyObject *\r
+file_readlines(PyFileObject *f, PyObject *args)\r
+{\r
+ long sizehint = 0;\r
+ PyObject *list = NULL;\r
+ PyObject *line;\r
+ char small_buffer[SMALLCHUNK];\r
+ char *buffer = small_buffer;\r
+ size_t buffersize = SMALLCHUNK;\r
+ PyObject *big_buffer = NULL;\r
+ size_t nfilled = 0;\r
+ size_t nread;\r
+ size_t totalread = 0;\r
+ char *p, *q, *end;\r
+ int err;\r
+ int shortread = 0; /* bool, did the previous read come up short? */\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ if (!f->readable)\r
+ return err_mode("reading");\r
+ /* refuse to mix with f.next() */\r
+ if (f->f_buf != NULL &&\r
+ (f->f_bufend - f->f_bufptr) > 0 &&\r
+ f->f_buf[0] != '\0')\r
+ return err_iterbuffered();\r
+ if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))\r
+ return NULL;\r
+ if ((list = PyList_New(0)) == NULL)\r
+ return NULL;\r
+ for (;;) {\r
+ if (shortread)\r
+ nread = 0;\r
+ else {\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ nread = Py_UniversalNewlineFread(buffer+nfilled,\r
+ buffersize-nfilled, f->f_fp, (PyObject *)f);\r
+ FILE_END_ALLOW_THREADS(f)\r
+ shortread = (nread < buffersize-nfilled);\r
+ }\r
+ if (nread == 0) {\r
+ sizehint = 0;\r
+ if (!ferror(f->f_fp))\r
+ break;\r
+ if (errno == EINTR) {\r
+ if (PyErr_CheckSignals()) {\r
+ goto error;\r
+ }\r
+ clearerr(f->f_fp);\r
+ shortread = 0;\r
+ continue;\r
+ }\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(f->f_fp);\r
+ goto error;\r
+ }\r
+ totalread += nread;\r
+ p = (char *)memchr(buffer+nfilled, '\n', nread);\r
+ if (p == NULL) {\r
+ /* Need a larger buffer to fit this line */\r
+ nfilled += nread;\r
+ buffersize *= 2;\r
+ if (buffersize > PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "line is longer than a Python string can hold");\r
+ goto error;\r
+ }\r
+ if (big_buffer == NULL) {\r
+ /* Create the big buffer */\r
+ big_buffer = PyString_FromStringAndSize(\r
+ NULL, buffersize);\r
+ if (big_buffer == NULL)\r
+ goto error;\r
+ buffer = PyString_AS_STRING(big_buffer);\r
+ memcpy(buffer, small_buffer, nfilled);\r
+ }\r
+ else {\r
+ /* Grow the big buffer */\r
+ if ( _PyString_Resize(&big_buffer, buffersize) < 0 )\r
+ goto error;\r
+ buffer = PyString_AS_STRING(big_buffer);\r
+ }\r
+ continue;\r
+ }\r
+ end = buffer+nfilled+nread;\r
+ q = buffer;\r
+ do {\r
+ /* Process complete lines */\r
+ p++;\r
+ line = PyString_FromStringAndSize(q, p-q);\r
+ if (line == NULL)\r
+ goto error;\r
+ err = PyList_Append(list, line);\r
+ Py_DECREF(line);\r
+ if (err != 0)\r
+ goto error;\r
+ q = p;\r
+ p = (char *)memchr(q, '\n', end-q);\r
+ } while (p != NULL);\r
+ /* Move the remaining incomplete line to the start */\r
+ nfilled = end-q;\r
+ memmove(buffer, q, nfilled);\r
+ if (sizehint > 0)\r
+ if (totalread >= (size_t)sizehint)\r
+ break;\r
+ }\r
+ if (nfilled != 0) {\r
+ /* Partial last line */\r
+ line = PyString_FromStringAndSize(buffer, nfilled);\r
+ if (line == NULL)\r
+ goto error;\r
+ if (sizehint > 0) {\r
+ /* Need to complete the last line */\r
+ PyObject *rest = get_line(f, 0);\r
+ if (rest == NULL) {\r
+ Py_DECREF(line);\r
+ goto error;\r
+ }\r
+ PyString_Concat(&line, rest);\r
+ Py_DECREF(rest);\r
+ if (line == NULL)\r
+ goto error;\r
+ }\r
+ err = PyList_Append(list, line);\r
+ Py_DECREF(line);\r
+ if (err != 0)\r
+ goto error;\r
+ }\r
+\r
+cleanup:\r
+ Py_XDECREF(big_buffer);\r
+ return list;\r
+\r
+error:\r
+ Py_CLEAR(list);\r
+ goto cleanup;\r
+}\r
+\r
+static PyObject *\r
+file_write(PyFileObject *f, PyObject *args)\r
+{\r
+ Py_buffer pbuf;\r
+ const char *s;\r
+ Py_ssize_t n, n2;\r
+ PyObject *encoded = NULL;\r
+ int err_flag = 0, err;\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ if (!f->writable)\r
+ return err_mode("writing");\r
+ if (f->f_binary) {\r
+ if (!PyArg_ParseTuple(args, "s*", &pbuf))\r
+ return NULL;\r
+ s = pbuf.buf;\r
+ n = pbuf.len;\r
+ }\r
+ else {\r
+ PyObject *text;\r
+ if (!PyArg_ParseTuple(args, "O", &text))\r
+ return NULL;\r
+\r
+ if (PyString_Check(text)) {\r
+ s = PyString_AS_STRING(text);\r
+ n = PyString_GET_SIZE(text);\r
+#ifdef Py_USING_UNICODE\r
+ } else if (PyUnicode_Check(text)) {\r
+ const char *encoding, *errors;\r
+ if (f->f_encoding != Py_None)\r
+ encoding = PyString_AS_STRING(f->f_encoding);\r
+ else\r
+ encoding = PyUnicode_GetDefaultEncoding();\r
+ if (f->f_errors != Py_None)\r
+ errors = PyString_AS_STRING(f->f_errors);\r
+ else\r
+ errors = "strict";\r
+ encoded = PyUnicode_AsEncodedString(text, encoding, errors);\r
+ if (encoded == NULL)\r
+ return NULL;\r
+ s = PyString_AS_STRING(encoded);\r
+ n = PyString_GET_SIZE(encoded);\r
+#endif\r
+ } else {\r
+ if (PyObject_AsCharBuffer(text, &s, &n))\r
+ return NULL;\r
+ }\r
+ }\r
+ f->f_softspace = 0;\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ n2 = fwrite(s, 1, n, f->f_fp);\r
+ if (n2 != n || ferror(f->f_fp)) {\r
+ err_flag = 1;\r
+ err = errno;\r
+ }\r
+ FILE_END_ALLOW_THREADS(f)\r
+ Py_XDECREF(encoded);\r
+ if (f->f_binary)\r
+ PyBuffer_Release(&pbuf);\r
+ if (err_flag) {\r
+ errno = err;\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(f->f_fp);\r
+ return NULL;\r
+ }\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+file_writelines(PyFileObject *f, PyObject *seq)\r
+{\r
+#define CHUNKSIZE 1000\r
+ PyObject *list, *line;\r
+ PyObject *it; /* iter(seq) */\r
+ PyObject *result;\r
+ int index, islist;\r
+ Py_ssize_t i, j, nwritten, len;\r
+\r
+ assert(seq != NULL);\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ if (!f->writable)\r
+ return err_mode("writing");\r
+\r
+ result = NULL;\r
+ list = NULL;\r
+ islist = PyList_Check(seq);\r
+ if (islist)\r
+ it = NULL;\r
+ else {\r
+ it = PyObject_GetIter(seq);\r
+ if (it == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "writelines() requires an iterable argument");\r
+ return NULL;\r
+ }\r
+ /* From here on, fail by going to error, to reclaim "it". */\r
+ list = PyList_New(CHUNKSIZE);\r
+ if (list == NULL)\r
+ goto error;\r
+ }\r
+\r
+ /* Strategy: slurp CHUNKSIZE lines into a private list,\r
+ checking that they are all strings, then write that list\r
+ without holding the interpreter lock, then come back for more. */\r
+ for (index = 0; ; index += CHUNKSIZE) {\r
+ if (islist) {\r
+ Py_XDECREF(list);\r
+ list = PyList_GetSlice(seq, index, index+CHUNKSIZE);\r
+ if (list == NULL)\r
+ goto error;\r
+ j = PyList_GET_SIZE(list);\r
+ }\r
+ else {\r
+ for (j = 0; j < CHUNKSIZE; j++) {\r
+ line = PyIter_Next(it);\r
+ if (line == NULL) {\r
+ if (PyErr_Occurred())\r
+ goto error;\r
+ break;\r
+ }\r
+ PyList_SetItem(list, j, line);\r
+ }\r
+ /* The iterator might have closed the file on us. */\r
+ if (f->f_fp == NULL) {\r
+ err_closed();\r
+ goto error;\r
+ }\r
+ }\r
+ if (j == 0)\r
+ break;\r
+\r
+ /* Check that all entries are indeed strings. If not,\r
+ apply the same rules as for file.write() and\r
+ convert the results to strings. This is slow, but\r
+ seems to be the only way since all conversion APIs\r
+ could potentially execute Python code. */\r
+ for (i = 0; i < j; i++) {\r
+ PyObject *v = PyList_GET_ITEM(list, i);\r
+ if (!PyString_Check(v)) {\r
+ const char *buffer;\r
+ int res;\r
+ if (f->f_binary) {\r
+ res = PyObject_AsReadBuffer(v, (const void**)&buffer, &len);\r
+ } else {\r
+ res = PyObject_AsCharBuffer(v, &buffer, &len);\r
+ }\r
+ if (res) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "writelines() argument must be a sequence of strings");\r
+ goto error;\r
+ }\r
+ line = PyString_FromStringAndSize(buffer,\r
+ len);\r
+ if (line == NULL)\r
+ goto error;\r
+ Py_DECREF(v);\r
+ PyList_SET_ITEM(list, i, line);\r
+ }\r
+ }\r
+\r
+ /* Since we are releasing the global lock, the\r
+ following code may *not* execute Python code. */\r
+ f->f_softspace = 0;\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ for (i = 0; i < j; i++) {\r
+ line = PyList_GET_ITEM(list, i);\r
+ len = PyString_GET_SIZE(line);\r
+ nwritten = fwrite(PyString_AS_STRING(line),\r
+ 1, len, f->f_fp);\r
+ if (nwritten != len) {\r
+ FILE_ABORT_ALLOW_THREADS(f)\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(f->f_fp);\r
+ goto error;\r
+ }\r
+ }\r
+ FILE_END_ALLOW_THREADS(f)\r
+\r
+ if (j < CHUNKSIZE)\r
+ break;\r
+ }\r
+\r
+ Py_INCREF(Py_None);\r
+ result = Py_None;\r
+ error:\r
+ Py_XDECREF(list);\r
+ Py_XDECREF(it);\r
+ return result;\r
+#undef CHUNKSIZE\r
+}\r
+\r
+static PyObject *\r
+file_self(PyFileObject *f)\r
+{\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ Py_INCREF(f);\r
+ return (PyObject *)f;\r
+}\r
+\r
+static PyObject *\r
+file_xreadlines(PyFileObject *f)\r
+{\r
+ if (PyErr_WarnPy3k("f.xreadlines() not supported in 3.x, "\r
+ "try 'for line in f' instead", 1) < 0)\r
+ return NULL;\r
+ return file_self(f);\r
+}\r
+\r
+static PyObject *\r
+file_exit(PyObject *f, PyObject *args)\r
+{\r
+ PyObject *ret = PyObject_CallMethod(f, "close", NULL);\r
+ if (!ret)\r
+ /* If error occurred, pass through */\r
+ return NULL;\r
+ Py_DECREF(ret);\r
+ /* We cannot return the result of close since a true\r
+ * value will be interpreted as "yes, swallow the\r
+ * exception if one was raised inside the with block". */\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(readline_doc,\r
+"readline([size]) -> next line from the file, as a string.\n"\r
+"\n"\r
+"Retain newline. A non-negative size argument limits the maximum\n"\r
+"number of bytes to return (an incomplete line may be returned then).\n"\r
+"Return an empty string at EOF.");\r
+\r
+PyDoc_STRVAR(read_doc,\r
+"read([size]) -> read at most size bytes, returned as a string.\n"\r
+"\n"\r
+"If the size argument is negative or omitted, read until EOF is reached.\n"\r
+"Notice that when in non-blocking mode, less data than what was requested\n"\r
+"may be returned, even if no size parameter was given.");\r
+\r
+PyDoc_STRVAR(write_doc,\r
+"write(str) -> None. Write string str to file.\n"\r
+"\n"\r
+"Note that due to buffering, flush() or close() may be needed before\n"\r
+"the file on disk reflects the data written.");\r
+\r
+PyDoc_STRVAR(fileno_doc,\r
+"fileno() -> integer \"file descriptor\".\n"\r
+"\n"\r
+"This is needed for lower-level file interfaces, such os.read().");\r
+\r
+PyDoc_STRVAR(seek_doc,\r
+"seek(offset[, whence]) -> None. Move to new file position.\n"\r
+"\n"\r
+"Argument offset is a byte count. Optional argument whence defaults to\n"\r
+"0 (offset from start of file, offset should be >= 0); other values are 1\n"\r
+"(move relative to current position, positive or negative), and 2 (move\n"\r
+"relative to end of file, usually negative, although many platforms allow\n"\r
+"seeking beyond the end of a file). If the file is opened in text mode,\n"\r
+"only offsets returned by tell() are legal. Use of other offsets causes\n"\r
+"undefined behavior."\r
+"\n"\r
+"Note that not all file objects are seekable.");\r
+\r
+#ifdef HAVE_FTRUNCATE\r
+PyDoc_STRVAR(truncate_doc,\r
+"truncate([size]) -> None. Truncate the file to at most size bytes.\n"\r
+"\n"\r
+"Size defaults to the current file position, as returned by tell().");\r
+#endif\r
+\r
+PyDoc_STRVAR(tell_doc,\r
+"tell() -> current file position, an integer (may be a long integer).");\r
+\r
+PyDoc_STRVAR(readinto_doc,\r
+"readinto() -> Undocumented. Don't use this; it may go away.");\r
+\r
+PyDoc_STRVAR(readlines_doc,\r
+"readlines([size]) -> list of strings, each a line from the file.\n"\r
+"\n"\r
+"Call readline() repeatedly and return a list of the lines so read.\n"\r
+"The optional size argument, if given, is an approximate bound on the\n"\r
+"total number of bytes in the lines returned.");\r
+\r
+PyDoc_STRVAR(xreadlines_doc,\r
+"xreadlines() -> returns self.\n"\r
+"\n"\r
+"For backward compatibility. File objects now include the performance\n"\r
+"optimizations previously implemented in the xreadlines module.");\r
+\r
+PyDoc_STRVAR(writelines_doc,\r
+"writelines(sequence_of_strings) -> None. Write the strings to the file.\n"\r
+"\n"\r
+"Note that newlines are not added. The sequence can be any iterable object\n"\r
+"producing strings. This is equivalent to calling write() for each string.");\r
+\r
+PyDoc_STRVAR(flush_doc,\r
+"flush() -> None. Flush the internal I/O buffer.");\r
+\r
+PyDoc_STRVAR(close_doc,\r
+"close() -> None or (perhaps) an integer. Close the file.\n"\r
+"\n"\r
+"Sets data attribute .closed to True. A closed file cannot be used for\n"\r
+"further I/O operations. close() may be called more than once without\n"\r
+"error. Some kinds of file objects (for example, opened by popen())\n"\r
+"may return an exit status upon closing.");\r
+\r
+PyDoc_STRVAR(isatty_doc,\r
+"isatty() -> true or false. True if the file is connected to a tty device.");\r
+\r
+PyDoc_STRVAR(enter_doc,\r
+ "__enter__() -> self.");\r
+\r
+PyDoc_STRVAR(exit_doc,\r
+ "__exit__(*excinfo) -> None. Closes the file.");\r
+\r
+static PyMethodDef file_methods[] = {\r
+ {"readline", (PyCFunction)file_readline, METH_VARARGS, readline_doc},\r
+ {"read", (PyCFunction)file_read, METH_VARARGS, read_doc},\r
+ {"write", (PyCFunction)file_write, METH_VARARGS, write_doc},\r
+ {"fileno", (PyCFunction)file_fileno, METH_NOARGS, fileno_doc},\r
+ {"seek", (PyCFunction)file_seek, METH_VARARGS, seek_doc},\r
+#ifdef HAVE_FTRUNCATE\r
+ {"truncate", (PyCFunction)file_truncate, METH_VARARGS, truncate_doc},\r
+#endif\r
+ {"tell", (PyCFunction)file_tell, METH_NOARGS, tell_doc},\r
+ {"readinto", (PyCFunction)file_readinto, METH_VARARGS, readinto_doc},\r
+ {"readlines", (PyCFunction)file_readlines, METH_VARARGS, readlines_doc},\r
+ {"xreadlines",(PyCFunction)file_xreadlines, METH_NOARGS, xreadlines_doc},\r
+ {"writelines",(PyCFunction)file_writelines, METH_O, writelines_doc},\r
+ {"flush", (PyCFunction)file_flush, METH_NOARGS, flush_doc},\r
+ {"close", (PyCFunction)file_close, METH_NOARGS, close_doc},\r
+ {"isatty", (PyCFunction)file_isatty, METH_NOARGS, isatty_doc},\r
+ {"__enter__", (PyCFunction)file_self, METH_NOARGS, enter_doc},\r
+ {"__exit__", (PyCFunction)file_exit, METH_VARARGS, exit_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+#define OFF(x) offsetof(PyFileObject, x)\r
+\r
+static PyMemberDef file_memberlist[] = {\r
+ {"mode", T_OBJECT, OFF(f_mode), RO,\r
+ "file mode ('r', 'U', 'w', 'a', possibly with 'b' or '+' added)"},\r
+ {"name", T_OBJECT, OFF(f_name), RO,\r
+ "file name"},\r
+ {"encoding", T_OBJECT, OFF(f_encoding), RO,\r
+ "file encoding"},\r
+ {"errors", T_OBJECT, OFF(f_errors), RO,\r
+ "Unicode error handler"},\r
+ /* getattr(f, "closed") is implemented without this table */\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+static PyObject *\r
+get_closed(PyFileObject *f, void *closure)\r
+{\r
+ return PyBool_FromLong((long)(f->f_fp == 0));\r
+}\r
+static PyObject *\r
+get_newlines(PyFileObject *f, void *closure)\r
+{\r
+ switch (f->f_newlinetypes) {\r
+ case NEWLINE_UNKNOWN:\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ case NEWLINE_CR:\r
+ return PyString_FromString("\r");\r
+ case NEWLINE_LF:\r
+ return PyString_FromString("\n");\r
+ case NEWLINE_CR|NEWLINE_LF:\r
+ return Py_BuildValue("(ss)", "\r", "\n");\r
+ case NEWLINE_CRLF:\r
+ return PyString_FromString("\r\n");\r
+ case NEWLINE_CR|NEWLINE_CRLF:\r
+ return Py_BuildValue("(ss)", "\r", "\r\n");\r
+ case NEWLINE_LF|NEWLINE_CRLF:\r
+ return Py_BuildValue("(ss)", "\n", "\r\n");\r
+ case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:\r
+ return Py_BuildValue("(sss)", "\r", "\n", "\r\n");\r
+ default:\r
+ PyErr_Format(PyExc_SystemError,\r
+ "Unknown newlines value 0x%x\n",\r
+ f->f_newlinetypes);\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+get_softspace(PyFileObject *f, void *closure)\r
+{\r
+ if (PyErr_WarnPy3k("file.softspace not supported in 3.x", 1) < 0)\r
+ return NULL;\r
+ return PyInt_FromLong(f->f_softspace);\r
+}\r
+\r
+static int\r
+set_softspace(PyFileObject *f, PyObject *value)\r
+{\r
+ int new;\r
+ if (PyErr_WarnPy3k("file.softspace not supported in 3.x", 1) < 0)\r
+ return -1;\r
+\r
+ if (value == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "can't delete softspace attribute");\r
+ return -1;\r
+ }\r
+\r
+ new = PyInt_AsLong(value);\r
+ if (new == -1 && PyErr_Occurred())\r
+ return -1;\r
+ f->f_softspace = new;\r
+ return 0;\r
+}\r
+\r
+static PyGetSetDef file_getsetlist[] = {\r
+ {"closed", (getter)get_closed, NULL, "True if the file is closed"},\r
+ {"newlines", (getter)get_newlines, NULL,\r
+ "end-of-line convention used in this file"},\r
+ {"softspace", (getter)get_softspace, (setter)set_softspace,\r
+ "flag indicating that a space needs to be printed; used by print"},\r
+ {0},\r
+};\r
+\r
+static void\r
+drop_readahead(PyFileObject *f)\r
+{\r
+ if (f->f_buf != NULL) {\r
+ PyMem_Free(f->f_buf);\r
+ f->f_buf = NULL;\r
+ }\r
+}\r
+\r
+/* Make sure that file has a readahead buffer with at least one byte\r
+ (unless at EOF) and no more than bufsize. Returns negative value on\r
+ error, will set MemoryError if bufsize bytes cannot be allocated. */\r
+static int\r
+readahead(PyFileObject *f, Py_ssize_t bufsize)\r
+{\r
+ Py_ssize_t chunksize;\r
+\r
+ if (f->f_buf != NULL) {\r
+ if( (f->f_bufend - f->f_bufptr) >= 1)\r
+ return 0;\r
+ else\r
+ drop_readahead(f);\r
+ }\r
+ if ((f->f_buf = (char *)PyMem_Malloc(bufsize)) == NULL) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ FILE_BEGIN_ALLOW_THREADS(f)\r
+ errno = 0;\r
+ chunksize = Py_UniversalNewlineFread(\r
+ f->f_buf, bufsize, f->f_fp, (PyObject *)f);\r
+ FILE_END_ALLOW_THREADS(f)\r
+ if (chunksize == 0) {\r
+ if (ferror(f->f_fp)) {\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(f->f_fp);\r
+ drop_readahead(f);\r
+ return -1;\r
+ }\r
+ }\r
+ f->f_bufptr = f->f_buf;\r
+ f->f_bufend = f->f_buf + chunksize;\r
+ return 0;\r
+}\r
+\r
+/* Used by file_iternext. The returned string will start with 'skip'\r
+ uninitialized bytes followed by the remainder of the line. Don't be\r
+ horrified by the recursive call: maximum recursion depth is limited by\r
+ logarithmic buffer growth to about 50 even when reading a 1gb line. */\r
+\r
+static PyStringObject *\r
+readahead_get_line_skip(PyFileObject *f, Py_ssize_t skip, Py_ssize_t bufsize)\r
+{\r
+ PyStringObject* s;\r
+ char *bufptr;\r
+ char *buf;\r
+ Py_ssize_t len;\r
+\r
+ if (f->f_buf == NULL)\r
+ if (readahead(f, bufsize) < 0)\r
+ return NULL;\r
+\r
+ len = f->f_bufend - f->f_bufptr;\r
+ if (len == 0)\r
+ return (PyStringObject *)\r
+ PyString_FromStringAndSize(NULL, skip);\r
+ bufptr = (char *)memchr(f->f_bufptr, '\n', len);\r
+ if (bufptr != NULL) {\r
+ bufptr++; /* Count the '\n' */\r
+ len = bufptr - f->f_bufptr;\r
+ s = (PyStringObject *)\r
+ PyString_FromStringAndSize(NULL, skip + len);\r
+ if (s == NULL)\r
+ return NULL;\r
+ memcpy(PyString_AS_STRING(s) + skip, f->f_bufptr, len);\r
+ f->f_bufptr = bufptr;\r
+ if (bufptr == f->f_bufend)\r
+ drop_readahead(f);\r
+ } else {\r
+ bufptr = f->f_bufptr;\r
+ buf = f->f_buf;\r
+ f->f_buf = NULL; /* Force new readahead buffer */\r
+ assert(len <= PY_SSIZE_T_MAX - skip);\r
+ s = readahead_get_line_skip(f, skip + len, bufsize + (bufsize>>2));\r
+ if (s == NULL) {\r
+ PyMem_Free(buf);\r
+ return NULL;\r
+ }\r
+ memcpy(PyString_AS_STRING(s) + skip, bufptr, len);\r
+ PyMem_Free(buf);\r
+ }\r
+ return s;\r
+}\r
+\r
+/* A larger buffer size may actually decrease performance. */\r
+#define READAHEAD_BUFSIZE 8192\r
+\r
+static PyObject *\r
+file_iternext(PyFileObject *f)\r
+{\r
+ PyStringObject* l;\r
+\r
+ if (f->f_fp == NULL)\r
+ return err_closed();\r
+ if (!f->readable)\r
+ return err_mode("reading");\r
+\r
+ l = readahead_get_line_skip(f, 0, READAHEAD_BUFSIZE);\r
+ if (l == NULL || PyString_GET_SIZE(l) == 0) {\r
+ Py_XDECREF(l);\r
+ return NULL;\r
+ }\r
+ return (PyObject *)l;\r
+}\r
+\r
+\r
+static PyObject *\r
+file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *self;\r
+ static PyObject *not_yet_string;\r
+\r
+ assert(type != NULL && type->tp_alloc != NULL);\r
+\r
+ if (not_yet_string == NULL) {\r
+ not_yet_string = PyString_InternFromString("<uninitialized file>");\r
+ if (not_yet_string == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ self = type->tp_alloc(type, 0);\r
+ if (self != NULL) {\r
+ /* Always fill in the name and mode, so that nobody else\r
+ needs to special-case NULLs there. */\r
+ Py_INCREF(not_yet_string);\r
+ ((PyFileObject *)self)->f_name = not_yet_string;\r
+ Py_INCREF(not_yet_string);\r
+ ((PyFileObject *)self)->f_mode = not_yet_string;\r
+ Py_INCREF(Py_None);\r
+ ((PyFileObject *)self)->f_encoding = Py_None;\r
+ Py_INCREF(Py_None);\r
+ ((PyFileObject *)self)->f_errors = Py_None;\r
+ ((PyFileObject *)self)->weakreflist = NULL;\r
+ ((PyFileObject *)self)->unlocked_count = 0;\r
+ }\r
+ return self;\r
+}\r
+\r
+static int\r
+file_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ PyFileObject *foself = (PyFileObject *)self;\r
+ int ret = 0;\r
+ static char *kwlist[] = {"name", "mode", "buffering", 0};\r
+ char *name = NULL;\r
+ char *mode = "r";\r
+ int bufsize = -1;\r
+ int wideargument = 0;\r
+#ifdef MS_WINDOWS\r
+ PyObject *po;\r
+#endif\r
+\r
+ assert(PyFile_Check(self));\r
+ if (foself->f_fp != NULL) {\r
+ /* Have to close the existing file first. */\r
+ PyObject *closeresult = file_close(foself);\r
+ if (closeresult == NULL)\r
+ return -1;\r
+ Py_DECREF(closeresult);\r
+ }\r
+\r
+#ifdef MS_WINDOWS\r
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:file",\r
+ kwlist, &po, &mode, &bufsize)) {\r
+ wideargument = 1;\r
+ if (fill_file_fields(foself, NULL, po, mode,\r
+ fclose) == NULL)\r
+ goto Error;\r
+ } else {\r
+ /* Drop the argument parsing error as narrow\r
+ strings are also valid. */\r
+ PyErr_Clear();\r
+ }\r
+#endif\r
+\r
+ if (!wideargument) {\r
+ PyObject *o_name;\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,\r
+ Py_FileSystemDefaultEncoding,\r
+ &name,\r
+ &mode, &bufsize))\r
+ return -1;\r
+\r
+ /* We parse again to get the name as a PyObject */\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:file",\r
+ kwlist, &o_name, &mode,\r
+ &bufsize))\r
+ goto Error;\r
+\r
+ if (fill_file_fields(foself, NULL, o_name, mode,\r
+ fclose) == NULL)\r
+ goto Error;\r
+ }\r
+ if (open_the_file(foself, name, mode) == NULL)\r
+ goto Error;\r
+ foself->f_setbuf = NULL;\r
+ PyFile_SetBufSize(self, bufsize);\r
+ goto Done;\r
+\r
+Error:\r
+ ret = -1;\r
+ /* fall through */\r
+Done:\r
+ PyMem_Free(name); /* free the encoded string */\r
+ return ret;\r
+}\r
+\r
+PyDoc_VAR(file_doc) =\r
+PyDoc_STR(\r
+"file(name[, mode[, buffering]]) -> file object\n"\r
+"\n"\r
+"Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n"\r
+"writing or appending. The file will be created if it doesn't exist\n"\r
+"when opened for writing or appending; it will be truncated when\n"\r
+"opened for writing. Add a 'b' to the mode for binary files.\n"\r
+"Add a '+' to the mode to allow simultaneous reading and writing.\n"\r
+"If the buffering argument is given, 0 means unbuffered, 1 means line\n"\r
+"buffered, and larger numbers specify the buffer size. The preferred way\n"\r
+"to open a file is with the builtin open() function.\n"\r
+)\r
+PyDoc_STR(\r
+"Add a 'U' to mode to open the file for input with universal newline\n"\r
+"support. Any line ending in the input file will be seen as a '\\n'\n"\r
+"in Python. Also, a file so opened gains the attribute 'newlines';\n"\r
+"the value for this attribute is one of None (no newline read yet),\n"\r
+"'\\r', '\\n', '\\r\\n' or a tuple containing all the newline types seen.\n"\r
+"\n"\r
+"'U' cannot be combined with 'w' or '+' mode.\n"\r
+);\r
+\r
+PyTypeObject PyFile_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "file",\r
+ sizeof(PyFileObject),\r
+ 0,\r
+ (destructor)file_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)file_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ /* softspace is writable: we must supply tp_setattro */\r
+ PyObject_GenericSetAttr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */\r
+ file_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ offsetof(PyFileObject, weakreflist), /* tp_weaklistoffset */\r
+ (getiterfunc)file_self, /* tp_iter */\r
+ (iternextfunc)file_iternext, /* tp_iternext */\r
+ file_methods, /* tp_methods */\r
+ file_memberlist, /* tp_members */\r
+ file_getsetlist, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ file_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ file_new, /* tp_new */\r
+ PyObject_Del, /* tp_free */\r
+};\r
+\r
+/* Interface for the 'soft space' between print items. */\r
+\r
+int\r
+PyFile_SoftSpace(PyObject *f, int newflag)\r
+{\r
+ long oldflag = 0;\r
+ if (f == NULL) {\r
+ /* Do nothing */\r
+ }\r
+ else if (PyFile_Check(f)) {\r
+ oldflag = ((PyFileObject *)f)->f_softspace;\r
+ ((PyFileObject *)f)->f_softspace = newflag;\r
+ }\r
+ else {\r
+ PyObject *v;\r
+ v = PyObject_GetAttrString(f, "softspace");\r
+ if (v == NULL)\r
+ PyErr_Clear();\r
+ else {\r
+ if (PyInt_Check(v))\r
+ oldflag = PyInt_AsLong(v);\r
+ assert(oldflag < INT_MAX);\r
+ Py_DECREF(v);\r
+ }\r
+ v = PyInt_FromLong((long)newflag);\r
+ if (v == NULL)\r
+ PyErr_Clear();\r
+ else {\r
+ if (PyObject_SetAttrString(f, "softspace", v) != 0)\r
+ PyErr_Clear();\r
+ Py_DECREF(v);\r
+ }\r
+ }\r
+ return (int)oldflag;\r
+}\r
+\r
+/* Interfaces to write objects/strings to file-like objects */\r
+\r
+int\r
+PyFile_WriteObject(PyObject *v, PyObject *f, int flags)\r
+{\r
+ PyObject *writer, *value, *args, *result;\r
+ if (f == NULL) {\r
+ PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");\r
+ return -1;\r
+ }\r
+ else if (PyFile_Check(f)) {\r
+ PyFileObject *fobj = (PyFileObject *) f;\r
+#ifdef Py_USING_UNICODE\r
+ PyObject *enc = fobj->f_encoding;\r
+ int result;\r
+#endif\r
+ if (fobj->f_fp == NULL) {\r
+ err_closed();\r
+ return -1;\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ if ((flags & Py_PRINT_RAW) &&\r
+ PyUnicode_Check(v) && enc != Py_None) {\r
+ char *cenc = PyString_AS_STRING(enc);\r
+ char *errors = fobj->f_errors == Py_None ?\r
+ "strict" : PyString_AS_STRING(fobj->f_errors);\r
+ value = PyUnicode_AsEncodedString(v, cenc, errors);\r
+ if (value == NULL)\r
+ return -1;\r
+ } else {\r
+ value = v;\r
+ Py_INCREF(value);\r
+ }\r
+ result = file_PyObject_Print(value, fobj, flags);\r
+ Py_DECREF(value);\r
+ return result;\r
+#else\r
+ return file_PyObject_Print(v, fobj, flags);\r
+#endif\r
+ }\r
+ writer = PyObject_GetAttrString(f, "write");\r
+ if (writer == NULL)\r
+ return -1;\r
+ if (flags & Py_PRINT_RAW) {\r
+ if (PyUnicode_Check(v)) {\r
+ value = v;\r
+ Py_INCREF(value);\r
+ } else\r
+ value = PyObject_Str(v);\r
+ }\r
+ else\r
+ value = PyObject_Repr(v);\r
+ if (value == NULL) {\r
+ Py_DECREF(writer);\r
+ return -1;\r
+ }\r
+ args = PyTuple_Pack(1, value);\r
+ if (args == NULL) {\r
+ Py_DECREF(value);\r
+ Py_DECREF(writer);\r
+ return -1;\r
+ }\r
+ result = PyEval_CallObject(writer, args);\r
+ Py_DECREF(args);\r
+ Py_DECREF(value);\r
+ Py_DECREF(writer);\r
+ if (result == NULL)\r
+ return -1;\r
+ Py_DECREF(result);\r
+ return 0;\r
+}\r
+\r
+int\r
+PyFile_WriteString(const char *s, PyObject *f)\r
+{\r
+\r
+ if (f == NULL) {\r
+ /* Should be caused by a pre-existing error */\r
+ if (!PyErr_Occurred())\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "null file for PyFile_WriteString");\r
+ return -1;\r
+ }\r
+ else if (PyFile_Check(f)) {\r
+ PyFileObject *fobj = (PyFileObject *) f;\r
+ FILE *fp = PyFile_AsFile(f);\r
+ if (fp == NULL) {\r
+ err_closed();\r
+ return -1;\r
+ }\r
+ FILE_BEGIN_ALLOW_THREADS(fobj)\r
+ fputs(s, fp);\r
+ FILE_END_ALLOW_THREADS(fobj)\r
+ return 0;\r
+ }\r
+ else if (!PyErr_Occurred()) {\r
+ PyObject *v = PyString_FromString(s);\r
+ int err;\r
+ if (v == NULL)\r
+ return -1;\r
+ err = PyFile_WriteObject(v, f, Py_PRINT_RAW);\r
+ Py_DECREF(v);\r
+ return err;\r
+ }\r
+ else\r
+ return -1;\r
+}\r
+\r
+/* Try to get a file-descriptor from a Python object. If the object\r
+ is an integer or long integer, its value is returned. If not, the\r
+ object's fileno() method is called if it exists; the method must return\r
+ an integer or long integer, which is returned as the file descriptor value.\r
+ -1 is returned on failure.\r
+*/\r
+\r
+int PyObject_AsFileDescriptor(PyObject *o)\r
+{\r
+ int fd;\r
+ PyObject *meth;\r
+\r
+ if (PyInt_Check(o)) {\r
+ fd = _PyInt_AsInt(o);\r
+ }\r
+ else if (PyLong_Check(o)) {\r
+ fd = _PyLong_AsInt(o);\r
+ }\r
+ else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)\r
+ {\r
+ PyObject *fno = PyEval_CallObject(meth, NULL);\r
+ Py_DECREF(meth);\r
+ if (fno == NULL)\r
+ return -1;\r
+\r
+ if (PyInt_Check(fno)) {\r
+ fd = _PyInt_AsInt(fno);\r
+ Py_DECREF(fno);\r
+ }\r
+ else if (PyLong_Check(fno)) {\r
+ fd = _PyLong_AsInt(fno);\r
+ Py_DECREF(fno);\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "fileno() returned a non-integer");\r
+ Py_DECREF(fno);\r
+ return -1;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "argument must be an int, or have a fileno() method.");\r
+ return -1;\r
+ }\r
+\r
+ if (fd < 0) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "file descriptor cannot be a negative integer (%i)",\r
+ fd);\r
+ return -1;\r
+ }\r
+ return fd;\r
+}\r
+\r
+/* From here on we need access to the real fgets and fread */\r
+#undef fgets\r
+#undef fread\r
+\r
+/*\r
+** Py_UniversalNewlineFgets is an fgets variation that understands\r
+** all of \r, \n and \r\n conventions.\r
+** The stream should be opened in binary mode.\r
+** If fobj is NULL the routine always does newline conversion, and\r
+** it may peek one char ahead to gobble the second char in \r\n.\r
+** If fobj is non-NULL it must be a PyFileObject. In this case there\r
+** is no readahead but in stead a flag is used to skip a following\r
+** \n on the next read. Also, if the file is open in binary mode\r
+** the whole conversion is skipped. Finally, the routine keeps track of\r
+** the different types of newlines seen.\r
+** Note that we need no error handling: fgets() treats error and eof\r
+** identically.\r
+*/\r
+char *\r
+Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)\r
+{\r
+ char *p = buf;\r
+ int c;\r
+ int newlinetypes = 0;\r
+ int skipnextlf = 0;\r
+ int univ_newline = 1;\r
+\r
+ if (fobj) {\r
+ if (!PyFile_Check(fobj)) {\r
+ errno = ENXIO; /* What can you do... */\r
+ return NULL;\r
+ }\r
+ univ_newline = ((PyFileObject *)fobj)->f_univ_newline;\r
+ if ( !univ_newline )\r
+ return fgets(buf, n, stream);\r
+ newlinetypes = ((PyFileObject *)fobj)->f_newlinetypes;\r
+ skipnextlf = ((PyFileObject *)fobj)->f_skipnextlf;\r
+ }\r
+ FLOCKFILE(stream);\r
+ c = 'x'; /* Shut up gcc warning */\r
+ while (--n > 0 && (c = GETC(stream)) != EOF ) {\r
+ if (skipnextlf ) {\r
+ skipnextlf = 0;\r
+ if (c == '\n') {\r
+ /* Seeing a \n here with skipnextlf true\r
+ ** means we saw a \r before.\r
+ */\r
+ newlinetypes |= NEWLINE_CRLF;\r
+ c = GETC(stream);\r
+ if (c == EOF) break;\r
+ } else {\r
+ /*\r
+ ** Note that c == EOF also brings us here,\r
+ ** so we're okay if the last char in the file\r
+ ** is a CR.\r
+ */\r
+ newlinetypes |= NEWLINE_CR;\r
+ }\r
+ }\r
+ if (c == '\r') {\r
+ /* A \r is translated into a \n, and we skip\r
+ ** an adjacent \n, if any. We don't set the\r
+ ** newlinetypes flag until we've seen the next char.\r
+ */\r
+ skipnextlf = 1;\r
+ c = '\n';\r
+ } else if ( c == '\n') {\r
+ newlinetypes |= NEWLINE_LF;\r
+ }\r
+ *p++ = c;\r
+ if (c == '\n') break;\r
+ }\r
+ if ( c == EOF && skipnextlf )\r
+ newlinetypes |= NEWLINE_CR;\r
+ FUNLOCKFILE(stream);\r
+ *p = '\0';\r
+ if (fobj) {\r
+ ((PyFileObject *)fobj)->f_newlinetypes = newlinetypes;\r
+ ((PyFileObject *)fobj)->f_skipnextlf = skipnextlf;\r
+ } else if ( skipnextlf ) {\r
+ /* If we have no file object we cannot save the\r
+ ** skipnextlf flag. We have to readahead, which\r
+ ** will cause a pause if we're reading from an\r
+ ** interactive stream, but that is very unlikely\r
+ ** unless we're doing something silly like\r
+ ** execfile("/dev/tty").\r
+ */\r
+ c = GETC(stream);\r
+ if ( c != '\n' )\r
+ ungetc(c, stream);\r
+ }\r
+ if (p == buf)\r
+ return NULL;\r
+ return buf;\r
+}\r
+\r
+/*\r
+** Py_UniversalNewlineFread is an fread variation that understands\r
+** all of \r, \n and \r\n conventions.\r
+** The stream should be opened in binary mode.\r
+** fobj must be a PyFileObject. In this case there\r
+** is no readahead but in stead a flag is used to skip a following\r
+** \n on the next read. Also, if the file is open in binary mode\r
+** the whole conversion is skipped. Finally, the routine keeps track of\r
+** the different types of newlines seen.\r
+*/\r
+size_t\r
+Py_UniversalNewlineFread(char *buf, size_t n,\r
+ FILE *stream, PyObject *fobj)\r
+{\r
+ char *dst = buf;\r
+ PyFileObject *f = (PyFileObject *)fobj;\r
+ int newlinetypes, skipnextlf;\r
+\r
+ assert(buf != NULL);\r
+ assert(stream != NULL);\r
+\r
+ if (!fobj || !PyFile_Check(fobj)) {\r
+ errno = ENXIO; /* What can you do... */\r
+ return 0;\r
+ }\r
+ if (!f->f_univ_newline)\r
+ return fread(buf, 1, n, stream);\r
+ newlinetypes = f->f_newlinetypes;\r
+ skipnextlf = f->f_skipnextlf;\r
+ /* Invariant: n is the number of bytes remaining to be filled\r
+ * in the buffer.\r
+ */\r
+ while (n) {\r
+ size_t nread;\r
+ int shortread;\r
+ char *src = dst;\r
+\r
+ nread = fread(dst, 1, n, stream);\r
+ assert(nread <= n);\r
+ if (nread == 0)\r
+ break;\r
+\r
+ n -= nread; /* assuming 1 byte out for each in; will adjust */\r
+ shortread = n != 0; /* true iff EOF or error */\r
+ while (nread--) {\r
+ char c = *src++;\r
+ if (c == '\r') {\r
+ /* Save as LF and set flag to skip next LF. */\r
+ *dst++ = '\n';\r
+ skipnextlf = 1;\r
+ }\r
+ else if (skipnextlf && c == '\n') {\r
+ /* Skip LF, and remember we saw CR LF. */\r
+ skipnextlf = 0;\r
+ newlinetypes |= NEWLINE_CRLF;\r
+ ++n;\r
+ }\r
+ else {\r
+ /* Normal char to be stored in buffer. Also\r
+ * update the newlinetypes flag if either this\r
+ * is an LF or the previous char was a CR.\r
+ */\r
+ if (c == '\n')\r
+ newlinetypes |= NEWLINE_LF;\r
+ else if (skipnextlf)\r
+ newlinetypes |= NEWLINE_CR;\r
+ *dst++ = c;\r
+ skipnextlf = 0;\r
+ }\r
+ }\r
+ if (shortread) {\r
+ /* If this is EOF, update type flags. */\r
+ if (skipnextlf && feof(stream))\r
+ newlinetypes |= NEWLINE_CR;\r
+ break;\r
+ }\r
+ }\r
+ f->f_newlinetypes = newlinetypes;\r
+ f->f_skipnextlf = skipnextlf;\r
+ return dst - buf;\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+\r
+/* Float object implementation */\r
+\r
+/* XXX There should be overflow checks here, but it's hard to check\r
+ for any kind of float exception without losing portability. */\r
+\r
+#include "Python.h"\r
+#include "structseq.h"\r
+\r
+#include <ctype.h>\r
+#include <float.h>\r
+\r
+#undef MAX\r
+#undef MIN\r
+#define MAX(x, y) ((x) < (y) ? (y) : (x))\r
+#define MIN(x, y) ((x) < (y) ? (x) : (y))\r
+\r
+#ifdef _OSF_SOURCE\r
+/* OSF1 5.1 doesn't make this available with XOPEN_SOURCE_EXTENDED defined */\r
+extern int finite(double);\r
+#endif\r
+\r
+/* Special free list -- see comments for same code in intobject.c. */\r
+#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */\r
+#define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */\r
+#define N_FLOATOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject))\r
+\r
+struct _floatblock {\r
+ struct _floatblock *next;\r
+ PyFloatObject objects[N_FLOATOBJECTS];\r
+};\r
+\r
+typedef struct _floatblock PyFloatBlock;\r
+\r
+static PyFloatBlock *block_list = NULL;\r
+static PyFloatObject *free_list = NULL;\r
+\r
+static PyFloatObject *\r
+fill_free_list(void)\r
+{\r
+ PyFloatObject *p, *q;\r
+ /* XXX Float blocks escape the object heap. Use PyObject_MALLOC ??? */\r
+ p = (PyFloatObject *) PyMem_MALLOC(sizeof(PyFloatBlock));\r
+ if (p == NULL)\r
+ return (PyFloatObject *) PyErr_NoMemory();\r
+ ((PyFloatBlock *)p)->next = block_list;\r
+ block_list = (PyFloatBlock *)p;\r
+ p = &((PyFloatBlock *)p)->objects[0];\r
+ q = p + N_FLOATOBJECTS;\r
+ while (--q > p)\r
+ Py_TYPE(q) = (struct _typeobject *)(q-1);\r
+ Py_TYPE(q) = NULL;\r
+ return p + N_FLOATOBJECTS - 1;\r
+}\r
+\r
+double\r
+PyFloat_GetMax(void)\r
+{\r
+ return DBL_MAX;\r
+}\r
+\r
+double\r
+PyFloat_GetMin(void)\r
+{\r
+ return DBL_MIN;\r
+}\r
+\r
+static PyTypeObject FloatInfoType = {0, 0, 0, 0, 0, 0};\r
+\r
+PyDoc_STRVAR(floatinfo__doc__,\r
+"sys.float_info\n\\r
+\n\\r
+A structseq holding information about the float type. It contains low level\n\\r
+information about the precision and internal representation. Please study\n\\r
+your system's :file:`float.h` for more information.");\r
+\r
+static PyStructSequence_Field floatinfo_fields[] = {\r
+ {"max", "DBL_MAX -- maximum representable finite float"},\r
+ {"max_exp", "DBL_MAX_EXP -- maximum int e such that radix**(e-1) "\r
+ "is representable"},\r
+ {"max_10_exp", "DBL_MAX_10_EXP -- maximum int e such that 10**e "\r
+ "is representable"},\r
+ {"min", "DBL_MIN -- Minimum positive normalizer float"},\r
+ {"min_exp", "DBL_MIN_EXP -- minimum int e such that radix**(e-1) "\r
+ "is a normalized float"},\r
+ {"min_10_exp", "DBL_MIN_10_EXP -- minimum int e such that 10**e is "\r
+ "a normalized"},\r
+ {"dig", "DBL_DIG -- digits"},\r
+ {"mant_dig", "DBL_MANT_DIG -- mantissa digits"},\r
+ {"epsilon", "DBL_EPSILON -- Difference between 1 and the next "\r
+ "representable float"},\r
+ {"radix", "FLT_RADIX -- radix of exponent"},\r
+ {"rounds", "FLT_ROUNDS -- addition rounds"},\r
+ {0}\r
+};\r
+\r
+static PyStructSequence_Desc floatinfo_desc = {\r
+ "sys.float_info", /* name */\r
+ floatinfo__doc__, /* doc */\r
+ floatinfo_fields, /* fields */\r
+ 11\r
+};\r
+\r
+PyObject *\r
+PyFloat_GetInfo(void)\r
+{\r
+ PyObject* floatinfo;\r
+ int pos = 0;\r
+\r
+ floatinfo = PyStructSequence_New(&FloatInfoType);\r
+ if (floatinfo == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+#define SetIntFlag(flag) \\r
+ PyStructSequence_SET_ITEM(floatinfo, pos++, PyInt_FromLong(flag))\r
+#define SetDblFlag(flag) \\r
+ PyStructSequence_SET_ITEM(floatinfo, pos++, PyFloat_FromDouble(flag))\r
+\r
+ SetDblFlag(DBL_MAX);\r
+ SetIntFlag(DBL_MAX_EXP);\r
+ SetIntFlag(DBL_MAX_10_EXP);\r
+ SetDblFlag(DBL_MIN);\r
+ SetIntFlag(DBL_MIN_EXP);\r
+ SetIntFlag(DBL_MIN_10_EXP);\r
+ SetIntFlag(DBL_DIG);\r
+ SetIntFlag(DBL_MANT_DIG);\r
+ SetDblFlag(DBL_EPSILON);\r
+ SetIntFlag(FLT_RADIX);\r
+ SetIntFlag(FLT_ROUNDS);\r
+#undef SetIntFlag\r
+#undef SetDblFlag\r
+\r
+ if (PyErr_Occurred()) {\r
+ Py_CLEAR(floatinfo);\r
+ return NULL;\r
+ }\r
+ return floatinfo;\r
+}\r
+\r
+PyObject *\r
+PyFloat_FromDouble(double fval)\r
+{\r
+ register PyFloatObject *op;\r
+ if (free_list == NULL) {\r
+ if ((free_list = fill_free_list()) == NULL)\r
+ return NULL;\r
+ }\r
+ /* Inline PyObject_New */\r
+ op = free_list;\r
+ free_list = (PyFloatObject *)Py_TYPE(op);\r
+ PyObject_INIT(op, &PyFloat_Type);\r
+ op->ob_fval = fval;\r
+ return (PyObject *) op;\r
+}\r
+\r
+/**************************************************************************\r
+RED_FLAG 22-Sep-2000 tim\r
+PyFloat_FromString's pend argument is braindead. Prior to this RED_FLAG,\r
+\r
+1. If v was a regular string, *pend was set to point to its terminating\r
+ null byte. That's useless (the caller can find that without any\r
+ help from this function!).\r
+\r
+2. If v was a Unicode string, or an object convertible to a character\r
+ buffer, *pend was set to point into stack trash (the auto temp\r
+ vector holding the character buffer). That was downright dangerous.\r
+\r
+Since we can't change the interface of a public API function, pend is\r
+still supported but now *officially* useless: if pend is not NULL,\r
+*pend is set to NULL.\r
+**************************************************************************/\r
+PyObject *\r
+PyFloat_FromString(PyObject *v, char **pend)\r
+{\r
+ const char *s, *last, *end;\r
+ double x;\r
+ char buffer[256]; /* for errors */\r
+#ifdef Py_USING_UNICODE\r
+ char *s_buffer = NULL;\r
+#endif\r
+ Py_ssize_t len;\r
+ PyObject *result = NULL;\r
+\r
+ if (pend)\r
+ *pend = NULL;\r
+ if (PyString_Check(v)) {\r
+ s = PyString_AS_STRING(v);\r
+ len = PyString_GET_SIZE(v);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(v)) {\r
+ s_buffer = (char *)PyMem_MALLOC(PyUnicode_GET_SIZE(v)+1);\r
+ if (s_buffer == NULL)\r
+ return PyErr_NoMemory();\r
+ if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),\r
+ PyUnicode_GET_SIZE(v),\r
+ s_buffer,\r
+ NULL))\r
+ goto error;\r
+ s = s_buffer;\r
+ len = strlen(s);\r
+ }\r
+#endif\r
+ else if (PyObject_AsCharBuffer(v, &s, &len)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "float() argument must be a string or a number");\r
+ return NULL;\r
+ }\r
+ last = s + len;\r
+\r
+ while (Py_ISSPACE(*s))\r
+ s++;\r
+ /* We don't care about overflow or underflow. If the platform\r
+ * supports them, infinities and signed zeroes (on underflow) are\r
+ * fine. */\r
+ x = PyOS_string_to_double(s, (char **)&end, NULL);\r
+ if (x == -1.0 && PyErr_Occurred())\r
+ goto error;\r
+ while (Py_ISSPACE(*end))\r
+ end++;\r
+ if (end == last)\r
+ result = PyFloat_FromDouble(x);\r
+ else {\r
+ PyOS_snprintf(buffer, sizeof(buffer),\r
+ "invalid literal for float(): %.200s", s);\r
+ PyErr_SetString(PyExc_ValueError, buffer);\r
+ result = NULL;\r
+ }\r
+\r
+ error:\r
+#ifdef Py_USING_UNICODE\r
+ if (s_buffer)\r
+ PyMem_FREE(s_buffer);\r
+#endif\r
+ return result;\r
+}\r
+\r
+static void\r
+float_dealloc(PyFloatObject *op)\r
+{\r
+ if (PyFloat_CheckExact(op)) {\r
+ Py_TYPE(op) = (struct _typeobject *)free_list;\r
+ free_list = op;\r
+ }\r
+ else\r
+ Py_TYPE(op)->tp_free((PyObject *)op);\r
+}\r
+\r
+double\r
+PyFloat_AsDouble(PyObject *op)\r
+{\r
+ PyNumberMethods *nb;\r
+ PyFloatObject *fo;\r
+ double val;\r
+\r
+ if (op && PyFloat_Check(op))\r
+ return PyFloat_AS_DOUBLE((PyFloatObject*) op);\r
+\r
+ if (op == NULL) {\r
+ PyErr_BadArgument();\r
+ return -1;\r
+ }\r
+\r
+ if ((nb = Py_TYPE(op)->tp_as_number) == NULL || nb->nb_float == NULL) {\r
+ PyErr_SetString(PyExc_TypeError, "a float is required");\r
+ return -1;\r
+ }\r
+\r
+ fo = (PyFloatObject*) (*nb->nb_float) (op);\r
+ if (fo == NULL)\r
+ return -1;\r
+ if (!PyFloat_Check(fo)) {\r
+ Py_DECREF(fo);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "nb_float should return float object");\r
+ return -1;\r
+ }\r
+\r
+ val = PyFloat_AS_DOUBLE(fo);\r
+ Py_DECREF(fo);\r
+\r
+ return val;\r
+}\r
+\r
+/* Methods */\r
+\r
+/* Macro and helper that convert PyObject obj to a C double and store\r
+ the value in dbl; this replaces the functionality of the coercion\r
+ slot function. If conversion to double raises an exception, obj is\r
+ set to NULL, and the function invoking this macro returns NULL. If\r
+ obj is not of float, int or long type, Py_NotImplemented is incref'ed,\r
+ stored in obj, and returned from the function invoking this macro.\r
+*/\r
+#define CONVERT_TO_DOUBLE(obj, dbl) \\r
+ if (PyFloat_Check(obj)) \\r
+ dbl = PyFloat_AS_DOUBLE(obj); \\r
+ else if (convert_to_double(&(obj), &(dbl)) < 0) \\r
+ return obj;\r
+\r
+static int\r
+convert_to_double(PyObject **v, double *dbl)\r
+{\r
+ register PyObject *obj = *v;\r
+\r
+ if (PyInt_Check(obj)) {\r
+ *dbl = (double)PyInt_AS_LONG(obj);\r
+ }\r
+ else if (PyLong_Check(obj)) {\r
+ *dbl = PyLong_AsDouble(obj);\r
+ if (*dbl == -1.0 && PyErr_Occurred()) {\r
+ *v = NULL;\r
+ return -1;\r
+ }\r
+ }\r
+ else {\r
+ Py_INCREF(Py_NotImplemented);\r
+ *v = Py_NotImplemented;\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+/* XXX PyFloat_AsString and PyFloat_AsReprString are deprecated:\r
+ XXX they pass a char buffer without passing a length.\r
+*/\r
+void\r
+PyFloat_AsString(char *buf, PyFloatObject *v)\r
+{\r
+ char *tmp = PyOS_double_to_string(v->ob_fval, 'g',\r
+ PyFloat_STR_PRECISION,\r
+ Py_DTSF_ADD_DOT_0, NULL);\r
+ strcpy(buf, tmp);\r
+ PyMem_Free(tmp);\r
+}\r
+\r
+void\r
+PyFloat_AsReprString(char *buf, PyFloatObject *v)\r
+{\r
+ char * tmp = PyOS_double_to_string(v->ob_fval, 'r', 0,\r
+ Py_DTSF_ADD_DOT_0, NULL);\r
+ strcpy(buf, tmp);\r
+ PyMem_Free(tmp);\r
+}\r
+\r
+/* ARGSUSED */\r
+static int\r
+float_print(PyFloatObject *v, FILE *fp, int flags)\r
+{\r
+ char *buf;\r
+ if (flags & Py_PRINT_RAW)\r
+ buf = PyOS_double_to_string(v->ob_fval,\r
+ 'g', PyFloat_STR_PRECISION,\r
+ Py_DTSF_ADD_DOT_0, NULL);\r
+ else\r
+ buf = PyOS_double_to_string(v->ob_fval,\r
+ 'r', 0, Py_DTSF_ADD_DOT_0, NULL);\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fputs(buf, fp);\r
+ Py_END_ALLOW_THREADS\r
+ PyMem_Free(buf);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+float_str_or_repr(PyFloatObject *v, int precision, char format_code)\r
+{\r
+ PyObject *result;\r
+ char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),\r
+ format_code, precision,\r
+ Py_DTSF_ADD_DOT_0,\r
+ NULL);\r
+ if (!buf)\r
+ return PyErr_NoMemory();\r
+ result = PyString_FromString(buf);\r
+ PyMem_Free(buf);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+float_repr(PyFloatObject *v)\r
+{\r
+ return float_str_or_repr(v, 0, 'r');\r
+}\r
+\r
+static PyObject *\r
+float_str(PyFloatObject *v)\r
+{\r
+ return float_str_or_repr(v, PyFloat_STR_PRECISION, 'g');\r
+}\r
+\r
+/* Comparison is pretty much a nightmare. When comparing float to float,\r
+ * we do it as straightforwardly (and long-windedly) as conceivable, so\r
+ * that, e.g., Python x == y delivers the same result as the platform\r
+ * C x == y when x and/or y is a NaN.\r
+ * When mixing float with an integer type, there's no good *uniform* approach.\r
+ * Converting the double to an integer obviously doesn't work, since we\r
+ * may lose info from fractional bits. Converting the integer to a double\r
+ * also has two failure modes: (1) a long int may trigger overflow (too\r
+ * large to fit in the dynamic range of a C double); (2) even a C long may have\r
+ * more bits than fit in a C double (e.g., on a a 64-bit box long may have\r
+ * 63 bits of precision, but a C double probably has only 53), and then\r
+ * we can falsely claim equality when low-order integer bits are lost by\r
+ * coercion to double. So this part is painful too.\r
+ */\r
+\r
+static PyObject*\r
+float_richcompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ double i, j;\r
+ int r = 0;\r
+\r
+ assert(PyFloat_Check(v));\r
+ i = PyFloat_AS_DOUBLE(v);\r
+\r
+ /* Switch on the type of w. Set i and j to doubles to be compared,\r
+ * and op to the richcomp to use.\r
+ */\r
+ if (PyFloat_Check(w))\r
+ j = PyFloat_AS_DOUBLE(w);\r
+\r
+ else if (!Py_IS_FINITE(i)) {\r
+ if (PyInt_Check(w) || PyLong_Check(w))\r
+ /* If i is an infinity, its magnitude exceeds any\r
+ * finite integer, so it doesn't matter which int we\r
+ * compare i with. If i is a NaN, similarly.\r
+ */\r
+ j = 0.0;\r
+ else\r
+ goto Unimplemented;\r
+ }\r
+\r
+ else if (PyInt_Check(w)) {\r
+ long jj = PyInt_AS_LONG(w);\r
+ /* In the worst realistic case I can imagine, C double is a\r
+ * Cray single with 48 bits of precision, and long has 64\r
+ * bits.\r
+ */\r
+#if SIZEOF_LONG > 6\r
+ unsigned long abs = (unsigned long)(jj < 0 ? -jj : jj);\r
+ if (abs >> 48) {\r
+ /* Needs more than 48 bits. Make it take the\r
+ * PyLong path.\r
+ */\r
+ PyObject *result;\r
+ PyObject *ww = PyLong_FromLong(jj);\r
+\r
+ if (ww == NULL)\r
+ return NULL;\r
+ result = float_richcompare(v, ww, op);\r
+ Py_DECREF(ww);\r
+ return result;\r
+ }\r
+#endif\r
+ j = (double)jj;\r
+ assert((long)j == jj);\r
+ }\r
+\r
+ else if (PyLong_Check(w)) {\r
+ int vsign = i == 0.0 ? 0 : i < 0.0 ? -1 : 1;\r
+ int wsign = _PyLong_Sign(w);\r
+ size_t nbits;\r
+ int exponent;\r
+\r
+ if (vsign != wsign) {\r
+ /* Magnitudes are irrelevant -- the signs alone\r
+ * determine the outcome.\r
+ */\r
+ i = (double)vsign;\r
+ j = (double)wsign;\r
+ goto Compare;\r
+ }\r
+ /* The signs are the same. */\r
+ /* Convert w to a double if it fits. In particular, 0 fits. */\r
+ nbits = _PyLong_NumBits(w);\r
+ if (nbits == (size_t)-1 && PyErr_Occurred()) {\r
+ /* This long is so large that size_t isn't big enough\r
+ * to hold the # of bits. Replace with little doubles\r
+ * that give the same outcome -- w is so large that\r
+ * its magnitude must exceed the magnitude of any\r
+ * finite float.\r
+ */\r
+ PyErr_Clear();\r
+ i = (double)vsign;\r
+ assert(wsign != 0);\r
+ j = wsign * 2.0;\r
+ goto Compare;\r
+ }\r
+ if (nbits <= 48) {\r
+ j = PyLong_AsDouble(w);\r
+ /* It's impossible that <= 48 bits overflowed. */\r
+ assert(j != -1.0 || ! PyErr_Occurred());\r
+ goto Compare;\r
+ }\r
+ assert(wsign != 0); /* else nbits was 0 */\r
+ assert(vsign != 0); /* if vsign were 0, then since wsign is\r
+ * not 0, we would have taken the\r
+ * vsign != wsign branch at the start */\r
+ /* We want to work with non-negative numbers. */\r
+ if (vsign < 0) {\r
+ /* "Multiply both sides" by -1; this also swaps the\r
+ * comparator.\r
+ */\r
+ i = -i;\r
+ op = _Py_SwappedOp[op];\r
+ }\r
+ assert(i > 0.0);\r
+ (void) frexp(i, &exponent);\r
+ /* exponent is the # of bits in v before the radix point;\r
+ * we know that nbits (the # of bits in w) > 48 at this point\r
+ */\r
+ if (exponent < 0 || (size_t)exponent < nbits) {\r
+ i = 1.0;\r
+ j = 2.0;\r
+ goto Compare;\r
+ }\r
+ if ((size_t)exponent > nbits) {\r
+ i = 2.0;\r
+ j = 1.0;\r
+ goto Compare;\r
+ }\r
+ /* v and w have the same number of bits before the radix\r
+ * point. Construct two longs that have the same comparison\r
+ * outcome.\r
+ */\r
+ {\r
+ double fracpart;\r
+ double intpart;\r
+ PyObject *result = NULL;\r
+ PyObject *one = NULL;\r
+ PyObject *vv = NULL;\r
+ PyObject *ww = w;\r
+\r
+ if (wsign < 0) {\r
+ ww = PyNumber_Negative(w);\r
+ if (ww == NULL)\r
+ goto Error;\r
+ }\r
+ else\r
+ Py_INCREF(ww);\r
+\r
+ fracpart = modf(i, &intpart);\r
+ vv = PyLong_FromDouble(intpart);\r
+ if (vv == NULL)\r
+ goto Error;\r
+\r
+ if (fracpart != 0.0) {\r
+ /* Shift left, and or a 1 bit into vv\r
+ * to represent the lost fraction.\r
+ */\r
+ PyObject *temp;\r
+\r
+ one = PyInt_FromLong(1);\r
+ if (one == NULL)\r
+ goto Error;\r
+\r
+ temp = PyNumber_Lshift(ww, one);\r
+ if (temp == NULL)\r
+ goto Error;\r
+ Py_DECREF(ww);\r
+ ww = temp;\r
+\r
+ temp = PyNumber_Lshift(vv, one);\r
+ if (temp == NULL)\r
+ goto Error;\r
+ Py_DECREF(vv);\r
+ vv = temp;\r
+\r
+ temp = PyNumber_Or(vv, one);\r
+ if (temp == NULL)\r
+ goto Error;\r
+ Py_DECREF(vv);\r
+ vv = temp;\r
+ }\r
+\r
+ r = PyObject_RichCompareBool(vv, ww, op);\r
+ if (r < 0)\r
+ goto Error;\r
+ result = PyBool_FromLong(r);\r
+ Error:\r
+ Py_XDECREF(vv);\r
+ Py_XDECREF(ww);\r
+ Py_XDECREF(one);\r
+ return result;\r
+ }\r
+ } /* else if (PyLong_Check(w)) */\r
+\r
+ else /* w isn't float, int, or long */\r
+ goto Unimplemented;\r
+\r
+ Compare:\r
+ PyFPE_START_PROTECT("richcompare", return NULL)\r
+ switch (op) {\r
+ case Py_EQ:\r
+ r = i == j;\r
+ break;\r
+ case Py_NE:\r
+ r = i != j;\r
+ break;\r
+ case Py_LE:\r
+ r = i <= j;\r
+ break;\r
+ case Py_GE:\r
+ r = i >= j;\r
+ break;\r
+ case Py_LT:\r
+ r = i < j;\r
+ break;\r
+ case Py_GT:\r
+ r = i > j;\r
+ break;\r
+ }\r
+ PyFPE_END_PROTECT(r)\r
+ return PyBool_FromLong(r);\r
+\r
+ Unimplemented:\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+}\r
+\r
+static long\r
+float_hash(PyFloatObject *v)\r
+{\r
+ return _Py_HashDouble(v->ob_fval);\r
+}\r
+\r
+static PyObject *\r
+float_add(PyObject *v, PyObject *w)\r
+{\r
+ double a,b;\r
+ CONVERT_TO_DOUBLE(v, a);\r
+ CONVERT_TO_DOUBLE(w, b);\r
+ PyFPE_START_PROTECT("add", return 0)\r
+ a = a + b;\r
+ PyFPE_END_PROTECT(a)\r
+ return PyFloat_FromDouble(a);\r
+}\r
+\r
+static PyObject *\r
+float_sub(PyObject *v, PyObject *w)\r
+{\r
+ double a,b;\r
+ CONVERT_TO_DOUBLE(v, a);\r
+ CONVERT_TO_DOUBLE(w, b);\r
+ PyFPE_START_PROTECT("subtract", return 0)\r
+ a = a - b;\r
+ PyFPE_END_PROTECT(a)\r
+ return PyFloat_FromDouble(a);\r
+}\r
+\r
+static PyObject *\r
+float_mul(PyObject *v, PyObject *w)\r
+{\r
+ double a,b;\r
+ CONVERT_TO_DOUBLE(v, a);\r
+ CONVERT_TO_DOUBLE(w, b);\r
+ PyFPE_START_PROTECT("multiply", return 0)\r
+ a = a * b;\r
+ PyFPE_END_PROTECT(a)\r
+ return PyFloat_FromDouble(a);\r
+}\r
+\r
+static PyObject *\r
+float_div(PyObject *v, PyObject *w)\r
+{\r
+ double a,b;\r
+ CONVERT_TO_DOUBLE(v, a);\r
+ CONVERT_TO_DOUBLE(w, b);\r
+#ifdef Py_NAN\r
+ if (b == 0.0) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError,\r
+ "float division by zero");\r
+ return NULL;\r
+ }\r
+#endif\r
+ PyFPE_START_PROTECT("divide", return 0)\r
+ a = a / b;\r
+ PyFPE_END_PROTECT(a)\r
+ return PyFloat_FromDouble(a);\r
+}\r
+\r
+static PyObject *\r
+float_classic_div(PyObject *v, PyObject *w)\r
+{\r
+ double a,b;\r
+ CONVERT_TO_DOUBLE(v, a);\r
+ CONVERT_TO_DOUBLE(w, b);\r
+ if (Py_DivisionWarningFlag >= 2 &&\r
+ PyErr_Warn(PyExc_DeprecationWarning, "classic float division") < 0)\r
+ return NULL;\r
+#ifdef Py_NAN\r
+ if (b == 0.0) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError,\r
+ "float division by zero");\r
+ return NULL;\r
+ }\r
+#endif\r
+ PyFPE_START_PROTECT("divide", return 0)\r
+ a = a / b;\r
+ PyFPE_END_PROTECT(a)\r
+ return PyFloat_FromDouble(a);\r
+}\r
+\r
+static PyObject *\r
+float_rem(PyObject *v, PyObject *w)\r
+{\r
+ double vx, wx;\r
+ double mod;\r
+ CONVERT_TO_DOUBLE(v, vx);\r
+ CONVERT_TO_DOUBLE(w, wx);\r
+#ifdef Py_NAN\r
+ if (wx == 0.0) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError,\r
+ "float modulo");\r
+ return NULL;\r
+ }\r
+#endif\r
+ PyFPE_START_PROTECT("modulo", return 0)\r
+ mod = fmod(vx, wx);\r
+ if (mod) {\r
+ /* ensure the remainder has the same sign as the denominator */\r
+ if ((wx < 0) != (mod < 0)) {\r
+ mod += wx;\r
+ }\r
+ }\r
+ else {\r
+ /* the remainder is zero, and in the presence of signed zeroes\r
+ fmod returns different results across platforms; ensure\r
+ it has the same sign as the denominator; we'd like to do\r
+ "mod = wx * 0.0", but that may get optimized away */\r
+ mod *= mod; /* hide "mod = +0" from optimizer */\r
+ if (wx < 0.0)\r
+ mod = -mod;\r
+ }\r
+ PyFPE_END_PROTECT(mod)\r
+ return PyFloat_FromDouble(mod);\r
+}\r
+\r
+static PyObject *\r
+float_divmod(PyObject *v, PyObject *w)\r
+{\r
+ double vx, wx;\r
+ double div, mod, floordiv;\r
+ CONVERT_TO_DOUBLE(v, vx);\r
+ CONVERT_TO_DOUBLE(w, wx);\r
+ if (wx == 0.0) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");\r
+ return NULL;\r
+ }\r
+ PyFPE_START_PROTECT("divmod", return 0)\r
+ mod = fmod(vx, wx);\r
+ /* fmod is typically exact, so vx-mod is *mathematically* an\r
+ exact multiple of wx. But this is fp arithmetic, and fp\r
+ vx - mod is an approximation; the result is that div may\r
+ not be an exact integral value after the division, although\r
+ it will always be very close to one.\r
+ */\r
+ div = (vx - mod) / wx;\r
+ if (mod) {\r
+ /* ensure the remainder has the same sign as the denominator */\r
+ if ((wx < 0) != (mod < 0)) {\r
+ mod += wx;\r
+ div -= 1.0;\r
+ }\r
+ }\r
+ else {\r
+ /* the remainder is zero, and in the presence of signed zeroes\r
+ fmod returns different results across platforms; ensure\r
+ it has the same sign as the denominator; we'd like to do\r
+ "mod = wx * 0.0", but that may get optimized away */\r
+ mod *= mod; /* hide "mod = +0" from optimizer */\r
+ if (wx < 0.0)\r
+ mod = -mod;\r
+ }\r
+ /* snap quotient to nearest integral value */\r
+ if (div) {\r
+ floordiv = floor(div);\r
+ if (div - floordiv > 0.5)\r
+ floordiv += 1.0;\r
+ }\r
+ else {\r
+ /* div is zero - get the same sign as the true quotient */\r
+ div *= div; /* hide "div = +0" from optimizers */\r
+ floordiv = div * vx / wx; /* zero w/ sign of vx/wx */\r
+ }\r
+ PyFPE_END_PROTECT(floordiv)\r
+ return Py_BuildValue("(dd)", floordiv, mod);\r
+}\r
+\r
+static PyObject *\r
+float_floor_div(PyObject *v, PyObject *w)\r
+{\r
+ PyObject *t, *r;\r
+\r
+ t = float_divmod(v, w);\r
+ if (t == NULL || t == Py_NotImplemented)\r
+ return t;\r
+ assert(PyTuple_CheckExact(t));\r
+ r = PyTuple_GET_ITEM(t, 0);\r
+ Py_INCREF(r);\r
+ Py_DECREF(t);\r
+ return r;\r
+}\r
+\r
+/* determine whether x is an odd integer or not; assumes that\r
+ x is not an infinity or nan. */\r
+#define DOUBLE_IS_ODD_INTEGER(x) (fmod(fabs(x), 2.0) == 1.0)\r
+\r
+static PyObject *\r
+float_pow(PyObject *v, PyObject *w, PyObject *z)\r
+{\r
+ double iv, iw, ix;\r
+ int negate_result = 0;\r
+\r
+ if ((PyObject *)z != Py_None) {\r
+ PyErr_SetString(PyExc_TypeError, "pow() 3rd argument not "\r
+ "allowed unless all arguments are integers");\r
+ return NULL;\r
+ }\r
+\r
+ CONVERT_TO_DOUBLE(v, iv);\r
+ CONVERT_TO_DOUBLE(w, iw);\r
+\r
+ /* Sort out special cases here instead of relying on pow() */\r
+ if (iw == 0) { /* v**0 is 1, even 0**0 */\r
+ return PyFloat_FromDouble(1.0);\r
+ }\r
+ if (Py_IS_NAN(iv)) { /* nan**w = nan, unless w == 0 */\r
+ return PyFloat_FromDouble(iv);\r
+ }\r
+ if (Py_IS_NAN(iw)) { /* v**nan = nan, unless v == 1; 1**nan = 1 */\r
+ return PyFloat_FromDouble(iv == 1.0 ? 1.0 : iw);\r
+ }\r
+ if (Py_IS_INFINITY(iw)) {\r
+ /* v**inf is: 0.0 if abs(v) < 1; 1.0 if abs(v) == 1; inf if\r
+ * abs(v) > 1 (including case where v infinite)\r
+ *\r
+ * v**-inf is: inf if abs(v) < 1; 1.0 if abs(v) == 1; 0.0 if\r
+ * abs(v) > 1 (including case where v infinite)\r
+ */\r
+ iv = fabs(iv);\r
+ if (iv == 1.0)\r
+ return PyFloat_FromDouble(1.0);\r
+ else if ((iw > 0.0) == (iv > 1.0))\r
+ return PyFloat_FromDouble(fabs(iw)); /* return inf */\r
+ else\r
+ return PyFloat_FromDouble(0.0);\r
+ }\r
+ if (Py_IS_INFINITY(iv)) {\r
+ /* (+-inf)**w is: inf for w positive, 0 for w negative; in\r
+ * both cases, we need to add the appropriate sign if w is\r
+ * an odd integer.\r
+ */\r
+ int iw_is_odd = DOUBLE_IS_ODD_INTEGER(iw);\r
+ if (iw > 0.0)\r
+ return PyFloat_FromDouble(iw_is_odd ? iv : fabs(iv));\r
+ else\r
+ return PyFloat_FromDouble(iw_is_odd ?\r
+ copysign(0.0, iv) : 0.0);\r
+ }\r
+ if (iv == 0.0) { /* 0**w is: 0 for w positive, 1 for w zero\r
+ (already dealt with above), and an error\r
+ if w is negative. */\r
+ int iw_is_odd = DOUBLE_IS_ODD_INTEGER(iw);\r
+ if (iw < 0.0) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError,\r
+ "0.0 cannot be raised to a "\r
+ "negative power");\r
+ return NULL;\r
+ }\r
+ /* use correct sign if iw is odd */\r
+ return PyFloat_FromDouble(iw_is_odd ? iv : 0.0);\r
+ }\r
+\r
+ if (iv < 0.0) {\r
+ /* Whether this is an error is a mess, and bumps into libm\r
+ * bugs so we have to figure it out ourselves.\r
+ */\r
+ if (iw != floor(iw)) {\r
+ PyErr_SetString(PyExc_ValueError, "negative number "\r
+ "cannot be raised to a fractional power");\r
+ return NULL;\r
+ }\r
+ /* iw is an exact integer, albeit perhaps a very large\r
+ * one. Replace iv by its absolute value and remember\r
+ * to negate the pow result if iw is odd.\r
+ */\r
+ iv = -iv;\r
+ negate_result = DOUBLE_IS_ODD_INTEGER(iw);\r
+ }\r
+\r
+ if (iv == 1.0) { /* 1**w is 1, even 1**inf and 1**nan */\r
+ /* (-1) ** large_integer also ends up here. Here's an\r
+ * extract from the comments for the previous\r
+ * implementation explaining why this special case is\r
+ * necessary:\r
+ *\r
+ * -1 raised to an exact integer should never be exceptional.\r
+ * Alas, some libms (chiefly glibc as of early 2003) return\r
+ * NaN and set EDOM on pow(-1, large_int) if the int doesn't\r
+ * happen to be representable in a *C* integer. That's a\r
+ * bug.\r
+ */\r
+ return PyFloat_FromDouble(negate_result ? -1.0 : 1.0);\r
+ }\r
+\r
+ /* Now iv and iw are finite, iw is nonzero, and iv is\r
+ * positive and not equal to 1.0. We finally allow\r
+ * the platform pow to step in and do the rest.\r
+ */\r
+ errno = 0;\r
+ PyFPE_START_PROTECT("pow", return NULL)\r
+ ix = pow(iv, iw);\r
+ PyFPE_END_PROTECT(ix)\r
+ Py_ADJUST_ERANGE1(ix);\r
+ if (negate_result)\r
+ ix = -ix;\r
+\r
+ if (errno != 0) {\r
+ /* We don't expect any errno value other than ERANGE, but\r
+ * the range of libm bugs appears unbounded.\r
+ */\r
+ PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError :\r
+ PyExc_ValueError);\r
+ return NULL;\r
+ }\r
+ return PyFloat_FromDouble(ix);\r
+}\r
+\r
+#undef DOUBLE_IS_ODD_INTEGER\r
+\r
+static PyObject *\r
+float_neg(PyFloatObject *v)\r
+{\r
+ return PyFloat_FromDouble(-v->ob_fval);\r
+}\r
+\r
+static PyObject *\r
+float_abs(PyFloatObject *v)\r
+{\r
+ return PyFloat_FromDouble(fabs(v->ob_fval));\r
+}\r
+\r
+static int\r
+float_nonzero(PyFloatObject *v)\r
+{\r
+ return v->ob_fval != 0.0;\r
+}\r
+\r
+static int\r
+float_coerce(PyObject **pv, PyObject **pw)\r
+{\r
+ if (PyInt_Check(*pw)) {\r
+ long x = PyInt_AsLong(*pw);\r
+ *pw = PyFloat_FromDouble((double)x);\r
+ Py_INCREF(*pv);\r
+ return 0;\r
+ }\r
+ else if (PyLong_Check(*pw)) {\r
+ double x = PyLong_AsDouble(*pw);\r
+ if (x == -1.0 && PyErr_Occurred())\r
+ return -1;\r
+ *pw = PyFloat_FromDouble(x);\r
+ Py_INCREF(*pv);\r
+ return 0;\r
+ }\r
+ else if (PyFloat_Check(*pw)) {\r
+ Py_INCREF(*pv);\r
+ Py_INCREF(*pw);\r
+ return 0;\r
+ }\r
+ return 1; /* Can't do it */\r
+}\r
+\r
+static PyObject *\r
+float_is_integer(PyObject *v)\r
+{\r
+ double x = PyFloat_AsDouble(v);\r
+ PyObject *o;\r
+\r
+ if (x == -1.0 && PyErr_Occurred())\r
+ return NULL;\r
+ if (!Py_IS_FINITE(x))\r
+ Py_RETURN_FALSE;\r
+ errno = 0;\r
+ PyFPE_START_PROTECT("is_integer", return NULL)\r
+ o = (floor(x) == x) ? Py_True : Py_False;\r
+ PyFPE_END_PROTECT(x)\r
+ if (errno != 0) {\r
+ PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError :\r
+ PyExc_ValueError);\r
+ return NULL;\r
+ }\r
+ Py_INCREF(o);\r
+ return o;\r
+}\r
+\r
+#if 0\r
+static PyObject *\r
+float_is_inf(PyObject *v)\r
+{\r
+ double x = PyFloat_AsDouble(v);\r
+ if (x == -1.0 && PyErr_Occurred())\r
+ return NULL;\r
+ return PyBool_FromLong((long)Py_IS_INFINITY(x));\r
+}\r
+\r
+static PyObject *\r
+float_is_nan(PyObject *v)\r
+{\r
+ double x = PyFloat_AsDouble(v);\r
+ if (x == -1.0 && PyErr_Occurred())\r
+ return NULL;\r
+ return PyBool_FromLong((long)Py_IS_NAN(x));\r
+}\r
+\r
+static PyObject *\r
+float_is_finite(PyObject *v)\r
+{\r
+ double x = PyFloat_AsDouble(v);\r
+ if (x == -1.0 && PyErr_Occurred())\r
+ return NULL;\r
+ return PyBool_FromLong((long)Py_IS_FINITE(x));\r
+}\r
+#endif\r
+\r
+static PyObject *\r
+float_trunc(PyObject *v)\r
+{\r
+ double x = PyFloat_AsDouble(v);\r
+ double wholepart; /* integral portion of x, rounded toward 0 */\r
+\r
+ (void)modf(x, &wholepart);\r
+ /* Try to get out cheap if this fits in a Python int. The attempt\r
+ * to cast to long must be protected, as C doesn't define what\r
+ * happens if the double is too big to fit in a long. Some rare\r
+ * systems raise an exception then (RISCOS was mentioned as one,\r
+ * and someone using a non-default option on Sun also bumped into\r
+ * that). Note that checking for <= LONG_MAX is unsafe: if a long\r
+ * has more bits of precision than a double, casting LONG_MAX to\r
+ * double may yield an approximation, and if that's rounded up,\r
+ * then, e.g., wholepart=LONG_MAX+1 would yield true from the C\r
+ * expression wholepart<=LONG_MAX, despite that wholepart is\r
+ * actually greater than LONG_MAX. However, assuming a two's complement\r
+ * machine with no trap representation, LONG_MIN will be a power of 2 (and\r
+ * hence exactly representable as a double), and LONG_MAX = -1-LONG_MIN, so\r
+ * the comparisons with (double)LONG_MIN below should be safe.\r
+ */\r
+ if ((double)LONG_MIN <= wholepart && wholepart < -(double)LONG_MIN) {\r
+ const long aslong = (long)wholepart;\r
+ return PyInt_FromLong(aslong);\r
+ }\r
+ return PyLong_FromDouble(wholepart);\r
+}\r
+\r
+static PyObject *\r
+float_long(PyObject *v)\r
+{\r
+ double x = PyFloat_AsDouble(v);\r
+ return PyLong_FromDouble(x);\r
+}\r
+\r
+/* _Py_double_round: rounds a finite nonzero double to the closest multiple of\r
+ 10**-ndigits; here ndigits is within reasonable bounds (typically, -308 <=\r
+ ndigits <= 323). Returns a Python float, or sets a Python error and\r
+ returns NULL on failure (OverflowError and memory errors are possible). */\r
+\r
+#ifndef PY_NO_SHORT_FLOAT_REPR\r
+/* version of _Py_double_round that uses the correctly-rounded string<->double\r
+ conversions from Python/dtoa.c */\r
+\r
+/* FIVE_POW_LIMIT is the largest k such that 5**k is exactly representable as\r
+ a double. Since we're using the code in Python/dtoa.c, it should be safe\r
+ to assume that C doubles are IEEE 754 binary64 format. To be on the safe\r
+ side, we check this. */\r
+#if DBL_MANT_DIG == 53\r
+#define FIVE_POW_LIMIT 22\r
+#else\r
+#error "C doubles do not appear to be IEEE 754 binary64 format"\r
+#endif\r
+\r
+PyObject *\r
+_Py_double_round(double x, int ndigits) {\r
+\r
+ double rounded, m;\r
+ Py_ssize_t buflen, mybuflen=100;\r
+ char *buf, *buf_end, shortbuf[100], *mybuf=shortbuf;\r
+ int decpt, sign, val, halfway_case;\r
+ PyObject *result = NULL;\r
+ _Py_SET_53BIT_PRECISION_HEADER;\r
+\r
+ /* Easy path for the common case ndigits == 0. */\r
+ if (ndigits == 0) {\r
+ rounded = round(x);\r
+ if (fabs(rounded - x) == 0.5)\r
+ /* halfway between two integers; use round-away-from-zero */\r
+ rounded = x + (x > 0.0 ? 0.5 : -0.5);\r
+ return PyFloat_FromDouble(rounded);\r
+ }\r
+\r
+ /* The basic idea is very simple: convert and round the double to a\r
+ decimal string using _Py_dg_dtoa, then convert that decimal string\r
+ back to a double with _Py_dg_strtod. There's one minor difficulty:\r
+ Python 2.x expects round to do round-half-away-from-zero, while\r
+ _Py_dg_dtoa does round-half-to-even. So we need some way to detect\r
+ and correct the halfway cases.\r
+\r
+ Detection: a halfway value has the form k * 0.5 * 10**-ndigits for\r
+ some odd integer k. Or in other words, a rational number x is\r
+ exactly halfway between two multiples of 10**-ndigits if its\r
+ 2-valuation is exactly -ndigits-1 and its 5-valuation is at least\r
+ -ndigits. For ndigits >= 0 the latter condition is automatically\r
+ satisfied for a binary float x, since any such float has\r
+ nonnegative 5-valuation. For 0 > ndigits >= -22, x needs to be an\r
+ integral multiple of 5**-ndigits; we can check this using fmod.\r
+ For -22 > ndigits, there are no halfway cases: 5**23 takes 54 bits\r
+ to represent exactly, so any odd multiple of 0.5 * 10**n for n >=\r
+ 23 takes at least 54 bits of precision to represent exactly.\r
+\r
+ Correction: a simple strategy for dealing with halfway cases is to\r
+ (for the halfway cases only) call _Py_dg_dtoa with an argument of\r
+ ndigits+1 instead of ndigits (thus doing an exact conversion to\r
+ decimal), round the resulting string manually, and then convert\r
+ back using _Py_dg_strtod.\r
+ */\r
+\r
+ /* nans, infinities and zeros should have already been dealt\r
+ with by the caller (in this case, builtin_round) */\r
+ assert(Py_IS_FINITE(x) && x != 0.0);\r
+\r
+ /* find 2-valuation val of x */\r
+ m = frexp(x, &val);\r
+ while (m != floor(m)) {\r
+ m *= 2.0;\r
+ val--;\r
+ }\r
+\r
+ /* determine whether this is a halfway case */\r
+ if (val == -ndigits-1) {\r
+ if (ndigits >= 0)\r
+ halfway_case = 1;\r
+ else if (ndigits >= -FIVE_POW_LIMIT) {\r
+ double five_pow = 1.0;\r
+ int i;\r
+ for (i=0; i < -ndigits; i++)\r
+ five_pow *= 5.0;\r
+ halfway_case = fmod(x, five_pow) == 0.0;\r
+ }\r
+ else\r
+ halfway_case = 0;\r
+ }\r
+ else\r
+ halfway_case = 0;\r
+\r
+ /* round to a decimal string; use an extra place for halfway case */\r
+ _Py_SET_53BIT_PRECISION_START;\r
+ buf = _Py_dg_dtoa(x, 3, ndigits+halfway_case, &decpt, &sign, &buf_end);\r
+ _Py_SET_53BIT_PRECISION_END;\r
+ if (buf == NULL) {\r
+ PyErr_NoMemory();\r
+ return NULL;\r
+ }\r
+ buflen = buf_end - buf;\r
+\r
+ /* in halfway case, do the round-half-away-from-zero manually */\r
+ if (halfway_case) {\r
+ int i, carry;\r
+ /* sanity check: _Py_dg_dtoa should not have stripped\r
+ any zeros from the result: there should be exactly\r
+ ndigits+1 places following the decimal point, and\r
+ the last digit in the buffer should be a '5'.*/\r
+ assert(buflen - decpt == ndigits+1);\r
+ assert(buf[buflen-1] == '5');\r
+\r
+ /* increment and shift right at the same time. */\r
+ decpt += 1;\r
+ carry = 1;\r
+ for (i=buflen-1; i-- > 0;) {\r
+ carry += buf[i] - '0';\r
+ buf[i+1] = carry % 10 + '0';\r
+ carry /= 10;\r
+ }\r
+ buf[0] = carry + '0';\r
+ }\r
+\r
+ /* Get new buffer if shortbuf is too small. Space needed <= buf_end -\r
+ buf + 8: (1 extra for '0', 1 for sign, 5 for exp, 1 for '\0'). */\r
+ if (buflen + 8 > mybuflen) {\r
+ mybuflen = buflen+8;\r
+ mybuf = (char *)PyMem_Malloc(mybuflen);\r
+ if (mybuf == NULL) {\r
+ PyErr_NoMemory();\r
+ goto exit;\r
+ }\r
+ }\r
+ /* copy buf to mybuf, adding exponent, sign and leading 0 */\r
+ PyOS_snprintf(mybuf, mybuflen, "%s0%se%d", (sign ? "-" : ""),\r
+ buf, decpt - (int)buflen);\r
+\r
+ /* and convert the resulting string back to a double */\r
+ errno = 0;\r
+ _Py_SET_53BIT_PRECISION_START;\r
+ rounded = _Py_dg_strtod(mybuf, NULL);\r
+ _Py_SET_53BIT_PRECISION_END;\r
+ if (errno == ERANGE && fabs(rounded) >= 1.)\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "rounded value too large to represent");\r
+ else\r
+ result = PyFloat_FromDouble(rounded);\r
+\r
+ /* done computing value; now clean up */\r
+ if (mybuf != shortbuf)\r
+ PyMem_Free(mybuf);\r
+ exit:\r
+ _Py_dg_freedtoa(buf);\r
+ return result;\r
+}\r
+\r
+#undef FIVE_POW_LIMIT\r
+\r
+#else /* PY_NO_SHORT_FLOAT_REPR */\r
+\r
+/* fallback version, to be used when correctly rounded binary<->decimal\r
+ conversions aren't available */\r
+\r
+PyObject *\r
+_Py_double_round(double x, int ndigits) {\r
+ double pow1, pow2, y, z;\r
+ if (ndigits >= 0) {\r
+ if (ndigits > 22) {\r
+ /* pow1 and pow2 are each safe from overflow, but\r
+ pow1*pow2 ~= pow(10.0, ndigits) might overflow */\r
+ pow1 = pow(10.0, (double)(ndigits-22));\r
+ pow2 = 1e22;\r
+ }\r
+ else {\r
+ pow1 = pow(10.0, (double)ndigits);\r
+ pow2 = 1.0;\r
+ }\r
+ y = (x*pow1)*pow2;\r
+ /* if y overflows, then rounded value is exactly x */\r
+ if (!Py_IS_FINITE(y))\r
+ return PyFloat_FromDouble(x);\r
+ }\r
+ else {\r
+ pow1 = pow(10.0, (double)-ndigits);\r
+ pow2 = 1.0; /* unused; silences a gcc compiler warning */\r
+ y = x / pow1;\r
+ }\r
+\r
+ z = round(y);\r
+ if (fabs(y-z) == 0.5)\r
+ /* halfway between two integers; use round-away-from-zero */\r
+ z = y + copysign(0.5, y);\r
+\r
+ if (ndigits >= 0)\r
+ z = (z / pow2) / pow1;\r
+ else\r
+ z *= pow1;\r
+\r
+ /* if computation resulted in overflow, raise OverflowError */\r
+ if (!Py_IS_FINITE(z)) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "overflow occurred during round");\r
+ return NULL;\r
+ }\r
+\r
+ return PyFloat_FromDouble(z);\r
+}\r
+\r
+#endif /* PY_NO_SHORT_FLOAT_REPR */\r
+\r
+static PyObject *\r
+float_float(PyObject *v)\r
+{\r
+ if (PyFloat_CheckExact(v))\r
+ Py_INCREF(v);\r
+ else\r
+ v = PyFloat_FromDouble(((PyFloatObject *)v)->ob_fval);\r
+ return v;\r
+}\r
+\r
+/* turn ASCII hex characters into integer values and vice versa */\r
+\r
+static char\r
+char_from_hex(int x)\r
+{\r
+ assert(0 <= x && x < 16);\r
+ return "0123456789abcdef"[x];\r
+}\r
+\r
+static int\r
+hex_from_char(char c) {\r
+ int x;\r
+ switch(c) {\r
+ case '0':\r
+ x = 0;\r
+ break;\r
+ case '1':\r
+ x = 1;\r
+ break;\r
+ case '2':\r
+ x = 2;\r
+ break;\r
+ case '3':\r
+ x = 3;\r
+ break;\r
+ case '4':\r
+ x = 4;\r
+ break;\r
+ case '5':\r
+ x = 5;\r
+ break;\r
+ case '6':\r
+ x = 6;\r
+ break;\r
+ case '7':\r
+ x = 7;\r
+ break;\r
+ case '8':\r
+ x = 8;\r
+ break;\r
+ case '9':\r
+ x = 9;\r
+ break;\r
+ case 'a':\r
+ case 'A':\r
+ x = 10;\r
+ break;\r
+ case 'b':\r
+ case 'B':\r
+ x = 11;\r
+ break;\r
+ case 'c':\r
+ case 'C':\r
+ x = 12;\r
+ break;\r
+ case 'd':\r
+ case 'D':\r
+ x = 13;\r
+ break;\r
+ case 'e':\r
+ case 'E':\r
+ x = 14;\r
+ break;\r
+ case 'f':\r
+ case 'F':\r
+ x = 15;\r
+ break;\r
+ default:\r
+ x = -1;\r
+ break;\r
+ }\r
+ return x;\r
+}\r
+\r
+/* convert a float to a hexadecimal string */\r
+\r
+/* TOHEX_NBITS is DBL_MANT_DIG rounded up to the next integer\r
+ of the form 4k+1. */\r
+#define TOHEX_NBITS DBL_MANT_DIG + 3 - (DBL_MANT_DIG+2)%4\r
+\r
+static PyObject *\r
+float_hex(PyObject *v)\r
+{\r
+ double x, m;\r
+ int e, shift, i, si, esign;\r
+ /* Space for 1+(TOHEX_NBITS-1)/4 digits, a decimal point, and the\r
+ trailing NUL byte. */\r
+ char s[(TOHEX_NBITS-1)/4+3];\r
+\r
+ CONVERT_TO_DOUBLE(v, x);\r
+\r
+ if (Py_IS_NAN(x) || Py_IS_INFINITY(x))\r
+ return float_str((PyFloatObject *)v);\r
+\r
+ if (x == 0.0) {\r
+ if (copysign(1.0, x) == -1.0)\r
+ return PyString_FromString("-0x0.0p+0");\r
+ else\r
+ return PyString_FromString("0x0.0p+0");\r
+ }\r
+\r
+ m = frexp(fabs(x), &e);\r
+ shift = 1 - MAX(DBL_MIN_EXP - e, 0);\r
+ m = ldexp(m, shift);\r
+ e -= shift;\r
+\r
+ si = 0;\r
+ s[si] = char_from_hex((int)m);\r
+ si++;\r
+ m -= (int)m;\r
+ s[si] = '.';\r
+ si++;\r
+ for (i=0; i < (TOHEX_NBITS-1)/4; i++) {\r
+ m *= 16.0;\r
+ s[si] = char_from_hex((int)m);\r
+ si++;\r
+ m -= (int)m;\r
+ }\r
+ s[si] = '\0';\r
+\r
+ if (e < 0) {\r
+ esign = (int)'-';\r
+ e = -e;\r
+ }\r
+ else\r
+ esign = (int)'+';\r
+\r
+ if (x < 0.0)\r
+ return PyString_FromFormat("-0x%sp%c%d", s, esign, e);\r
+ else\r
+ return PyString_FromFormat("0x%sp%c%d", s, esign, e);\r
+}\r
+\r
+PyDoc_STRVAR(float_hex_doc,\r
+"float.hex() -> string\n\\r
+\n\\r
+Return a hexadecimal representation of a floating-point number.\n\\r
+>>> (-0.1).hex()\n\\r
+'-0x1.999999999999ap-4'\n\\r
+>>> 3.14159.hex()\n\\r
+'0x1.921f9f01b866ep+1'");\r
+\r
+/* Case-insensitive locale-independent string match used for nan and inf\r
+ detection. t should be lower-case and null-terminated. Return a nonzero\r
+ result if the first strlen(t) characters of s match t and 0 otherwise. */\r
+\r
+static int\r
+case_insensitive_match(const char *s, const char *t)\r
+{\r
+ while(*t && Py_TOLOWER(*s) == *t) {\r
+ s++;\r
+ t++;\r
+ }\r
+ return *t ? 0 : 1;\r
+}\r
+\r
+/* Convert a hexadecimal string to a float. */\r
+\r
+static PyObject *\r
+float_fromhex(PyObject *cls, PyObject *arg)\r
+{\r
+ PyObject *result_as_float, *result;\r
+ double x;\r
+ long exp, top_exp, lsb, key_digit;\r
+ char *s, *coeff_start, *s_store, *coeff_end, *exp_start, *s_end;\r
+ int half_eps, digit, round_up, sign=1;\r
+ Py_ssize_t length, ndigits, fdigits, i;\r
+\r
+ /*\r
+ * For the sake of simplicity and correctness, we impose an artificial\r
+ * limit on ndigits, the total number of hex digits in the coefficient\r
+ * The limit is chosen to ensure that, writing exp for the exponent,\r
+ *\r
+ * (1) if exp > LONG_MAX/2 then the value of the hex string is\r
+ * guaranteed to overflow (provided it's nonzero)\r
+ *\r
+ * (2) if exp < LONG_MIN/2 then the value of the hex string is\r
+ * guaranteed to underflow to 0.\r
+ *\r
+ * (3) if LONG_MIN/2 <= exp <= LONG_MAX/2 then there's no danger of\r
+ * overflow in the calculation of exp and top_exp below.\r
+ *\r
+ * More specifically, ndigits is assumed to satisfy the following\r
+ * inequalities:\r
+ *\r
+ * 4*ndigits <= DBL_MIN_EXP - DBL_MANT_DIG - LONG_MIN/2\r
+ * 4*ndigits <= LONG_MAX/2 + 1 - DBL_MAX_EXP\r
+ *\r
+ * If either of these inequalities is not satisfied, a ValueError is\r
+ * raised. Otherwise, write x for the value of the hex string, and\r
+ * assume x is nonzero. Then\r
+ *\r
+ * 2**(exp-4*ndigits) <= |x| < 2**(exp+4*ndigits).\r
+ *\r
+ * Now if exp > LONG_MAX/2 then:\r
+ *\r
+ * exp - 4*ndigits >= LONG_MAX/2 + 1 - (LONG_MAX/2 + 1 - DBL_MAX_EXP)\r
+ * = DBL_MAX_EXP\r
+ *\r
+ * so |x| >= 2**DBL_MAX_EXP, which is too large to be stored in C\r
+ * double, so overflows. If exp < LONG_MIN/2, then\r
+ *\r
+ * exp + 4*ndigits <= LONG_MIN/2 - 1 + (\r
+ * DBL_MIN_EXP - DBL_MANT_DIG - LONG_MIN/2)\r
+ * = DBL_MIN_EXP - DBL_MANT_DIG - 1\r
+ *\r
+ * and so |x| < 2**(DBL_MIN_EXP-DBL_MANT_DIG-1), hence underflows to 0\r
+ * when converted to a C double.\r
+ *\r
+ * It's easy to show that if LONG_MIN/2 <= exp <= LONG_MAX/2 then both\r
+ * exp+4*ndigits and exp-4*ndigits are within the range of a long.\r
+ */\r
+\r
+ if (PyString_AsStringAndSize(arg, &s, &length))\r
+ return NULL;\r
+ s_end = s + length;\r
+\r
+ /********************\r
+ * Parse the string *\r
+ ********************/\r
+\r
+ /* leading whitespace and optional sign */\r
+ while (Py_ISSPACE(*s))\r
+ s++;\r
+ if (*s == '-') {\r
+ s++;\r
+ sign = -1;\r
+ }\r
+ else if (*s == '+')\r
+ s++;\r
+\r
+ /* infinities and nans */\r
+ if (*s == 'i' || *s == 'I') {\r
+ if (!case_insensitive_match(s+1, "nf"))\r
+ goto parse_error;\r
+ s += 3;\r
+ x = Py_HUGE_VAL;\r
+ if (case_insensitive_match(s, "inity"))\r
+ s += 5;\r
+ goto finished;\r
+ }\r
+ if (*s == 'n' || *s == 'N') {\r
+ if (!case_insensitive_match(s+1, "an"))\r
+ goto parse_error;\r
+ s += 3;\r
+ x = Py_NAN;\r
+ goto finished;\r
+ }\r
+\r
+ /* [0x] */\r
+ s_store = s;\r
+ if (*s == '0') {\r
+ s++;\r
+ if (*s == 'x' || *s == 'X')\r
+ s++;\r
+ else\r
+ s = s_store;\r
+ }\r
+\r
+ /* coefficient: <integer> [. <fraction>] */\r
+ coeff_start = s;\r
+ while (hex_from_char(*s) >= 0)\r
+ s++;\r
+ s_store = s;\r
+ if (*s == '.') {\r
+ s++;\r
+ while (hex_from_char(*s) >= 0)\r
+ s++;\r
+ coeff_end = s-1;\r
+ }\r
+ else\r
+ coeff_end = s;\r
+\r
+ /* ndigits = total # of hex digits; fdigits = # after point */\r
+ ndigits = coeff_end - coeff_start;\r
+ fdigits = coeff_end - s_store;\r
+ if (ndigits == 0)\r
+ goto parse_error;\r
+ if (ndigits > MIN(DBL_MIN_EXP - DBL_MANT_DIG - LONG_MIN/2,\r
+ LONG_MAX/2 + 1 - DBL_MAX_EXP)/4)\r
+ goto insane_length_error;\r
+\r
+ /* [p <exponent>] */\r
+ if (*s == 'p' || *s == 'P') {\r
+ s++;\r
+ exp_start = s;\r
+ if (*s == '-' || *s == '+')\r
+ s++;\r
+ if (!('0' <= *s && *s <= '9'))\r
+ goto parse_error;\r
+ s++;\r
+ while ('0' <= *s && *s <= '9')\r
+ s++;\r
+ exp = strtol(exp_start, NULL, 10);\r
+ }\r
+ else\r
+ exp = 0;\r
+\r
+/* for 0 <= j < ndigits, HEX_DIGIT(j) gives the jth most significant digit */\r
+#define HEX_DIGIT(j) hex_from_char(*((j) < fdigits ? \\r
+ coeff_end-(j) : \\r
+ coeff_end-1-(j)))\r
+\r
+ /*******************************************\r
+ * Compute rounded value of the hex string *\r
+ *******************************************/\r
+\r
+ /* Discard leading zeros, and catch extreme overflow and underflow */\r
+ while (ndigits > 0 && HEX_DIGIT(ndigits-1) == 0)\r
+ ndigits--;\r
+ if (ndigits == 0 || exp < LONG_MIN/2) {\r
+ x = 0.0;\r
+ goto finished;\r
+ }\r
+ if (exp > LONG_MAX/2)\r
+ goto overflow_error;\r
+\r
+ /* Adjust exponent for fractional part. */\r
+ exp = exp - 4*((long)fdigits);\r
+\r
+ /* top_exp = 1 more than exponent of most sig. bit of coefficient */\r
+ top_exp = exp + 4*((long)ndigits - 1);\r
+ for (digit = HEX_DIGIT(ndigits-1); digit != 0; digit /= 2)\r
+ top_exp++;\r
+\r
+ /* catch almost all nonextreme cases of overflow and underflow here */\r
+ if (top_exp < DBL_MIN_EXP - DBL_MANT_DIG) {\r
+ x = 0.0;\r
+ goto finished;\r
+ }\r
+ if (top_exp > DBL_MAX_EXP)\r
+ goto overflow_error;\r
+\r
+ /* lsb = exponent of least significant bit of the *rounded* value.\r
+ This is top_exp - DBL_MANT_DIG unless result is subnormal. */\r
+ lsb = MAX(top_exp, (long)DBL_MIN_EXP) - DBL_MANT_DIG;\r
+\r
+ x = 0.0;\r
+ if (exp >= lsb) {\r
+ /* no rounding required */\r
+ for (i = ndigits-1; i >= 0; i--)\r
+ x = 16.0*x + HEX_DIGIT(i);\r
+ x = ldexp(x, (int)(exp));\r
+ goto finished;\r
+ }\r
+ /* rounding required. key_digit is the index of the hex digit\r
+ containing the first bit to be rounded away. */\r
+ half_eps = 1 << (int)((lsb - exp - 1) % 4);\r
+ key_digit = (lsb - exp - 1) / 4;\r
+ for (i = ndigits-1; i > key_digit; i--)\r
+ x = 16.0*x + HEX_DIGIT(i);\r
+ digit = HEX_DIGIT(key_digit);\r
+ x = 16.0*x + (double)(digit & (16-2*half_eps));\r
+\r
+ /* round-half-even: round up if bit lsb-1 is 1 and at least one of\r
+ bits lsb, lsb-2, lsb-3, lsb-4, ... is 1. */\r
+ if ((digit & half_eps) != 0) {\r
+ round_up = 0;\r
+ if ((digit & (3*half_eps-1)) != 0 ||\r
+ (half_eps == 8 && (HEX_DIGIT(key_digit+1) & 1) != 0))\r
+ round_up = 1;\r
+ else\r
+ for (i = key_digit-1; i >= 0; i--)\r
+ if (HEX_DIGIT(i) != 0) {\r
+ round_up = 1;\r
+ break;\r
+ }\r
+ if (round_up == 1) {\r
+ x += 2*half_eps;\r
+ if (top_exp == DBL_MAX_EXP &&\r
+ x == ldexp((double)(2*half_eps), DBL_MANT_DIG))\r
+ /* overflow corner case: pre-rounded value <\r
+ 2**DBL_MAX_EXP; rounded=2**DBL_MAX_EXP. */\r
+ goto overflow_error;\r
+ }\r
+ }\r
+ x = ldexp(x, (int)(exp+4*key_digit));\r
+\r
+ finished:\r
+ /* optional trailing whitespace leading to the end of the string */\r
+ while (Py_ISSPACE(*s))\r
+ s++;\r
+ if (s != s_end)\r
+ goto parse_error;\r
+ result_as_float = Py_BuildValue("(d)", sign * x);\r
+ if (result_as_float == NULL)\r
+ return NULL;\r
+ result = PyObject_CallObject(cls, result_as_float);\r
+ Py_DECREF(result_as_float);\r
+ return result;\r
+\r
+ overflow_error:\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "hexadecimal value too large to represent as a float");\r
+ return NULL;\r
+\r
+ parse_error:\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "invalid hexadecimal floating-point string");\r
+ return NULL;\r
+\r
+ insane_length_error:\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "hexadecimal string too long to convert");\r
+ return NULL;\r
+}\r
+\r
+PyDoc_STRVAR(float_fromhex_doc,\r
+"float.fromhex(string) -> float\n\\r
+\n\\r
+Create a floating-point number from a hexadecimal string.\n\\r
+>>> float.fromhex('0x1.ffffp10')\n\\r
+2047.984375\n\\r
+>>> float.fromhex('-0x1p-1074')\n\\r
+-4.9406564584124654e-324");\r
+\r
+\r
+static PyObject *\r
+float_as_integer_ratio(PyObject *v, PyObject *unused)\r
+{\r
+ double self;\r
+ double float_part;\r
+ int exponent;\r
+ int i;\r
+\r
+ PyObject *prev;\r
+ PyObject *py_exponent = NULL;\r
+ PyObject *numerator = NULL;\r
+ PyObject *denominator = NULL;\r
+ PyObject *result_pair = NULL;\r
+ PyNumberMethods *long_methods = PyLong_Type.tp_as_number;\r
+\r
+#define INPLACE_UPDATE(obj, call) \\r
+ prev = obj; \\r
+ obj = call; \\r
+ Py_DECREF(prev); \\r
+\r
+ CONVERT_TO_DOUBLE(v, self);\r
+\r
+ if (Py_IS_INFINITY(self)) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "Cannot pass infinity to float.as_integer_ratio.");\r
+ return NULL;\r
+ }\r
+#ifdef Py_NAN\r
+ if (Py_IS_NAN(self)) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Cannot pass NaN to float.as_integer_ratio.");\r
+ return NULL;\r
+ }\r
+#endif\r
+\r
+ PyFPE_START_PROTECT("as_integer_ratio", goto error);\r
+ float_part = frexp(self, &exponent); /* self == float_part * 2**exponent exactly */\r
+ PyFPE_END_PROTECT(float_part);\r
+\r
+ for (i=0; i<300 && float_part != floor(float_part) ; i++) {\r
+ float_part *= 2.0;\r
+ exponent--;\r
+ }\r
+ /* self == float_part * 2**exponent exactly and float_part is integral.\r
+ If FLT_RADIX != 2, the 300 steps may leave a tiny fractional part\r
+ to be truncated by PyLong_FromDouble(). */\r
+\r
+ numerator = PyLong_FromDouble(float_part);\r
+ if (numerator == NULL) goto error;\r
+\r
+ /* fold in 2**exponent */\r
+ denominator = PyLong_FromLong(1);\r
+ py_exponent = PyLong_FromLong(labs((long)exponent));\r
+ if (py_exponent == NULL) goto error;\r
+ INPLACE_UPDATE(py_exponent,\r
+ long_methods->nb_lshift(denominator, py_exponent));\r
+ if (py_exponent == NULL) goto error;\r
+ if (exponent > 0) {\r
+ INPLACE_UPDATE(numerator,\r
+ long_methods->nb_multiply(numerator, py_exponent));\r
+ if (numerator == NULL) goto error;\r
+ }\r
+ else {\r
+ Py_DECREF(denominator);\r
+ denominator = py_exponent;\r
+ py_exponent = NULL;\r
+ }\r
+\r
+ /* Returns ints instead of longs where possible */\r
+ INPLACE_UPDATE(numerator, PyNumber_Int(numerator));\r
+ if (numerator == NULL) goto error;\r
+ INPLACE_UPDATE(denominator, PyNumber_Int(denominator));\r
+ if (denominator == NULL) goto error;\r
+\r
+ result_pair = PyTuple_Pack(2, numerator, denominator);\r
+\r
+#undef INPLACE_UPDATE\r
+error:\r
+ Py_XDECREF(py_exponent);\r
+ Py_XDECREF(denominator);\r
+ Py_XDECREF(numerator);\r
+ return result_pair;\r
+}\r
+\r
+PyDoc_STRVAR(float_as_integer_ratio_doc,\r
+"float.as_integer_ratio() -> (int, int)\n"\r
+"\n"\r
+"Return a pair of integers, whose ratio is exactly equal to the original\n"\r
+"float and with a positive denominator.\n"\r
+"Raise OverflowError on infinities and a ValueError on NaNs.\n"\r
+"\n"\r
+">>> (10.0).as_integer_ratio()\n"\r
+"(10, 1)\n"\r
+">>> (0.0).as_integer_ratio()\n"\r
+"(0, 1)\n"\r
+">>> (-.25).as_integer_ratio()\n"\r
+"(-1, 4)");\r
+\r
+\r
+static PyObject *\r
+float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);\r
+\r
+static PyObject *\r
+float_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *x = Py_False; /* Integer zero */\r
+ static char *kwlist[] = {"x", 0};\r
+\r
+ if (type != &PyFloat_Type)\r
+ return float_subtype_new(type, args, kwds); /* Wimp out */\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x))\r
+ return NULL;\r
+ /* If it's a string, but not a string subclass, use\r
+ PyFloat_FromString. */\r
+ if (PyString_CheckExact(x))\r
+ return PyFloat_FromString(x, NULL);\r
+ return PyNumber_Float(x);\r
+}\r
+\r
+/* Wimpy, slow approach to tp_new calls for subtypes of float:\r
+ first create a regular float from whatever arguments we got,\r
+ then allocate a subtype instance and initialize its ob_fval\r
+ from the regular float. The regular float is then thrown away.\r
+*/\r
+static PyObject *\r
+float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *tmp, *newobj;\r
+\r
+ assert(PyType_IsSubtype(type, &PyFloat_Type));\r
+ tmp = float_new(&PyFloat_Type, args, kwds);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ assert(PyFloat_CheckExact(tmp));\r
+ newobj = type->tp_alloc(type, 0);\r
+ if (newobj == NULL) {\r
+ Py_DECREF(tmp);\r
+ return NULL;\r
+ }\r
+ ((PyFloatObject *)newobj)->ob_fval = ((PyFloatObject *)tmp)->ob_fval;\r
+ Py_DECREF(tmp);\r
+ return newobj;\r
+}\r
+\r
+static PyObject *\r
+float_getnewargs(PyFloatObject *v)\r
+{\r
+ return Py_BuildValue("(d)", v->ob_fval);\r
+}\r
+\r
+/* this is for the benefit of the pack/unpack routines below */\r
+\r
+typedef enum {\r
+ unknown_format, ieee_big_endian_format, ieee_little_endian_format\r
+} float_format_type;\r
+\r
+static float_format_type double_format, float_format;\r
+static float_format_type detected_double_format, detected_float_format;\r
+\r
+static PyObject *\r
+float_getformat(PyTypeObject *v, PyObject* arg)\r
+{\r
+ char* s;\r
+ float_format_type r;\r
+\r
+ if (!PyString_Check(arg)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__getformat__() argument must be string, not %.500s",\r
+ Py_TYPE(arg)->tp_name);\r
+ return NULL;\r
+ }\r
+ s = PyString_AS_STRING(arg);\r
+ if (strcmp(s, "double") == 0) {\r
+ r = double_format;\r
+ }\r
+ else if (strcmp(s, "float") == 0) {\r
+ r = float_format;\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "__getformat__() argument 1 must be "\r
+ "'double' or 'float'");\r
+ return NULL;\r
+ }\r
+\r
+ switch (r) {\r
+ case unknown_format:\r
+ return PyString_FromString("unknown");\r
+ case ieee_little_endian_format:\r
+ return PyString_FromString("IEEE, little-endian");\r
+ case ieee_big_endian_format:\r
+ return PyString_FromString("IEEE, big-endian");\r
+ default:\r
+ Py_FatalError("insane float_format or double_format");\r
+ return NULL;\r
+ }\r
+}\r
+\r
+PyDoc_STRVAR(float_getformat_doc,\r
+"float.__getformat__(typestr) -> string\n"\r
+"\n"\r
+"You probably don't want to use this function. It exists mainly to be\n"\r
+"used in Python's test suite.\n"\r
+"\n"\r
+"typestr must be 'double' or 'float'. This function returns whichever of\n"\r
+"'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the\n"\r
+"format of floating point numbers used by the C type named by typestr.");\r
+\r
+static PyObject *\r
+float_setformat(PyTypeObject *v, PyObject* args)\r
+{\r
+ char* typestr;\r
+ char* format;\r
+ float_format_type f;\r
+ float_format_type detected;\r
+ float_format_type *p;\r
+\r
+ if (!PyArg_ParseTuple(args, "ss:__setformat__", &typestr, &format))\r
+ return NULL;\r
+\r
+ if (strcmp(typestr, "double") == 0) {\r
+ p = &double_format;\r
+ detected = detected_double_format;\r
+ }\r
+ else if (strcmp(typestr, "float") == 0) {\r
+ p = &float_format;\r
+ detected = detected_float_format;\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "__setformat__() argument 1 must "\r
+ "be 'double' or 'float'");\r
+ return NULL;\r
+ }\r
+\r
+ if (strcmp(format, "unknown") == 0) {\r
+ f = unknown_format;\r
+ }\r
+ else if (strcmp(format, "IEEE, little-endian") == 0) {\r
+ f = ieee_little_endian_format;\r
+ }\r
+ else if (strcmp(format, "IEEE, big-endian") == 0) {\r
+ f = ieee_big_endian_format;\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "__setformat__() argument 2 must be "\r
+ "'unknown', 'IEEE, little-endian' or "\r
+ "'IEEE, big-endian'");\r
+ return NULL;\r
+\r
+ }\r
+\r
+ if (f != unknown_format && f != detected) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "can only set %s format to 'unknown' or the "\r
+ "detected platform value", typestr);\r
+ return NULL;\r
+ }\r
+\r
+ *p = f;\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(float_setformat_doc,\r
+"float.__setformat__(typestr, fmt) -> None\n"\r
+"\n"\r
+"You probably don't want to use this function. It exists mainly to be\n"\r
+"used in Python's test suite.\n"\r
+"\n"\r
+"typestr must be 'double' or 'float'. fmt must be one of 'unknown',\n"\r
+"'IEEE, big-endian' or 'IEEE, little-endian', and in addition can only be\n"\r
+"one of the latter two if it appears to match the underlying C reality.\n"\r
+"\n"\r
+"Override the automatic determination of C-level floating point type.\n"\r
+"This affects how floats are converted to and from binary strings.");\r
+\r
+static PyObject *\r
+float_getzero(PyObject *v, void *closure)\r
+{\r
+ return PyFloat_FromDouble(0.0);\r
+}\r
+\r
+static PyObject *\r
+float__format__(PyObject *self, PyObject *args)\r
+{\r
+ PyObject *format_spec;\r
+\r
+ if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))\r
+ return NULL;\r
+ if (PyBytes_Check(format_spec))\r
+ return _PyFloat_FormatAdvanced(self,\r
+ PyBytes_AS_STRING(format_spec),\r
+ PyBytes_GET_SIZE(format_spec));\r
+ if (PyUnicode_Check(format_spec)) {\r
+ /* Convert format_spec to a str */\r
+ PyObject *result;\r
+ PyObject *str_spec = PyObject_Str(format_spec);\r
+\r
+ if (str_spec == NULL)\r
+ return NULL;\r
+\r
+ result = _PyFloat_FormatAdvanced(self,\r
+ PyBytes_AS_STRING(str_spec),\r
+ PyBytes_GET_SIZE(str_spec));\r
+\r
+ Py_DECREF(str_spec);\r
+ return result;\r
+ }\r
+ PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");\r
+ return NULL;\r
+}\r
+\r
+PyDoc_STRVAR(float__format__doc,\r
+"float.__format__(format_spec) -> string\n"\r
+"\n"\r
+"Formats the float according to format_spec.");\r
+\r
+\r
+static PyMethodDef float_methods[] = {\r
+ {"conjugate", (PyCFunction)float_float, METH_NOARGS,\r
+ "Return self, the complex conjugate of any float."},\r
+ {"__trunc__", (PyCFunction)float_trunc, METH_NOARGS,\r
+ "Return the Integral closest to x between 0 and x."},\r
+ {"as_integer_ratio", (PyCFunction)float_as_integer_ratio, METH_NOARGS,\r
+ float_as_integer_ratio_doc},\r
+ {"fromhex", (PyCFunction)float_fromhex,\r
+ METH_O|METH_CLASS, float_fromhex_doc},\r
+ {"hex", (PyCFunction)float_hex,\r
+ METH_NOARGS, float_hex_doc},\r
+ {"is_integer", (PyCFunction)float_is_integer, METH_NOARGS,\r
+ "Return True if the float is an integer."},\r
+#if 0\r
+ {"is_inf", (PyCFunction)float_is_inf, METH_NOARGS,\r
+ "Return True if the float is positive or negative infinite."},\r
+ {"is_finite", (PyCFunction)float_is_finite, METH_NOARGS,\r
+ "Return True if the float is finite, neither infinite nor NaN."},\r
+ {"is_nan", (PyCFunction)float_is_nan, METH_NOARGS,\r
+ "Return True if the float is not a number (NaN)."},\r
+#endif\r
+ {"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS},\r
+ {"__getformat__", (PyCFunction)float_getformat,\r
+ METH_O|METH_CLASS, float_getformat_doc},\r
+ {"__setformat__", (PyCFunction)float_setformat,\r
+ METH_VARARGS|METH_CLASS, float_setformat_doc},\r
+ {"__format__", (PyCFunction)float__format__,\r
+ METH_VARARGS, float__format__doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyGetSetDef float_getset[] = {\r
+ {"real",\r
+ (getter)float_float, (setter)NULL,\r
+ "the real part of a complex number",\r
+ NULL},\r
+ {"imag",\r
+ (getter)float_getzero, (setter)NULL,\r
+ "the imaginary part of a complex number",\r
+ NULL},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+PyDoc_STRVAR(float_doc,\r
+"float(x) -> floating point number\n\\r
+\n\\r
+Convert a string or number to a floating point number, if possible.");\r
+\r
+\r
+static PyNumberMethods float_as_number = {\r
+ float_add, /*nb_add*/\r
+ float_sub, /*nb_subtract*/\r
+ float_mul, /*nb_multiply*/\r
+ float_classic_div, /*nb_divide*/\r
+ float_rem, /*nb_remainder*/\r
+ float_divmod, /*nb_divmod*/\r
+ float_pow, /*nb_power*/\r
+ (unaryfunc)float_neg, /*nb_negative*/\r
+ (unaryfunc)float_float, /*nb_positive*/\r
+ (unaryfunc)float_abs, /*nb_absolute*/\r
+ (inquiry)float_nonzero, /*nb_nonzero*/\r
+ 0, /*nb_invert*/\r
+ 0, /*nb_lshift*/\r
+ 0, /*nb_rshift*/\r
+ 0, /*nb_and*/\r
+ 0, /*nb_xor*/\r
+ 0, /*nb_or*/\r
+ float_coerce, /*nb_coerce*/\r
+ float_trunc, /*nb_int*/\r
+ float_long, /*nb_long*/\r
+ float_float, /*nb_float*/\r
+ 0, /* nb_oct */\r
+ 0, /* nb_hex */\r
+ 0, /* nb_inplace_add */\r
+ 0, /* nb_inplace_subtract */\r
+ 0, /* nb_inplace_multiply */\r
+ 0, /* nb_inplace_divide */\r
+ 0, /* nb_inplace_remainder */\r
+ 0, /* nb_inplace_power */\r
+ 0, /* nb_inplace_lshift */\r
+ 0, /* nb_inplace_rshift */\r
+ 0, /* nb_inplace_and */\r
+ 0, /* nb_inplace_xor */\r
+ 0, /* nb_inplace_or */\r
+ float_floor_div, /* nb_floor_divide */\r
+ float_div, /* nb_true_divide */\r
+ 0, /* nb_inplace_floor_divide */\r
+ 0, /* nb_inplace_true_divide */\r
+};\r
+\r
+PyTypeObject PyFloat_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "float",\r
+ sizeof(PyFloatObject),\r
+ 0,\r
+ (destructor)float_dealloc, /* tp_dealloc */\r
+ (printfunc)float_print, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)float_repr, /* tp_repr */\r
+ &float_as_number, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)float_hash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ (reprfunc)float_str, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |\r
+ Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ float_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ float_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ float_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ float_getset, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ float_new, /* tp_new */\r
+};\r
+\r
+void\r
+_PyFloat_Init(void)\r
+{\r
+ /* We attempt to determine if this machine is using IEEE\r
+ floating point formats by peering at the bits of some\r
+ carefully chosen values. If it looks like we are on an\r
+ IEEE platform, the float packing/unpacking routines can\r
+ just copy bits, if not they resort to arithmetic & shifts\r
+ and masks. The shifts & masks approach works on all finite\r
+ values, but what happens to infinities, NaNs and signed\r
+ zeroes on packing is an accident, and attempting to unpack\r
+ a NaN or an infinity will raise an exception.\r
+\r
+ Note that if we're on some whacked-out platform which uses\r
+ IEEE formats but isn't strictly little-endian or big-\r
+ endian, we will fall back to the portable shifts & masks\r
+ method. */\r
+\r
+#if SIZEOF_DOUBLE == 8\r
+ {\r
+ double x = 9006104071832581.0;\r
+ if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0)\r
+ detected_double_format = ieee_big_endian_format;\r
+ else if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0)\r
+ detected_double_format = ieee_little_endian_format;\r
+ else\r
+ detected_double_format = unknown_format;\r
+ }\r
+#else\r
+ detected_double_format = unknown_format;\r
+#endif\r
+\r
+#if SIZEOF_FLOAT == 4\r
+ {\r
+ float y = 16711938.0;\r
+ if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0)\r
+ detected_float_format = ieee_big_endian_format;\r
+ else if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0)\r
+ detected_float_format = ieee_little_endian_format;\r
+ else\r
+ detected_float_format = unknown_format;\r
+ }\r
+#else\r
+ detected_float_format = unknown_format;\r
+#endif\r
+\r
+ double_format = detected_double_format;\r
+ float_format = detected_float_format;\r
+\r
+ /* Init float info */\r
+ if (FloatInfoType.tp_name == 0)\r
+ PyStructSequence_InitType(&FloatInfoType, &floatinfo_desc);\r
+}\r
+\r
+int\r
+PyFloat_ClearFreeList(void)\r
+{\r
+ PyFloatObject *p;\r
+ PyFloatBlock *list, *next;\r
+ int i;\r
+ int u; /* remaining unfreed ints per block */\r
+ int freelist_size = 0;\r
+\r
+ list = block_list;\r
+ block_list = NULL;\r
+ free_list = NULL;\r
+ while (list != NULL) {\r
+ u = 0;\r
+ for (i = 0, p = &list->objects[0];\r
+ i < N_FLOATOBJECTS;\r
+ i++, p++) {\r
+ if (PyFloat_CheckExact(p) && Py_REFCNT(p) != 0)\r
+ u++;\r
+ }\r
+ next = list->next;\r
+ if (u) {\r
+ list->next = block_list;\r
+ block_list = list;\r
+ for (i = 0, p = &list->objects[0];\r
+ i < N_FLOATOBJECTS;\r
+ i++, p++) {\r
+ if (!PyFloat_CheckExact(p) ||\r
+ Py_REFCNT(p) == 0) {\r
+ Py_TYPE(p) = (struct _typeobject *)\r
+ free_list;\r
+ free_list = p;\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ PyMem_FREE(list);\r
+ }\r
+ freelist_size += u;\r
+ list = next;\r
+ }\r
+ return freelist_size;\r
+}\r
+\r
+void\r
+PyFloat_Fini(void)\r
+{\r
+ PyFloatObject *p;\r
+ PyFloatBlock *list;\r
+ int i;\r
+ int u; /* total unfreed floats per block */\r
+\r
+ u = PyFloat_ClearFreeList();\r
+\r
+ if (!Py_VerboseFlag)\r
+ return;\r
+ fprintf(stderr, "# cleanup floats");\r
+ if (!u) {\r
+ fprintf(stderr, "\n");\r
+ }\r
+ else {\r
+ fprintf(stderr,\r
+ ": %d unfreed float%s\n",\r
+ u, u == 1 ? "" : "s");\r
+ }\r
+ if (Py_VerboseFlag > 1) {\r
+ list = block_list;\r
+ while (list != NULL) {\r
+ for (i = 0, p = &list->objects[0];\r
+ i < N_FLOATOBJECTS;\r
+ i++, p++) {\r
+ if (PyFloat_CheckExact(p) &&\r
+ Py_REFCNT(p) != 0) {\r
+ char *buf = PyOS_double_to_string(\r
+ PyFloat_AS_DOUBLE(p), 'r',\r
+ 0, 0, NULL);\r
+ if (buf) {\r
+ /* XXX(twouters) cast\r
+ refcount to long\r
+ until %zd is\r
+ universally\r
+ available\r
+ */\r
+ fprintf(stderr,\r
+ "# <float at %p, refcnt=%ld, val=%s>\n",\r
+ p, (long)Py_REFCNT(p), buf);\r
+ PyMem_Free(buf);\r
+ }\r
+ }\r
+ }\r
+ list = list->next;\r
+ }\r
+ }\r
+}\r
+\r
+/*----------------------------------------------------------------------------\r
+ * _PyFloat_{Pack,Unpack}{4,8}. See floatobject.h.\r
+ */\r
+int\r
+_PyFloat_Pack4(double x, unsigned char *p, int le)\r
+{\r
+ if (float_format == unknown_format) {\r
+ unsigned char sign;\r
+ int e;\r
+ double f;\r
+ unsigned int fbits;\r
+ int incr = 1;\r
+\r
+ if (le) {\r
+ p += 3;\r
+ incr = -1;\r
+ }\r
+\r
+ if (x < 0) {\r
+ sign = 1;\r
+ x = -x;\r
+ }\r
+ else\r
+ sign = 0;\r
+\r
+ f = frexp(x, &e);\r
+\r
+ /* Normalize f to be in the range [1.0, 2.0) */\r
+ if (0.5 <= f && f < 1.0) {\r
+ f *= 2.0;\r
+ e--;\r
+ }\r
+ else if (f == 0.0)\r
+ e = 0;\r
+ else {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "frexp() result out of range");\r
+ return -1;\r
+ }\r
+\r
+ if (e >= 128)\r
+ goto Overflow;\r
+ else if (e < -126) {\r
+ /* Gradual underflow */\r
+ f = ldexp(f, 126 + e);\r
+ e = 0;\r
+ }\r
+ else if (!(e == 0 && f == 0.0)) {\r
+ e += 127;\r
+ f -= 1.0; /* Get rid of leading 1 */\r
+ }\r
+\r
+ f *= 8388608.0; /* 2**23 */\r
+ fbits = (unsigned int)(f + 0.5); /* Round */\r
+ assert(fbits <= 8388608);\r
+ if (fbits >> 23) {\r
+ /* The carry propagated out of a string of 23 1 bits. */\r
+ fbits = 0;\r
+ ++e;\r
+ if (e >= 255)\r
+ goto Overflow;\r
+ }\r
+\r
+ /* First byte */\r
+ *p = (sign << 7) | (e >> 1);\r
+ p += incr;\r
+\r
+ /* Second byte */\r
+ *p = (char) (((e & 1) << 7) | (fbits >> 16));\r
+ p += incr;\r
+\r
+ /* Third byte */\r
+ *p = (fbits >> 8) & 0xFF;\r
+ p += incr;\r
+\r
+ /* Fourth byte */\r
+ *p = fbits & 0xFF;\r
+\r
+ /* Done */\r
+ return 0;\r
+\r
+ }\r
+ else {\r
+ float y = (float)x;\r
+ const char *s = (char*)&y;\r
+ int i, incr = 1;\r
+\r
+ if (Py_IS_INFINITY(y) && !Py_IS_INFINITY(x))\r
+ goto Overflow;\r
+\r
+ if ((float_format == ieee_little_endian_format && !le)\r
+ || (float_format == ieee_big_endian_format && le)) {\r
+ p += 3;\r
+ incr = -1;\r
+ }\r
+\r
+ for (i = 0; i < 4; i++) {\r
+ *p = *s++;\r
+ p += incr;\r
+ }\r
+ return 0;\r
+ }\r
+ Overflow:\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "float too large to pack with f format");\r
+ return -1;\r
+}\r
+\r
+int\r
+_PyFloat_Pack8(double x, unsigned char *p, int le)\r
+{\r
+ if (double_format == unknown_format) {\r
+ unsigned char sign;\r
+ int e;\r
+ double f;\r
+ unsigned int fhi, flo;\r
+ int incr = 1;\r
+\r
+ if (le) {\r
+ p += 7;\r
+ incr = -1;\r
+ }\r
+\r
+ if (x < 0) {\r
+ sign = 1;\r
+ x = -x;\r
+ }\r
+ else\r
+ sign = 0;\r
+\r
+ f = frexp(x, &e);\r
+\r
+ /* Normalize f to be in the range [1.0, 2.0) */\r
+ if (0.5 <= f && f < 1.0) {\r
+ f *= 2.0;\r
+ e--;\r
+ }\r
+ else if (f == 0.0)\r
+ e = 0;\r
+ else {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "frexp() result out of range");\r
+ return -1;\r
+ }\r
+\r
+ if (e >= 1024)\r
+ goto Overflow;\r
+ else if (e < -1022) {\r
+ /* Gradual underflow */\r
+ f = ldexp(f, 1022 + e);\r
+ e = 0;\r
+ }\r
+ else if (!(e == 0 && f == 0.0)) {\r
+ e += 1023;\r
+ f -= 1.0; /* Get rid of leading 1 */\r
+ }\r
+\r
+ /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */\r
+ f *= 268435456.0; /* 2**28 */\r
+ fhi = (unsigned int)f; /* Truncate */\r
+ assert(fhi < 268435456);\r
+\r
+ f -= (double)fhi;\r
+ f *= 16777216.0; /* 2**24 */\r
+ flo = (unsigned int)(f + 0.5); /* Round */\r
+ assert(flo <= 16777216);\r
+ if (flo >> 24) {\r
+ /* The carry propagated out of a string of 24 1 bits. */\r
+ flo = 0;\r
+ ++fhi;\r
+ if (fhi >> 28) {\r
+ /* And it also progagated out of the next 28 bits. */\r
+ fhi = 0;\r
+ ++e;\r
+ if (e >= 2047)\r
+ goto Overflow;\r
+ }\r
+ }\r
+\r
+ /* First byte */\r
+ *p = (sign << 7) | (e >> 4);\r
+ p += incr;\r
+\r
+ /* Second byte */\r
+ *p = (unsigned char) (((e & 0xF) << 4) | (fhi >> 24));\r
+ p += incr;\r
+\r
+ /* Third byte */\r
+ *p = (fhi >> 16) & 0xFF;\r
+ p += incr;\r
+\r
+ /* Fourth byte */\r
+ *p = (fhi >> 8) & 0xFF;\r
+ p += incr;\r
+\r
+ /* Fifth byte */\r
+ *p = fhi & 0xFF;\r
+ p += incr;\r
+\r
+ /* Sixth byte */\r
+ *p = (flo >> 16) & 0xFF;\r
+ p += incr;\r
+\r
+ /* Seventh byte */\r
+ *p = (flo >> 8) & 0xFF;\r
+ p += incr;\r
+\r
+ /* Eighth byte */\r
+ *p = flo & 0xFF;\r
+ /* p += incr; Unneeded (for now) */\r
+\r
+ /* Done */\r
+ return 0;\r
+\r
+ Overflow:\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "float too large to pack with d format");\r
+ return -1;\r
+ }\r
+ else {\r
+ const char *s = (char*)&x;\r
+ int i, incr = 1;\r
+\r
+ if ((double_format == ieee_little_endian_format && !le)\r
+ || (double_format == ieee_big_endian_format && le)) {\r
+ p += 7;\r
+ incr = -1;\r
+ }\r
+\r
+ for (i = 0; i < 8; i++) {\r
+ *p = *s++;\r
+ p += incr;\r
+ }\r
+ return 0;\r
+ }\r
+}\r
+\r
+double\r
+_PyFloat_Unpack4(const unsigned char *p, int le)\r
+{\r
+ if (float_format == unknown_format) {\r
+ unsigned char sign;\r
+ int e;\r
+ unsigned int f;\r
+ double x;\r
+ int incr = 1;\r
+\r
+ if (le) {\r
+ p += 3;\r
+ incr = -1;\r
+ }\r
+\r
+ /* First byte */\r
+ sign = (*p >> 7) & 1;\r
+ e = (*p & 0x7F) << 1;\r
+ p += incr;\r
+\r
+ /* Second byte */\r
+ e |= (*p >> 7) & 1;\r
+ f = (*p & 0x7F) << 16;\r
+ p += incr;\r
+\r
+ if (e == 255) {\r
+ PyErr_SetString(\r
+ PyExc_ValueError,\r
+ "can't unpack IEEE 754 special value "\r
+ "on non-IEEE platform");\r
+ return -1;\r
+ }\r
+\r
+ /* Third byte */\r
+ f |= *p << 8;\r
+ p += incr;\r
+\r
+ /* Fourth byte */\r
+ f |= *p;\r
+\r
+ x = (double)f / 8388608.0;\r
+\r
+ /* XXX This sadly ignores Inf/NaN issues */\r
+ if (e == 0)\r
+ e = -126;\r
+ else {\r
+ x += 1.0;\r
+ e -= 127;\r
+ }\r
+ x = ldexp(x, e);\r
+\r
+ if (sign)\r
+ x = -x;\r
+\r
+ return x;\r
+ }\r
+ else {\r
+ float x;\r
+\r
+ if ((float_format == ieee_little_endian_format && !le)\r
+ || (float_format == ieee_big_endian_format && le)) {\r
+ char buf[4];\r
+ char *d = &buf[3];\r
+ int i;\r
+\r
+ for (i = 0; i < 4; i++) {\r
+ *d-- = *p++;\r
+ }\r
+ memcpy(&x, buf, 4);\r
+ }\r
+ else {\r
+ memcpy(&x, p, 4);\r
+ }\r
+\r
+ return x;\r
+ }\r
+}\r
+\r
+double\r
+_PyFloat_Unpack8(const unsigned char *p, int le)\r
+{\r
+ if (double_format == unknown_format) {\r
+ unsigned char sign;\r
+ int e;\r
+ unsigned int fhi, flo;\r
+ double x;\r
+ int incr = 1;\r
+\r
+ if (le) {\r
+ p += 7;\r
+ incr = -1;\r
+ }\r
+\r
+ /* First byte */\r
+ sign = (*p >> 7) & 1;\r
+ e = (*p & 0x7F) << 4;\r
+\r
+ p += incr;\r
+\r
+ /* Second byte */\r
+ e |= (*p >> 4) & 0xF;\r
+ fhi = (*p & 0xF) << 24;\r
+ p += incr;\r
+\r
+ if (e == 2047) {\r
+ PyErr_SetString(\r
+ PyExc_ValueError,\r
+ "can't unpack IEEE 754 special value "\r
+ "on non-IEEE platform");\r
+ return -1.0;\r
+ }\r
+\r
+ /* Third byte */\r
+ fhi |= *p << 16;\r
+ p += incr;\r
+\r
+ /* Fourth byte */\r
+ fhi |= *p << 8;\r
+ p += incr;\r
+\r
+ /* Fifth byte */\r
+ fhi |= *p;\r
+ p += incr;\r
+\r
+ /* Sixth byte */\r
+ flo = *p << 16;\r
+ p += incr;\r
+\r
+ /* Seventh byte */\r
+ flo |= *p << 8;\r
+ p += incr;\r
+\r
+ /* Eighth byte */\r
+ flo |= *p;\r
+\r
+ x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */\r
+ x /= 268435456.0; /* 2**28 */\r
+\r
+ if (e == 0)\r
+ e = -1022;\r
+ else {\r
+ x += 1.0;\r
+ e -= 1023;\r
+ }\r
+ x = ldexp(x, e);\r
+\r
+ if (sign)\r
+ x = -x;\r
+\r
+ return x;\r
+ }\r
+ else {\r
+ double x;\r
+\r
+ if ((double_format == ieee_little_endian_format && !le)\r
+ || (double_format == ieee_big_endian_format && le)) {\r
+ char buf[8];\r
+ char *d = &buf[7];\r
+ int i;\r
+\r
+ for (i = 0; i < 8; i++) {\r
+ *d-- = *p++;\r
+ }\r
+ memcpy(&x, buf, 8);\r
+ }\r
+ else {\r
+ memcpy(&x, p, 8);\r
+ }\r
+\r
+ return x;\r
+ }\r
+}\r
--- /dev/null
+/* Frame object implementation */\r
+\r
+#include "Python.h"\r
+\r
+#include "code.h"\r
+#include "frameobject.h"\r
+#include "opcode.h"\r
+#include "structmember.h"\r
+\r
+#undef MIN\r
+#undef MAX\r
+#define MIN(a, b) ((a) < (b) ? (a) : (b))\r
+#define MAX(a, b) ((a) > (b) ? (a) : (b))\r
+\r
+#define OFF(x) offsetof(PyFrameObject, x)\r
+\r
+static PyMemberDef frame_memberlist[] = {\r
+ {"f_back", T_OBJECT, OFF(f_back), RO},\r
+ {"f_code", T_OBJECT, OFF(f_code), RO},\r
+ {"f_builtins", T_OBJECT, OFF(f_builtins),RO},\r
+ {"f_globals", T_OBJECT, OFF(f_globals), RO},\r
+ {"f_lasti", T_INT, OFF(f_lasti), RO},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+#define WARN_GET_SET(NAME) \\r
+static PyObject * frame_get_ ## NAME(PyFrameObject *f) { \\r
+ if (PyErr_WarnPy3k(#NAME " has been removed in 3.x", 2) < 0) \\r
+ return NULL; \\r
+ if (f->NAME) { \\r
+ Py_INCREF(f->NAME); \\r
+ return f->NAME; \\r
+ } \\r
+ Py_RETURN_NONE; \\r
+} \\r
+static int frame_set_ ## NAME(PyFrameObject *f, PyObject *new) { \\r
+ if (PyErr_WarnPy3k(#NAME " has been removed in 3.x", 2) < 0) \\r
+ return -1; \\r
+ if (f->NAME) { \\r
+ Py_CLEAR(f->NAME); \\r
+ } \\r
+ if (new == Py_None) \\r
+ new = NULL; \\r
+ Py_XINCREF(new); \\r
+ f->NAME = new; \\r
+ return 0; \\r
+}\r
+\r
+\r
+WARN_GET_SET(f_exc_traceback)\r
+WARN_GET_SET(f_exc_type)\r
+WARN_GET_SET(f_exc_value)\r
+\r
+\r
+static PyObject *\r
+frame_getlocals(PyFrameObject *f, void *closure)\r
+{\r
+ PyFrame_FastToLocals(f);\r
+ Py_INCREF(f->f_locals);\r
+ return f->f_locals;\r
+}\r
+\r
+int\r
+PyFrame_GetLineNumber(PyFrameObject *f)\r
+{\r
+ if (f->f_trace)\r
+ return f->f_lineno;\r
+ else\r
+ return PyCode_Addr2Line(f->f_code, f->f_lasti);\r
+}\r
+\r
+static PyObject *\r
+frame_getlineno(PyFrameObject *f, void *closure)\r
+{\r
+ return PyInt_FromLong(PyFrame_GetLineNumber(f));\r
+}\r
+\r
+/* Setter for f_lineno - you can set f_lineno from within a trace function in\r
+ * order to jump to a given line of code, subject to some restrictions. Most\r
+ * lines are OK to jump to because they don't make any assumptions about the\r
+ * state of the stack (obvious because you could remove the line and the code\r
+ * would still work without any stack errors), but there are some constructs\r
+ * that limit jumping:\r
+ *\r
+ * o Lines with an 'except' statement on them can't be jumped to, because\r
+ * they expect an exception to be on the top of the stack.\r
+ * o Lines that live in a 'finally' block can't be jumped from or to, since\r
+ * the END_FINALLY expects to clean up the stack after the 'try' block.\r
+ * o 'try'/'for'/'while' blocks can't be jumped into because the blockstack\r
+ * needs to be set up before their code runs, and for 'for' loops the\r
+ * iterator needs to be on the stack.\r
+ */\r
+static int\r
+frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)\r
+{\r
+ int new_lineno = 0; /* The new value of f_lineno */\r
+ int new_lasti = 0; /* The new value of f_lasti */\r
+ int new_iblock = 0; /* The new value of f_iblock */\r
+ unsigned char *code = NULL; /* The bytecode for the frame... */\r
+ Py_ssize_t code_len = 0; /* ...and its length */\r
+ unsigned char *lnotab = NULL; /* Iterating over co_lnotab */\r
+ Py_ssize_t lnotab_len = 0; /* (ditto) */\r
+ int offset = 0; /* (ditto) */\r
+ int line = 0; /* (ditto) */\r
+ int addr = 0; /* (ditto) */\r
+ int min_addr = 0; /* Scanning the SETUPs and POPs */\r
+ int max_addr = 0; /* (ditto) */\r
+ int delta_iblock = 0; /* (ditto) */\r
+ int min_delta_iblock = 0; /* (ditto) */\r
+ int min_iblock = 0; /* (ditto) */\r
+ int f_lasti_setup_addr = 0; /* Policing no-jump-into-finally */\r
+ int new_lasti_setup_addr = 0; /* (ditto) */\r
+ int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */\r
+ int in_finally[CO_MAXBLOCKS]; /* (ditto) */\r
+ int blockstack_top = 0; /* (ditto) */\r
+ unsigned char setup_op = 0; /* (ditto) */\r
+\r
+ /* f_lineno must be an integer. */\r
+ if (!PyInt_Check(p_new_lineno)) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "lineno must be an integer");\r
+ return -1;\r
+ }\r
+\r
+ /* You can only do this from within a trace function, not via\r
+ * _getframe or similar hackery. */\r
+ if (!f->f_trace)\r
+ {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "f_lineno can only be set by a"\r
+ " line trace function");\r
+ return -1;\r
+ }\r
+\r
+ /* Fail if the line comes before the start of the code block. */\r
+ new_lineno = (int) PyInt_AsLong(p_new_lineno);\r
+ if (new_lineno < f->f_code->co_firstlineno) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "line %d comes before the current code block",\r
+ new_lineno);\r
+ return -1;\r
+ }\r
+ else if (new_lineno == f->f_code->co_firstlineno) {\r
+ new_lasti = 0;\r
+ new_lineno = f->f_code->co_firstlineno;\r
+ }\r
+ else {\r
+ /* Find the bytecode offset for the start of the given\r
+ * line, or the first code-owning line after it. */\r
+ char *tmp;\r
+ PyString_AsStringAndSize(f->f_code->co_lnotab,\r
+ &tmp, &lnotab_len);\r
+ lnotab = (unsigned char *) tmp;\r
+ addr = 0;\r
+ line = f->f_code->co_firstlineno;\r
+ new_lasti = -1;\r
+ for (offset = 0; offset < lnotab_len; offset += 2) {\r
+ addr += lnotab[offset];\r
+ line += lnotab[offset+1];\r
+ if (line >= new_lineno) {\r
+ new_lasti = addr;\r
+ new_lineno = line;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* If we didn't reach the requested line, return an error. */\r
+ if (new_lasti == -1) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "line %d comes after the current code block",\r
+ new_lineno);\r
+ return -1;\r
+ }\r
+\r
+ /* We're now ready to look at the bytecode. */\r
+ PyString_AsStringAndSize(f->f_code->co_code, (char **)&code, &code_len);\r
+ min_addr = MIN(new_lasti, f->f_lasti);\r
+ max_addr = MAX(new_lasti, f->f_lasti);\r
+\r
+ /* You can't jump onto a line with an 'except' statement on it -\r
+ * they expect to have an exception on the top of the stack, which\r
+ * won't be true if you jump to them. They always start with code\r
+ * that either pops the exception using POP_TOP (plain 'except:'\r
+ * lines do this) or duplicates the exception on the stack using\r
+ * DUP_TOP (if there's an exception type specified). See compile.c,\r
+ * 'com_try_except' for the full details. There aren't any other\r
+ * cases (AFAIK) where a line's code can start with DUP_TOP or\r
+ * POP_TOP, but if any ever appear, they'll be subject to the same\r
+ * restriction (but with a different error message). */\r
+ if (code[new_lasti] == DUP_TOP || code[new_lasti] == POP_TOP) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "can't jump to 'except' line as there's no exception");\r
+ return -1;\r
+ }\r
+\r
+ /* You can't jump into or out of a 'finally' block because the 'try'\r
+ * block leaves something on the stack for the END_FINALLY to clean\r
+ * up. So we walk the bytecode, maintaining a simulated blockstack.\r
+ * When we reach the old or new address and it's in a 'finally' block\r
+ * we note the address of the corresponding SETUP_FINALLY. The jump\r
+ * is only legal if neither address is in a 'finally' block or\r
+ * they're both in the same one. 'blockstack' is a stack of the\r
+ * bytecode addresses of the SETUP_X opcodes, and 'in_finally' tracks\r
+ * whether we're in a 'finally' block at each blockstack level. */\r
+ f_lasti_setup_addr = -1;\r
+ new_lasti_setup_addr = -1;\r
+ memset(blockstack, '\0', sizeof(blockstack));\r
+ memset(in_finally, '\0', sizeof(in_finally));\r
+ blockstack_top = 0;\r
+ for (addr = 0; addr < code_len; addr++) {\r
+ unsigned char op = code[addr];\r
+ switch (op) {\r
+ case SETUP_LOOP:\r
+ case SETUP_EXCEPT:\r
+ case SETUP_FINALLY:\r
+ case SETUP_WITH:\r
+ blockstack[blockstack_top++] = addr;\r
+ in_finally[blockstack_top-1] = 0;\r
+ break;\r
+\r
+ case POP_BLOCK:\r
+ assert(blockstack_top > 0);\r
+ setup_op = code[blockstack[blockstack_top-1]];\r
+ if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) {\r
+ in_finally[blockstack_top-1] = 1;\r
+ }\r
+ else {\r
+ blockstack_top--;\r
+ }\r
+ break;\r
+\r
+ case END_FINALLY:\r
+ /* Ignore END_FINALLYs for SETUP_EXCEPTs - they exist\r
+ * in the bytecode but don't correspond to an actual\r
+ * 'finally' block. (If blockstack_top is 0, we must\r
+ * be seeing such an END_FINALLY.) */\r
+ if (blockstack_top > 0) {\r
+ setup_op = code[blockstack[blockstack_top-1]];\r
+ if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) {\r
+ blockstack_top--;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+\r
+ /* For the addresses we're interested in, see whether they're\r
+ * within a 'finally' block and if so, remember the address\r
+ * of the SETUP_FINALLY. */\r
+ if (addr == new_lasti || addr == f->f_lasti) {\r
+ int i = 0;\r
+ int setup_addr = -1;\r
+ for (i = blockstack_top-1; i >= 0; i--) {\r
+ if (in_finally[i]) {\r
+ setup_addr = blockstack[i];\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (setup_addr != -1) {\r
+ if (addr == new_lasti) {\r
+ new_lasti_setup_addr = setup_addr;\r
+ }\r
+\r
+ if (addr == f->f_lasti) {\r
+ f_lasti_setup_addr = setup_addr;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (op >= HAVE_ARGUMENT) {\r
+ addr += 2;\r
+ }\r
+ }\r
+\r
+ /* Verify that the blockstack tracking code didn't get lost. */\r
+ assert(blockstack_top == 0);\r
+\r
+ /* After all that, are we jumping into / out of a 'finally' block? */\r
+ if (new_lasti_setup_addr != f_lasti_setup_addr) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "can't jump into or out of a 'finally' block");\r
+ return -1;\r
+ }\r
+\r
+\r
+ /* Police block-jumping (you can't jump into the middle of a block)\r
+ * and ensure that the blockstack finishes up in a sensible state (by\r
+ * popping any blocks we're jumping out of). We look at all the\r
+ * blockstack operations between the current position and the new\r
+ * one, and keep track of how many blocks we drop out of on the way.\r
+ * By also keeping track of the lowest blockstack position we see, we\r
+ * can tell whether the jump goes into any blocks without coming out\r
+ * again - in that case we raise an exception below. */\r
+ delta_iblock = 0;\r
+ for (addr = min_addr; addr < max_addr; addr++) {\r
+ unsigned char op = code[addr];\r
+ switch (op) {\r
+ case SETUP_LOOP:\r
+ case SETUP_EXCEPT:\r
+ case SETUP_FINALLY:\r
+ case SETUP_WITH:\r
+ delta_iblock++;\r
+ break;\r
+\r
+ case POP_BLOCK:\r
+ delta_iblock--;\r
+ break;\r
+ }\r
+\r
+ min_delta_iblock = MIN(min_delta_iblock, delta_iblock);\r
+\r
+ if (op >= HAVE_ARGUMENT) {\r
+ addr += 2;\r
+ }\r
+ }\r
+\r
+ /* Derive the absolute iblock values from the deltas. */\r
+ min_iblock = f->f_iblock + min_delta_iblock;\r
+ if (new_lasti > f->f_lasti) {\r
+ /* Forwards jump. */\r
+ new_iblock = f->f_iblock + delta_iblock;\r
+ }\r
+ else {\r
+ /* Backwards jump. */\r
+ new_iblock = f->f_iblock - delta_iblock;\r
+ }\r
+\r
+ /* Are we jumping into a block? */\r
+ if (new_iblock > min_iblock) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "can't jump into the middle of a block");\r
+ return -1;\r
+ }\r
+\r
+ /* Pop any blocks that we're jumping out of. */\r
+ while (f->f_iblock > new_iblock) {\r
+ PyTryBlock *b = &f->f_blockstack[--f->f_iblock];\r
+ while ((f->f_stacktop - f->f_valuestack) > b->b_level) {\r
+ PyObject *v = (*--f->f_stacktop);\r
+ Py_DECREF(v);\r
+ }\r
+ }\r
+\r
+ /* Finally set the new f_lineno and f_lasti and return OK. */\r
+ f->f_lineno = new_lineno;\r
+ f->f_lasti = new_lasti;\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+frame_gettrace(PyFrameObject *f, void *closure)\r
+{\r
+ PyObject* trace = f->f_trace;\r
+\r
+ if (trace == NULL)\r
+ trace = Py_None;\r
+\r
+ Py_INCREF(trace);\r
+\r
+ return trace;\r
+}\r
+\r
+static int\r
+frame_settrace(PyFrameObject *f, PyObject* v, void *closure)\r
+{\r
+ PyObject* old_value;\r
+\r
+ /* We rely on f_lineno being accurate when f_trace is set. */\r
+ f->f_lineno = PyFrame_GetLineNumber(f);\r
+\r
+ old_value = f->f_trace;\r
+ Py_XINCREF(v);\r
+ f->f_trace = v;\r
+ Py_XDECREF(old_value);\r
+\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+frame_getrestricted(PyFrameObject *f, void *closure)\r
+{\r
+ return PyBool_FromLong(PyFrame_IsRestricted(f));\r
+}\r
+\r
+static PyGetSetDef frame_getsetlist[] = {\r
+ {"f_locals", (getter)frame_getlocals, NULL, NULL},\r
+ {"f_lineno", (getter)frame_getlineno,\r
+ (setter)frame_setlineno, NULL},\r
+ {"f_trace", (getter)frame_gettrace, (setter)frame_settrace, NULL},\r
+ {"f_restricted",(getter)frame_getrestricted,NULL, NULL},\r
+ {"f_exc_traceback", (getter)frame_get_f_exc_traceback,\r
+ (setter)frame_set_f_exc_traceback, NULL},\r
+ {"f_exc_type", (getter)frame_get_f_exc_type,\r
+ (setter)frame_set_f_exc_type, NULL},\r
+ {"f_exc_value", (getter)frame_get_f_exc_value,\r
+ (setter)frame_set_f_exc_value, NULL},\r
+ {0}\r
+};\r
+\r
+/* Stack frames are allocated and deallocated at a considerable rate.\r
+ In an attempt to improve the speed of function calls, we:\r
+\r
+ 1. Hold a single "zombie" frame on each code object. This retains\r
+ the allocated and initialised frame object from an invocation of\r
+ the code object. The zombie is reanimated the next time we need a\r
+ frame object for that code object. Doing this saves the malloc/\r
+ realloc required when using a free_list frame that isn't the\r
+ correct size. It also saves some field initialisation.\r
+\r
+ In zombie mode, no field of PyFrameObject holds a reference, but\r
+ the following fields are still valid:\r
+\r
+ * ob_type, ob_size, f_code, f_valuestack;\r
+\r
+ * f_locals, f_trace,\r
+ f_exc_type, f_exc_value, f_exc_traceback are NULL;\r
+\r
+ * f_localsplus does not require re-allocation and\r
+ the local variables in f_localsplus are NULL.\r
+\r
+ 2. We also maintain a separate free list of stack frames (just like\r
+ integers are allocated in a special way -- see intobject.c). When\r
+ a stack frame is on the free list, only the following members have\r
+ a meaning:\r
+ ob_type == &Frametype\r
+ f_back next item on free list, or NULL\r
+ f_stacksize size of value stack\r
+ ob_size size of localsplus\r
+ Note that the value and block stacks are preserved -- this can save\r
+ another malloc() call or two (and two free() calls as well!).\r
+ Also note that, unlike for integers, each frame object is a\r
+ malloc'ed object in its own right -- it is only the actual calls to\r
+ malloc() that we are trying to save here, not the administration.\r
+ After all, while a typical program may make millions of calls, a\r
+ call depth of more than 20 or 30 is probably already exceptional\r
+ unless the program contains run-away recursion. I hope.\r
+\r
+ Later, PyFrame_MAXFREELIST was added to bound the # of frames saved on\r
+ free_list. Else programs creating lots of cyclic trash involving\r
+ frames could provoke free_list into growing without bound.\r
+*/\r
+\r
+static PyFrameObject *free_list = NULL;\r
+static int numfree = 0; /* number of frames currently in free_list */\r
+/* max value for numfree */\r
+#define PyFrame_MAXFREELIST 200\r
+\r
+static void\r
+frame_dealloc(PyFrameObject *f)\r
+{\r
+ PyObject **p, **valuestack;\r
+ PyCodeObject *co;\r
+\r
+ PyObject_GC_UnTrack(f);\r
+ Py_TRASHCAN_SAFE_BEGIN(f)\r
+ /* Kill all local variables */\r
+ valuestack = f->f_valuestack;\r
+ for (p = f->f_localsplus; p < valuestack; p++)\r
+ Py_CLEAR(*p);\r
+\r
+ /* Free stack */\r
+ if (f->f_stacktop != NULL) {\r
+ for (p = valuestack; p < f->f_stacktop; p++)\r
+ Py_XDECREF(*p);\r
+ }\r
+\r
+ Py_XDECREF(f->f_back);\r
+ Py_DECREF(f->f_builtins);\r
+ Py_DECREF(f->f_globals);\r
+ Py_CLEAR(f->f_locals);\r
+ Py_CLEAR(f->f_trace);\r
+ Py_CLEAR(f->f_exc_type);\r
+ Py_CLEAR(f->f_exc_value);\r
+ Py_CLEAR(f->f_exc_traceback);\r
+\r
+ co = f->f_code;\r
+ if (co->co_zombieframe == NULL)\r
+ co->co_zombieframe = f;\r
+ else if (numfree < PyFrame_MAXFREELIST) {\r
+ ++numfree;\r
+ f->f_back = free_list;\r
+ free_list = f;\r
+ }\r
+ else\r
+ PyObject_GC_Del(f);\r
+\r
+ Py_DECREF(co);\r
+ Py_TRASHCAN_SAFE_END(f)\r
+}\r
+\r
+static int\r
+frame_traverse(PyFrameObject *f, visitproc visit, void *arg)\r
+{\r
+ PyObject **fastlocals, **p;\r
+ int i, slots;\r
+\r
+ Py_VISIT(f->f_back);\r
+ Py_VISIT(f->f_code);\r
+ Py_VISIT(f->f_builtins);\r
+ Py_VISIT(f->f_globals);\r
+ Py_VISIT(f->f_locals);\r
+ Py_VISIT(f->f_trace);\r
+ Py_VISIT(f->f_exc_type);\r
+ Py_VISIT(f->f_exc_value);\r
+ Py_VISIT(f->f_exc_traceback);\r
+\r
+ /* locals */\r
+ slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);\r
+ fastlocals = f->f_localsplus;\r
+ for (i = slots; --i >= 0; ++fastlocals)\r
+ Py_VISIT(*fastlocals);\r
+\r
+ /* stack */\r
+ if (f->f_stacktop != NULL) {\r
+ for (p = f->f_valuestack; p < f->f_stacktop; p++)\r
+ Py_VISIT(*p);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static void\r
+frame_clear(PyFrameObject *f)\r
+{\r
+ PyObject **fastlocals, **p, **oldtop;\r
+ int i, slots;\r
+\r
+ /* Before anything else, make sure that this frame is clearly marked\r
+ * as being defunct! Else, e.g., a generator reachable from this\r
+ * frame may also point to this frame, believe itself to still be\r
+ * active, and try cleaning up this frame again.\r
+ */\r
+ oldtop = f->f_stacktop;\r
+ f->f_stacktop = NULL;\r
+\r
+ Py_CLEAR(f->f_exc_type);\r
+ Py_CLEAR(f->f_exc_value);\r
+ Py_CLEAR(f->f_exc_traceback);\r
+ Py_CLEAR(f->f_trace);\r
+\r
+ /* locals */\r
+ slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);\r
+ fastlocals = f->f_localsplus;\r
+ for (i = slots; --i >= 0; ++fastlocals)\r
+ Py_CLEAR(*fastlocals);\r
+\r
+ /* stack */\r
+ if (oldtop != NULL) {\r
+ for (p = f->f_valuestack; p < oldtop; p++)\r
+ Py_CLEAR(*p);\r
+ }\r
+}\r
+\r
+static PyObject *\r
+frame_sizeof(PyFrameObject *f)\r
+{\r
+ Py_ssize_t res, extras, ncells, nfrees;\r
+\r
+ ncells = PyTuple_GET_SIZE(f->f_code->co_cellvars);\r
+ nfrees = PyTuple_GET_SIZE(f->f_code->co_freevars);\r
+ extras = f->f_code->co_stacksize + f->f_code->co_nlocals +\r
+ ncells + nfrees;\r
+ /* subtract one as it is already included in PyFrameObject */\r
+ res = sizeof(PyFrameObject) + (extras-1) * sizeof(PyObject *);\r
+\r
+ return PyInt_FromSsize_t(res);\r
+}\r
+\r
+PyDoc_STRVAR(sizeof__doc__,\r
+"F.__sizeof__() -> size of F in memory, in bytes");\r
+\r
+static PyMethodDef frame_methods[] = {\r
+ {"__sizeof__", (PyCFunction)frame_sizeof, METH_NOARGS,\r
+ sizeof__doc__},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyFrame_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "frame",\r
+ sizeof(PyFrameObject),\r
+ sizeof(PyObject *),\r
+ (destructor)frame_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ PyObject_GenericSetAttr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)frame_traverse, /* tp_traverse */\r
+ (inquiry)frame_clear, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ frame_methods, /* tp_methods */\r
+ frame_memberlist, /* tp_members */\r
+ frame_getsetlist, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+};\r
+\r
+static PyObject *builtin_object;\r
+\r
+int _PyFrame_Init()\r
+{\r
+ builtin_object = PyString_InternFromString("__builtins__");\r
+ if (builtin_object == NULL)\r
+ return 0;\r
+ return 1;\r
+}\r
+\r
+PyFrameObject *\r
+PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,\r
+ PyObject *locals)\r
+{\r
+ PyFrameObject *back = tstate->frame;\r
+ PyFrameObject *f;\r
+ PyObject *builtins;\r
+ Py_ssize_t i;\r
+\r
+#ifdef Py_DEBUG\r
+ if (code == NULL || globals == NULL || !PyDict_Check(globals) ||\r
+ (locals != NULL && !PyMapping_Check(locals))) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+#endif\r
+ if (back == NULL || back->f_globals != globals) {\r
+ builtins = PyDict_GetItem(globals, builtin_object);\r
+ if (builtins) {\r
+ if (PyModule_Check(builtins)) {\r
+ builtins = PyModule_GetDict(builtins);\r
+ assert(!builtins || PyDict_Check(builtins));\r
+ }\r
+ else if (!PyDict_Check(builtins))\r
+ builtins = NULL;\r
+ }\r
+ if (builtins == NULL) {\r
+ /* No builtins! Make up a minimal one\r
+ Give them 'None', at least. */\r
+ builtins = PyDict_New();\r
+ if (builtins == NULL ||\r
+ PyDict_SetItemString(\r
+ builtins, "None", Py_None) < 0)\r
+ return NULL;\r
+ }\r
+ else\r
+ Py_INCREF(builtins);\r
+\r
+ }\r
+ else {\r
+ /* If we share the globals, we share the builtins.\r
+ Save a lookup and a call. */\r
+ builtins = back->f_builtins;\r
+ assert(builtins != NULL && PyDict_Check(builtins));\r
+ Py_INCREF(builtins);\r
+ }\r
+ if (code->co_zombieframe != NULL) {\r
+ f = code->co_zombieframe;\r
+ code->co_zombieframe = NULL;\r
+ _Py_NewReference((PyObject *)f);\r
+ assert(f->f_code == code);\r
+ }\r
+ else {\r
+ Py_ssize_t extras, ncells, nfrees;\r
+ ncells = PyTuple_GET_SIZE(code->co_cellvars);\r
+ nfrees = PyTuple_GET_SIZE(code->co_freevars);\r
+ extras = code->co_stacksize + code->co_nlocals + ncells +\r
+ nfrees;\r
+ if (free_list == NULL) {\r
+ f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type,\r
+ extras);\r
+ if (f == NULL) {\r
+ Py_DECREF(builtins);\r
+ return NULL;\r
+ }\r
+ }\r
+ else {\r
+ assert(numfree > 0);\r
+ --numfree;\r
+ f = free_list;\r
+ free_list = free_list->f_back;\r
+ if (Py_SIZE(f) < extras) {\r
+ f = PyObject_GC_Resize(PyFrameObject, f, extras);\r
+ if (f == NULL) {\r
+ Py_DECREF(builtins);\r
+ return NULL;\r
+ }\r
+ }\r
+ _Py_NewReference((PyObject *)f);\r
+ }\r
+\r
+ f->f_code = code;\r
+ extras = code->co_nlocals + ncells + nfrees;\r
+ f->f_valuestack = f->f_localsplus + extras;\r
+ for (i=0; i<extras; i++)\r
+ f->f_localsplus[i] = NULL;\r
+ f->f_locals = NULL;\r
+ f->f_trace = NULL;\r
+ f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL;\r
+ }\r
+ f->f_stacktop = f->f_valuestack;\r
+ f->f_builtins = builtins;\r
+ Py_XINCREF(back);\r
+ f->f_back = back;\r
+ Py_INCREF(code);\r
+ Py_INCREF(globals);\r
+ f->f_globals = globals;\r
+ /* Most functions have CO_NEWLOCALS and CO_OPTIMIZED set. */\r
+ if ((code->co_flags & (CO_NEWLOCALS | CO_OPTIMIZED)) ==\r
+ (CO_NEWLOCALS | CO_OPTIMIZED))\r
+ ; /* f_locals = NULL; will be set by PyFrame_FastToLocals() */\r
+ else if (code->co_flags & CO_NEWLOCALS) {\r
+ locals = PyDict_New();\r
+ if (locals == NULL) {\r
+ Py_DECREF(f);\r
+ return NULL;\r
+ }\r
+ f->f_locals = locals;\r
+ }\r
+ else {\r
+ if (locals == NULL)\r
+ locals = globals;\r
+ Py_INCREF(locals);\r
+ f->f_locals = locals;\r
+ }\r
+ f->f_tstate = tstate;\r
+\r
+ f->f_lasti = -1;\r
+ f->f_lineno = code->co_firstlineno;\r
+ f->f_iblock = 0;\r
+\r
+ _PyObject_GC_TRACK(f);\r
+ return f;\r
+}\r
+\r
+/* Block management */\r
+\r
+void\r
+PyFrame_BlockSetup(PyFrameObject *f, int type, int handler, int level)\r
+{\r
+ PyTryBlock *b;\r
+ if (f->f_iblock >= CO_MAXBLOCKS)\r
+ Py_FatalError("XXX block stack overflow");\r
+ b = &f->f_blockstack[f->f_iblock++];\r
+ b->b_type = type;\r
+ b->b_level = level;\r
+ b->b_handler = handler;\r
+}\r
+\r
+PyTryBlock *\r
+PyFrame_BlockPop(PyFrameObject *f)\r
+{\r
+ PyTryBlock *b;\r
+ if (f->f_iblock <= 0)\r
+ Py_FatalError("XXX block stack underflow");\r
+ b = &f->f_blockstack[--f->f_iblock];\r
+ return b;\r
+}\r
+\r
+/* Convert between "fast" version of locals and dictionary version.\r
+\r
+ map and values are input arguments. map is a tuple of strings.\r
+ values is an array of PyObject*. At index i, map[i] is the name of\r
+ the variable with value values[i]. The function copies the first\r
+ nmap variable from map/values into dict. If values[i] is NULL,\r
+ the variable is deleted from dict.\r
+\r
+ If deref is true, then the values being copied are cell variables\r
+ and the value is extracted from the cell variable before being put\r
+ in dict.\r
+\r
+ Exceptions raised while modifying the dict are silently ignored,\r
+ because there is no good way to report them.\r
+ */\r
+\r
+static void\r
+map_to_dict(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,\r
+ int deref)\r
+{\r
+ Py_ssize_t j;\r
+ assert(PyTuple_Check(map));\r
+ assert(PyDict_Check(dict));\r
+ assert(PyTuple_Size(map) >= nmap);\r
+ for (j = nmap; --j >= 0; ) {\r
+ PyObject *key = PyTuple_GET_ITEM(map, j);\r
+ PyObject *value = values[j];\r
+ assert(PyString_Check(key));\r
+ if (deref) {\r
+ assert(PyCell_Check(value));\r
+ value = PyCell_GET(value);\r
+ }\r
+ if (value == NULL) {\r
+ if (PyObject_DelItem(dict, key) != 0)\r
+ PyErr_Clear();\r
+ }\r
+ else {\r
+ if (PyObject_SetItem(dict, key, value) != 0)\r
+ PyErr_Clear();\r
+ }\r
+ }\r
+}\r
+\r
+/* Copy values from the "locals" dict into the fast locals.\r
+\r
+ dict is an input argument containing string keys representing\r
+ variables names and arbitrary PyObject* as values.\r
+\r
+ map and values are input arguments. map is a tuple of strings.\r
+ values is an array of PyObject*. At index i, map[i] is the name of\r
+ the variable with value values[i]. The function copies the first\r
+ nmap variable from map/values into dict. If values[i] is NULL,\r
+ the variable is deleted from dict.\r
+\r
+ If deref is true, then the values being copied are cell variables\r
+ and the value is extracted from the cell variable before being put\r
+ in dict. If clear is true, then variables in map but not in dict\r
+ are set to NULL in map; if clear is false, variables missing in\r
+ dict are ignored.\r
+\r
+ Exceptions raised while modifying the dict are silently ignored,\r
+ because there is no good way to report them.\r
+*/\r
+\r
+static void\r
+dict_to_map(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,\r
+ int deref, int clear)\r
+{\r
+ Py_ssize_t j;\r
+ assert(PyTuple_Check(map));\r
+ assert(PyDict_Check(dict));\r
+ assert(PyTuple_Size(map) >= nmap);\r
+ for (j = nmap; --j >= 0; ) {\r
+ PyObject *key = PyTuple_GET_ITEM(map, j);\r
+ PyObject *value = PyObject_GetItem(dict, key);\r
+ assert(PyString_Check(key));\r
+ /* We only care about NULLs if clear is true. */\r
+ if (value == NULL) {\r
+ PyErr_Clear();\r
+ if (!clear)\r
+ continue;\r
+ }\r
+ if (deref) {\r
+ assert(PyCell_Check(values[j]));\r
+ if (PyCell_GET(values[j]) != value) {\r
+ if (PyCell_Set(values[j], value) < 0)\r
+ PyErr_Clear();\r
+ }\r
+ } else if (values[j] != value) {\r
+ Py_XINCREF(value);\r
+ Py_XDECREF(values[j]);\r
+ values[j] = value;\r
+ }\r
+ Py_XDECREF(value);\r
+ }\r
+}\r
+\r
+void\r
+PyFrame_FastToLocals(PyFrameObject *f)\r
+{\r
+ /* Merge fast locals into f->f_locals */\r
+ PyObject *locals, *map;\r
+ PyObject **fast;\r
+ PyObject *error_type, *error_value, *error_traceback;\r
+ PyCodeObject *co;\r
+ Py_ssize_t j;\r
+ int ncells, nfreevars;\r
+ if (f == NULL)\r
+ return;\r
+ locals = f->f_locals;\r
+ if (locals == NULL) {\r
+ locals = f->f_locals = PyDict_New();\r
+ if (locals == NULL) {\r
+ PyErr_Clear(); /* Can't report it :-( */\r
+ return;\r
+ }\r
+ }\r
+ co = f->f_code;\r
+ map = co->co_varnames;\r
+ if (!PyTuple_Check(map))\r
+ return;\r
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);\r
+ fast = f->f_localsplus;\r
+ j = PyTuple_GET_SIZE(map);\r
+ if (j > co->co_nlocals)\r
+ j = co->co_nlocals;\r
+ if (co->co_nlocals)\r
+ map_to_dict(map, j, locals, fast, 0);\r
+ ncells = PyTuple_GET_SIZE(co->co_cellvars);\r
+ nfreevars = PyTuple_GET_SIZE(co->co_freevars);\r
+ if (ncells || nfreevars) {\r
+ map_to_dict(co->co_cellvars, ncells,\r
+ locals, fast + co->co_nlocals, 1);\r
+ /* If the namespace is unoptimized, then one of the\r
+ following cases applies:\r
+ 1. It does not contain free variables, because it\r
+ uses import * or is a top-level namespace.\r
+ 2. It is a class namespace.\r
+ We don't want to accidentally copy free variables\r
+ into the locals dict used by the class.\r
+ */\r
+ if (co->co_flags & CO_OPTIMIZED) {\r
+ map_to_dict(co->co_freevars, nfreevars,\r
+ locals, fast + co->co_nlocals + ncells, 1);\r
+ }\r
+ }\r
+ PyErr_Restore(error_type, error_value, error_traceback);\r
+}\r
+\r
+void\r
+PyFrame_LocalsToFast(PyFrameObject *f, int clear)\r
+{\r
+ /* Merge f->f_locals into fast locals */\r
+ PyObject *locals, *map;\r
+ PyObject **fast;\r
+ PyObject *error_type, *error_value, *error_traceback;\r
+ PyCodeObject *co;\r
+ Py_ssize_t j;\r
+ int ncells, nfreevars;\r
+ if (f == NULL)\r
+ return;\r
+ locals = f->f_locals;\r
+ co = f->f_code;\r
+ map = co->co_varnames;\r
+ if (locals == NULL)\r
+ return;\r
+ if (!PyTuple_Check(map))\r
+ return;\r
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);\r
+ fast = f->f_localsplus;\r
+ j = PyTuple_GET_SIZE(map);\r
+ if (j > co->co_nlocals)\r
+ j = co->co_nlocals;\r
+ if (co->co_nlocals)\r
+ dict_to_map(co->co_varnames, j, locals, fast, 0, clear);\r
+ ncells = PyTuple_GET_SIZE(co->co_cellvars);\r
+ nfreevars = PyTuple_GET_SIZE(co->co_freevars);\r
+ if (ncells || nfreevars) {\r
+ dict_to_map(co->co_cellvars, ncells,\r
+ locals, fast + co->co_nlocals, 1, clear);\r
+ /* Same test as in PyFrame_FastToLocals() above. */\r
+ if (co->co_flags & CO_OPTIMIZED) {\r
+ dict_to_map(co->co_freevars, nfreevars,\r
+ locals, fast + co->co_nlocals + ncells, 1,\r
+ clear);\r
+ }\r
+ }\r
+ PyErr_Restore(error_type, error_value, error_traceback);\r
+}\r
+\r
+/* Clear out the free list */\r
+int\r
+PyFrame_ClearFreeList(void)\r
+{\r
+ int freelist_size = numfree;\r
+\r
+ while (free_list != NULL) {\r
+ PyFrameObject *f = free_list;\r
+ free_list = free_list->f_back;\r
+ PyObject_GC_Del(f);\r
+ --numfree;\r
+ }\r
+ assert(numfree == 0);\r
+ return freelist_size;\r
+}\r
+\r
+void\r
+PyFrame_Fini(void)\r
+{\r
+ (void)PyFrame_ClearFreeList();\r
+ Py_XDECREF(builtin_object);\r
+ builtin_object = NULL;\r
+}\r
--- /dev/null
+\r
+/* Function object implementation */\r
+\r
+#include "Python.h"\r
+#include "code.h"\r
+#include "eval.h"\r
+#include "structmember.h"\r
+\r
+PyObject *\r
+PyFunction_New(PyObject *code, PyObject *globals)\r
+{\r
+ PyFunctionObject *op = PyObject_GC_New(PyFunctionObject,\r
+ &PyFunction_Type);\r
+ static PyObject *__name__ = 0;\r
+ if (op != NULL) {\r
+ PyObject *doc;\r
+ PyObject *consts;\r
+ PyObject *module;\r
+ op->func_weakreflist = NULL;\r
+ Py_INCREF(code);\r
+ op->func_code = code;\r
+ Py_INCREF(globals);\r
+ op->func_globals = globals;\r
+ op->func_name = ((PyCodeObject *)code)->co_name;\r
+ Py_INCREF(op->func_name);\r
+ op->func_defaults = NULL; /* No default arguments */\r
+ op->func_closure = NULL;\r
+ consts = ((PyCodeObject *)code)->co_consts;\r
+ if (PyTuple_Size(consts) >= 1) {\r
+ doc = PyTuple_GetItem(consts, 0);\r
+ if (!PyString_Check(doc) && !PyUnicode_Check(doc))\r
+ doc = Py_None;\r
+ }\r
+ else\r
+ doc = Py_None;\r
+ Py_INCREF(doc);\r
+ op->func_doc = doc;\r
+ op->func_dict = NULL;\r
+ op->func_module = NULL;\r
+\r
+ /* __module__: If module name is in globals, use it.\r
+ Otherwise, use None.\r
+ */\r
+ if (!__name__) {\r
+ __name__ = PyString_InternFromString("__name__");\r
+ if (!__name__) {\r
+ Py_DECREF(op);\r
+ return NULL;\r
+ }\r
+ }\r
+ module = PyDict_GetItem(globals, __name__);\r
+ if (module) {\r
+ Py_INCREF(module);\r
+ op->func_module = module;\r
+ }\r
+ }\r
+ else\r
+ return NULL;\r
+ _PyObject_GC_TRACK(op);\r
+ return (PyObject *)op;\r
+}\r
+\r
+PyObject *\r
+PyFunction_GetCode(PyObject *op)\r
+{\r
+ if (!PyFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyFunctionObject *) op) -> func_code;\r
+}\r
+\r
+PyObject *\r
+PyFunction_GetGlobals(PyObject *op)\r
+{\r
+ if (!PyFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyFunctionObject *) op) -> func_globals;\r
+}\r
+\r
+PyObject *\r
+PyFunction_GetModule(PyObject *op)\r
+{\r
+ if (!PyFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyFunctionObject *) op) -> func_module;\r
+}\r
+\r
+PyObject *\r
+PyFunction_GetDefaults(PyObject *op)\r
+{\r
+ if (!PyFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyFunctionObject *) op) -> func_defaults;\r
+}\r
+\r
+int\r
+PyFunction_SetDefaults(PyObject *op, PyObject *defaults)\r
+{\r
+ if (!PyFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ if (defaults == Py_None)\r
+ defaults = NULL;\r
+ else if (defaults && PyTuple_Check(defaults)) {\r
+ Py_INCREF(defaults);\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_SystemError, "non-tuple default args");\r
+ return -1;\r
+ }\r
+ Py_XDECREF(((PyFunctionObject *) op) -> func_defaults);\r
+ ((PyFunctionObject *) op) -> func_defaults = defaults;\r
+ return 0;\r
+}\r
+\r
+PyObject *\r
+PyFunction_GetClosure(PyObject *op)\r
+{\r
+ if (!PyFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyFunctionObject *) op) -> func_closure;\r
+}\r
+\r
+int\r
+PyFunction_SetClosure(PyObject *op, PyObject *closure)\r
+{\r
+ if (!PyFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ if (closure == Py_None)\r
+ closure = NULL;\r
+ else if (PyTuple_Check(closure)) {\r
+ Py_INCREF(closure);\r
+ }\r
+ else {\r
+ PyErr_Format(PyExc_SystemError,\r
+ "expected tuple for closure, got '%.100s'",\r
+ closure->ob_type->tp_name);\r
+ return -1;\r
+ }\r
+ Py_XDECREF(((PyFunctionObject *) op) -> func_closure);\r
+ ((PyFunctionObject *) op) -> func_closure = closure;\r
+ return 0;\r
+}\r
+\r
+/* Methods */\r
+\r
+#define OFF(x) offsetof(PyFunctionObject, x)\r
+\r
+static PyMemberDef func_memberlist[] = {\r
+ {"func_closure", T_OBJECT, OFF(func_closure),\r
+ RESTRICTED|READONLY},\r
+ {"__closure__", T_OBJECT, OFF(func_closure),\r
+ RESTRICTED|READONLY},\r
+ {"func_doc", T_OBJECT, OFF(func_doc), PY_WRITE_RESTRICTED},\r
+ {"__doc__", T_OBJECT, OFF(func_doc), PY_WRITE_RESTRICTED},\r
+ {"func_globals", T_OBJECT, OFF(func_globals),\r
+ RESTRICTED|READONLY},\r
+ {"__globals__", T_OBJECT, OFF(func_globals),\r
+ RESTRICTED|READONLY},\r
+ {"__module__", T_OBJECT, OFF(func_module), PY_WRITE_RESTRICTED},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+static int\r
+restricted(void)\r
+{\r
+ if (!PyEval_GetRestricted())\r
+ return 0;\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "function attributes not accessible in restricted mode");\r
+ return 1;\r
+}\r
+\r
+static PyObject *\r
+func_get_dict(PyFunctionObject *op)\r
+{\r
+ if (restricted())\r
+ return NULL;\r
+ if (op->func_dict == NULL) {\r
+ op->func_dict = PyDict_New();\r
+ if (op->func_dict == NULL)\r
+ return NULL;\r
+ }\r
+ Py_INCREF(op->func_dict);\r
+ return op->func_dict;\r
+}\r
+\r
+static int\r
+func_set_dict(PyFunctionObject *op, PyObject *value)\r
+{\r
+ PyObject *tmp;\r
+\r
+ if (restricted())\r
+ return -1;\r
+ /* It is illegal to del f.func_dict */\r
+ if (value == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "function's dictionary may not be deleted");\r
+ return -1;\r
+ }\r
+ /* Can only set func_dict to a dictionary */\r
+ if (!PyDict_Check(value)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "setting function's dictionary to a non-dict");\r
+ return -1;\r
+ }\r
+ tmp = op->func_dict;\r
+ Py_INCREF(value);\r
+ op->func_dict = value;\r
+ Py_XDECREF(tmp);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+func_get_code(PyFunctionObject *op)\r
+{\r
+ if (restricted())\r
+ return NULL;\r
+ Py_INCREF(op->func_code);\r
+ return op->func_code;\r
+}\r
+\r
+static int\r
+func_set_code(PyFunctionObject *op, PyObject *value)\r
+{\r
+ PyObject *tmp;\r
+ Py_ssize_t nfree, nclosure;\r
+\r
+ if (restricted())\r
+ return -1;\r
+ /* Not legal to del f.func_code or to set it to anything\r
+ * other than a code object. */\r
+ if (value == NULL || !PyCode_Check(value)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__code__ must be set to a code object");\r
+ return -1;\r
+ }\r
+ nfree = PyCode_GetNumFree((PyCodeObject *)value);\r
+ nclosure = (op->func_closure == NULL ? 0 :\r
+ PyTuple_GET_SIZE(op->func_closure));\r
+ if (nclosure != nfree) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "%s() requires a code object with %zd free vars,"\r
+ " not %zd",\r
+ PyString_AsString(op->func_name),\r
+ nclosure, nfree);\r
+ return -1;\r
+ }\r
+ tmp = op->func_code;\r
+ Py_INCREF(value);\r
+ op->func_code = value;\r
+ Py_DECREF(tmp);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+func_get_name(PyFunctionObject *op)\r
+{\r
+ Py_INCREF(op->func_name);\r
+ return op->func_name;\r
+}\r
+\r
+static int\r
+func_set_name(PyFunctionObject *op, PyObject *value)\r
+{\r
+ PyObject *tmp;\r
+\r
+ if (restricted())\r
+ return -1;\r
+ /* Not legal to del f.func_name or to set it to anything\r
+ * other than a string object. */\r
+ if (value == NULL || !PyString_Check(value)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__name__ must be set to a string object");\r
+ return -1;\r
+ }\r
+ tmp = op->func_name;\r
+ Py_INCREF(value);\r
+ op->func_name = value;\r
+ Py_DECREF(tmp);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+func_get_defaults(PyFunctionObject *op)\r
+{\r
+ if (restricted())\r
+ return NULL;\r
+ if (op->func_defaults == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ Py_INCREF(op->func_defaults);\r
+ return op->func_defaults;\r
+}\r
+\r
+static int\r
+func_set_defaults(PyFunctionObject *op, PyObject *value)\r
+{\r
+ PyObject *tmp;\r
+\r
+ if (restricted())\r
+ return -1;\r
+ /* Legal to del f.func_defaults.\r
+ * Can only set func_defaults to NULL or a tuple. */\r
+ if (value == Py_None)\r
+ value = NULL;\r
+ if (value != NULL && !PyTuple_Check(value)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__defaults__ must be set to a tuple object");\r
+ return -1;\r
+ }\r
+ tmp = op->func_defaults;\r
+ Py_XINCREF(value);\r
+ op->func_defaults = value;\r
+ Py_XDECREF(tmp);\r
+ return 0;\r
+}\r
+\r
+static PyGetSetDef func_getsetlist[] = {\r
+ {"func_code", (getter)func_get_code, (setter)func_set_code},\r
+ {"__code__", (getter)func_get_code, (setter)func_set_code},\r
+ {"func_defaults", (getter)func_get_defaults,\r
+ (setter)func_set_defaults},\r
+ {"__defaults__", (getter)func_get_defaults,\r
+ (setter)func_set_defaults},\r
+ {"func_dict", (getter)func_get_dict, (setter)func_set_dict},\r
+ {"__dict__", (getter)func_get_dict, (setter)func_set_dict},\r
+ {"func_name", (getter)func_get_name, (setter)func_set_name},\r
+ {"__name__", (getter)func_get_name, (setter)func_set_name},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+PyDoc_STRVAR(func_doc,\r
+"function(code, globals[, name[, argdefs[, closure]]])\n\\r
+\n\\r
+Create a function object from a code object and a dictionary.\n\\r
+The optional name string overrides the name from the code object.\n\\r
+The optional argdefs tuple specifies the default argument values.\n\\r
+The optional closure tuple supplies the bindings for free variables.");\r
+\r
+/* func_new() maintains the following invariants for closures. The\r
+ closure must correspond to the free variables of the code object.\r
+\r
+ if len(code.co_freevars) == 0:\r
+ closure = NULL\r
+ else:\r
+ len(closure) == len(code.co_freevars)\r
+ for every elt in closure, type(elt) == cell\r
+*/\r
+\r
+static PyObject *\r
+func_new(PyTypeObject* type, PyObject* args, PyObject* kw)\r
+{\r
+ PyCodeObject *code;\r
+ PyObject *globals;\r
+ PyObject *name = Py_None;\r
+ PyObject *defaults = Py_None;\r
+ PyObject *closure = Py_None;\r
+ PyFunctionObject *newfunc;\r
+ Py_ssize_t nfree, nclosure;\r
+ static char *kwlist[] = {"code", "globals", "name",\r
+ "argdefs", "closure", 0};\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!|OOO:function",\r
+ kwlist,\r
+ &PyCode_Type, &code,\r
+ &PyDict_Type, &globals,\r
+ &name, &defaults, &closure))\r
+ return NULL;\r
+ if (name != Py_None && !PyString_Check(name)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "arg 3 (name) must be None or string");\r
+ return NULL;\r
+ }\r
+ if (defaults != Py_None && !PyTuple_Check(defaults)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "arg 4 (defaults) must be None or tuple");\r
+ return NULL;\r
+ }\r
+ nfree = PyTuple_GET_SIZE(code->co_freevars);\r
+ if (!PyTuple_Check(closure)) {\r
+ if (nfree && closure == Py_None) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "arg 5 (closure) must be tuple");\r
+ return NULL;\r
+ }\r
+ else if (closure != Py_None) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "arg 5 (closure) must be None or tuple");\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ /* check that the closure is well-formed */\r
+ nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure);\r
+ if (nfree != nclosure)\r
+ return PyErr_Format(PyExc_ValueError,\r
+ "%s requires closure of length %zd, not %zd",\r
+ PyString_AS_STRING(code->co_name),\r
+ nfree, nclosure);\r
+ if (nclosure) {\r
+ Py_ssize_t i;\r
+ for (i = 0; i < nclosure; i++) {\r
+ PyObject *o = PyTuple_GET_ITEM(closure, i);\r
+ if (!PyCell_Check(o)) {\r
+ return PyErr_Format(PyExc_TypeError,\r
+ "arg 5 (closure) expected cell, found %s",\r
+ o->ob_type->tp_name);\r
+ }\r
+ }\r
+ }\r
+\r
+ newfunc = (PyFunctionObject *)PyFunction_New((PyObject *)code,\r
+ globals);\r
+ if (newfunc == NULL)\r
+ return NULL;\r
+\r
+ if (name != Py_None) {\r
+ Py_INCREF(name);\r
+ Py_DECREF(newfunc->func_name);\r
+ newfunc->func_name = name;\r
+ }\r
+ if (defaults != Py_None) {\r
+ Py_INCREF(defaults);\r
+ newfunc->func_defaults = defaults;\r
+ }\r
+ if (closure != Py_None) {\r
+ Py_INCREF(closure);\r
+ newfunc->func_closure = closure;\r
+ }\r
+\r
+ return (PyObject *)newfunc;\r
+}\r
+\r
+static void\r
+func_dealloc(PyFunctionObject *op)\r
+{\r
+ _PyObject_GC_UNTRACK(op);\r
+ if (op->func_weakreflist != NULL)\r
+ PyObject_ClearWeakRefs((PyObject *) op);\r
+ Py_DECREF(op->func_code);\r
+ Py_DECREF(op->func_globals);\r
+ Py_XDECREF(op->func_module);\r
+ Py_DECREF(op->func_name);\r
+ Py_XDECREF(op->func_defaults);\r
+ Py_XDECREF(op->func_doc);\r
+ Py_XDECREF(op->func_dict);\r
+ Py_XDECREF(op->func_closure);\r
+ PyObject_GC_Del(op);\r
+}\r
+\r
+static PyObject*\r
+func_repr(PyFunctionObject *op)\r
+{\r
+ return PyString_FromFormat("<function %s at %p>",\r
+ PyString_AsString(op->func_name),\r
+ op);\r
+}\r
+\r
+static int\r
+func_traverse(PyFunctionObject *f, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(f->func_code);\r
+ Py_VISIT(f->func_globals);\r
+ Py_VISIT(f->func_module);\r
+ Py_VISIT(f->func_defaults);\r
+ Py_VISIT(f->func_doc);\r
+ Py_VISIT(f->func_name);\r
+ Py_VISIT(f->func_dict);\r
+ Py_VISIT(f->func_closure);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+function_call(PyObject *func, PyObject *arg, PyObject *kw)\r
+{\r
+ PyObject *result;\r
+ PyObject *argdefs;\r
+ PyObject *kwtuple = NULL;\r
+ PyObject **d, **k;\r
+ Py_ssize_t nk, nd;\r
+\r
+ argdefs = PyFunction_GET_DEFAULTS(func);\r
+ if (argdefs != NULL && PyTuple_Check(argdefs)) {\r
+ d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0);\r
+ nd = PyTuple_GET_SIZE(argdefs);\r
+ }\r
+ else {\r
+ d = NULL;\r
+ nd = 0;\r
+ }\r
+\r
+ if (kw != NULL && PyDict_Check(kw)) {\r
+ Py_ssize_t pos, i;\r
+ nk = PyDict_Size(kw);\r
+ kwtuple = PyTuple_New(2*nk);\r
+ if (kwtuple == NULL)\r
+ return NULL;\r
+ k = &PyTuple_GET_ITEM(kwtuple, 0);\r
+ pos = i = 0;\r
+ while (PyDict_Next(kw, &pos, &k[i], &k[i+1])) {\r
+ Py_INCREF(k[i]);\r
+ Py_INCREF(k[i+1]);\r
+ i += 2;\r
+ }\r
+ nk = i/2;\r
+ }\r
+ else {\r
+ k = NULL;\r
+ nk = 0;\r
+ }\r
+\r
+ result = PyEval_EvalCodeEx(\r
+ (PyCodeObject *)PyFunction_GET_CODE(func),\r
+ PyFunction_GET_GLOBALS(func), (PyObject *)NULL,\r
+ &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg),\r
+ k, nk, d, nd,\r
+ PyFunction_GET_CLOSURE(func));\r
+\r
+ Py_XDECREF(kwtuple);\r
+\r
+ return result;\r
+}\r
+\r
+/* Bind a function to an object */\r
+static PyObject *\r
+func_descr_get(PyObject *func, PyObject *obj, PyObject *type)\r
+{\r
+ if (obj == Py_None)\r
+ obj = NULL;\r
+ return PyMethod_New(func, obj, type);\r
+}\r
+\r
+PyTypeObject PyFunction_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "function",\r
+ sizeof(PyFunctionObject),\r
+ 0,\r
+ (destructor)func_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)func_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ function_call, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ PyObject_GenericSetAttr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ func_doc, /* tp_doc */\r
+ (traverseproc)func_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ func_memberlist, /* tp_members */\r
+ func_getsetlist, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ func_descr_get, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ func_new, /* tp_new */\r
+};\r
+\r
+\r
+/* Class method object */\r
+\r
+/* A class method receives the class as implicit first argument,\r
+ just like an instance method receives the instance.\r
+ To declare a class method, use this idiom:\r
+\r
+ class C:\r
+ def f(cls, arg1, arg2, ...): ...\r
+ f = classmethod(f)\r
+\r
+ It can be called either on the class (e.g. C.f()) or on an instance\r
+ (e.g. C().f()); the instance is ignored except for its class.\r
+ If a class method is called for a derived class, the derived class\r
+ object is passed as the implied first argument.\r
+\r
+ Class methods are different than C++ or Java static methods.\r
+ If you want those, see static methods below.\r
+*/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyObject *cm_callable;\r
+} classmethod;\r
+\r
+static void\r
+cm_dealloc(classmethod *cm)\r
+{\r
+ _PyObject_GC_UNTRACK((PyObject *)cm);\r
+ Py_XDECREF(cm->cm_callable);\r
+ Py_TYPE(cm)->tp_free((PyObject *)cm);\r
+}\r
+\r
+static int\r
+cm_traverse(classmethod *cm, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(cm->cm_callable);\r
+ return 0;\r
+}\r
+\r
+static int\r
+cm_clear(classmethod *cm)\r
+{\r
+ Py_CLEAR(cm->cm_callable);\r
+ return 0;\r
+}\r
+\r
+\r
+static PyObject *\r
+cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)\r
+{\r
+ classmethod *cm = (classmethod *)self;\r
+\r
+ if (cm->cm_callable == NULL) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "uninitialized classmethod object");\r
+ return NULL;\r
+ }\r
+ if (type == NULL)\r
+ type = (PyObject *)(Py_TYPE(obj));\r
+ return PyMethod_New(cm->cm_callable,\r
+ type, (PyObject *)(Py_TYPE(type)));\r
+}\r
+\r
+static int\r
+cm_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ classmethod *cm = (classmethod *)self;\r
+ PyObject *callable;\r
+\r
+ if (!PyArg_UnpackTuple(args, "classmethod", 1, 1, &callable))\r
+ return -1;\r
+ if (!_PyArg_NoKeywords("classmethod", kwds))\r
+ return -1;\r
+ Py_INCREF(callable);\r
+ cm->cm_callable = callable;\r
+ return 0;\r
+}\r
+\r
+static PyMemberDef cm_memberlist[] = {\r
+ {"__func__", T_OBJECT, offsetof(classmethod, cm_callable), READONLY},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+PyDoc_STRVAR(classmethod_doc,\r
+"classmethod(function) -> method\n\\r
+\n\\r
+Convert a function to be a class method.\n\\r
+\n\\r
+A class method receives the class as implicit first argument,\n\\r
+just like an instance method receives the instance.\n\\r
+To declare a class method, use this idiom:\n\\r
+\n\\r
+ class C:\n\\r
+ def f(cls, arg1, arg2, ...): ...\n\\r
+ f = classmethod(f)\n\\r
+\n\\r
+It can be called either on the class (e.g. C.f()) or on an instance\n\\r
+(e.g. C().f()). The instance is ignored except for its class.\n\\r
+If a class method is called for a derived class, the derived class\n\\r
+object is passed as the implied first argument.\n\\r
+\n\\r
+Class methods are different than C++ or Java static methods.\n\\r
+If you want those, see the staticmethod builtin.");\r
+\r
+PyTypeObject PyClassMethod_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "classmethod",\r
+ sizeof(classmethod),\r
+ 0,\r
+ (destructor)cm_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,\r
+ classmethod_doc, /* tp_doc */\r
+ (traverseproc)cm_traverse, /* tp_traverse */\r
+ (inquiry)cm_clear, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ cm_memberlist, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ cm_descr_get, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ cm_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ PyType_GenericNew, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
+\r
+PyObject *\r
+PyClassMethod_New(PyObject *callable)\r
+{\r
+ classmethod *cm = (classmethod *)\r
+ PyType_GenericAlloc(&PyClassMethod_Type, 0);\r
+ if (cm != NULL) {\r
+ Py_INCREF(callable);\r
+ cm->cm_callable = callable;\r
+ }\r
+ return (PyObject *)cm;\r
+}\r
+\r
+\r
+/* Static method object */\r
+\r
+/* A static method does not receive an implicit first argument.\r
+ To declare a static method, use this idiom:\r
+\r
+ class C:\r
+ def f(arg1, arg2, ...): ...\r
+ f = staticmethod(f)\r
+\r
+ It can be called either on the class (e.g. C.f()) or on an instance\r
+ (e.g. C().f()); the instance is ignored except for its class.\r
+\r
+ Static methods in Python are similar to those found in Java or C++.\r
+ For a more advanced concept, see class methods above.\r
+*/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyObject *sm_callable;\r
+} staticmethod;\r
+\r
+static void\r
+sm_dealloc(staticmethod *sm)\r
+{\r
+ _PyObject_GC_UNTRACK((PyObject *)sm);\r
+ Py_XDECREF(sm->sm_callable);\r
+ Py_TYPE(sm)->tp_free((PyObject *)sm);\r
+}\r
+\r
+static int\r
+sm_traverse(staticmethod *sm, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(sm->sm_callable);\r
+ return 0;\r
+}\r
+\r
+static int\r
+sm_clear(staticmethod *sm)\r
+{\r
+ Py_CLEAR(sm->sm_callable);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+sm_descr_get(PyObject *self, PyObject *obj, PyObject *type)\r
+{\r
+ staticmethod *sm = (staticmethod *)self;\r
+\r
+ if (sm->sm_callable == NULL) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "uninitialized staticmethod object");\r
+ return NULL;\r
+ }\r
+ Py_INCREF(sm->sm_callable);\r
+ return sm->sm_callable;\r
+}\r
+\r
+static int\r
+sm_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ staticmethod *sm = (staticmethod *)self;\r
+ PyObject *callable;\r
+\r
+ if (!PyArg_UnpackTuple(args, "staticmethod", 1, 1, &callable))\r
+ return -1;\r
+ if (!_PyArg_NoKeywords("staticmethod", kwds))\r
+ return -1;\r
+ Py_INCREF(callable);\r
+ sm->sm_callable = callable;\r
+ return 0;\r
+}\r
+\r
+static PyMemberDef sm_memberlist[] = {\r
+ {"__func__", T_OBJECT, offsetof(staticmethod, sm_callable), READONLY},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+PyDoc_STRVAR(staticmethod_doc,\r
+"staticmethod(function) -> method\n\\r
+\n\\r
+Convert a function to be a static method.\n\\r
+\n\\r
+A static method does not receive an implicit first argument.\n\\r
+To declare a static method, use this idiom:\n\\r
+\n\\r
+ class C:\n\\r
+ def f(arg1, arg2, ...): ...\n\\r
+ f = staticmethod(f)\n\\r
+\n\\r
+It can be called either on the class (e.g. C.f()) or on an instance\n\\r
+(e.g. C().f()). The instance is ignored except for its class.\n\\r
+\n\\r
+Static methods in Python are similar to those found in Java or C++.\n\\r
+For a more advanced concept, see the classmethod builtin.");\r
+\r
+PyTypeObject PyStaticMethod_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "staticmethod",\r
+ sizeof(staticmethod),\r
+ 0,\r
+ (destructor)sm_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,\r
+ staticmethod_doc, /* tp_doc */\r
+ (traverseproc)sm_traverse, /* tp_traverse */\r
+ (inquiry)sm_clear, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ sm_memberlist, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ sm_descr_get, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ sm_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ PyType_GenericNew, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
+\r
+PyObject *\r
+PyStaticMethod_New(PyObject *callable)\r
+{\r
+ staticmethod *sm = (staticmethod *)\r
+ PyType_GenericAlloc(&PyStaticMethod_Type, 0);\r
+ if (sm != NULL) {\r
+ Py_INCREF(callable);\r
+ sm->sm_callable = callable;\r
+ }\r
+ return (PyObject *)sm;\r
+}\r
--- /dev/null
+/* Generator object implementation */\r
+\r
+#include "Python.h"\r
+#include "frameobject.h"\r
+#include "genobject.h"\r
+#include "ceval.h"\r
+#include "structmember.h"\r
+#include "opcode.h"\r
+\r
+static int\r
+gen_traverse(PyGenObject *gen, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT((PyObject *)gen->gi_frame);\r
+ Py_VISIT(gen->gi_code);\r
+ return 0;\r
+}\r
+\r
+static void\r
+gen_dealloc(PyGenObject *gen)\r
+{\r
+ PyObject *self = (PyObject *) gen;\r
+\r
+ _PyObject_GC_UNTRACK(gen);\r
+\r
+ if (gen->gi_weakreflist != NULL)\r
+ PyObject_ClearWeakRefs(self);\r
+\r
+ _PyObject_GC_TRACK(self);\r
+\r
+ if (gen->gi_frame != NULL && gen->gi_frame->f_stacktop != NULL) {\r
+ /* Generator is paused, so we need to close */\r
+ Py_TYPE(gen)->tp_del(self);\r
+ if (self->ob_refcnt > 0)\r
+ return; /* resurrected. :( */\r
+ }\r
+\r
+ _PyObject_GC_UNTRACK(self);\r
+ Py_CLEAR(gen->gi_frame);\r
+ Py_CLEAR(gen->gi_code);\r
+ PyObject_GC_Del(gen);\r
+}\r
+\r
+\r
+static PyObject *\r
+gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)\r
+{\r
+ PyThreadState *tstate = PyThreadState_GET();\r
+ PyFrameObject *f = gen->gi_frame;\r
+ PyObject *result;\r
+\r
+ if (gen->gi_running) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "generator already executing");\r
+ return NULL;\r
+ }\r
+ if (f==NULL || f->f_stacktop == NULL) {\r
+ /* Only set exception if called from send() */\r
+ if (arg && !exc)\r
+ PyErr_SetNone(PyExc_StopIteration);\r
+ return NULL;\r
+ }\r
+\r
+ if (f->f_lasti == -1) {\r
+ if (arg && arg != Py_None) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "can't send non-None value to a "\r
+ "just-started generator");\r
+ return NULL;\r
+ }\r
+ } else {\r
+ /* Push arg onto the frame's value stack */\r
+ result = arg ? arg : Py_None;\r
+ Py_INCREF(result);\r
+ *(f->f_stacktop++) = result;\r
+ }\r
+\r
+ /* Generators always return to their most recent caller, not\r
+ * necessarily their creator. */\r
+ f->f_tstate = tstate;\r
+ Py_XINCREF(tstate->frame);\r
+ assert(f->f_back == NULL);\r
+ f->f_back = tstate->frame;\r
+\r
+ gen->gi_running = 1;\r
+ result = PyEval_EvalFrameEx(f, exc);\r
+ gen->gi_running = 0;\r
+\r
+ /* Don't keep the reference to f_back any longer than necessary. It\r
+ * may keep a chain of frames alive or it could create a reference\r
+ * cycle. */\r
+ assert(f->f_back == tstate->frame);\r
+ Py_CLEAR(f->f_back);\r
+ /* Clear the borrowed reference to the thread state */\r
+ f->f_tstate = NULL;\r
+\r
+ /* If the generator just returned (as opposed to yielding), signal\r
+ * that the generator is exhausted. */\r
+ if (result == Py_None && f->f_stacktop == NULL) {\r
+ Py_DECREF(result);\r
+ result = NULL;\r
+ /* Set exception if not called by gen_iternext() */\r
+ if (arg)\r
+ PyErr_SetNone(PyExc_StopIteration);\r
+ }\r
+\r
+ if (!result || f->f_stacktop == NULL) {\r
+ /* generator can't be rerun, so release the frame */\r
+ Py_DECREF(f);\r
+ gen->gi_frame = NULL;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(send_doc,\r
+"send(arg) -> send 'arg' into generator,\n\\r
+return next yielded value or raise StopIteration.");\r
+\r
+static PyObject *\r
+gen_send(PyGenObject *gen, PyObject *arg)\r
+{\r
+ return gen_send_ex(gen, arg, 0);\r
+}\r
+\r
+PyDoc_STRVAR(close_doc,\r
+"close() -> raise GeneratorExit inside generator.");\r
+\r
+static PyObject *\r
+gen_close(PyGenObject *gen, PyObject *args)\r
+{\r
+ PyObject *retval;\r
+ PyErr_SetNone(PyExc_GeneratorExit);\r
+ retval = gen_send_ex(gen, Py_None, 1);\r
+ if (retval) {\r
+ Py_DECREF(retval);\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "generator ignored GeneratorExit");\r
+ return NULL;\r
+ }\r
+ if (PyErr_ExceptionMatches(PyExc_StopIteration)\r
+ || PyErr_ExceptionMatches(PyExc_GeneratorExit))\r
+ {\r
+ PyErr_Clear(); /* ignore these errors */\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+static void\r
+gen_del(PyObject *self)\r
+{\r
+ PyObject *res;\r
+ PyObject *error_type, *error_value, *error_traceback;\r
+ PyGenObject *gen = (PyGenObject *)self;\r
+\r
+ if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)\r
+ /* Generator isn't paused, so no need to close */\r
+ return;\r
+\r
+ /* Temporarily resurrect the object. */\r
+ assert(self->ob_refcnt == 0);\r
+ self->ob_refcnt = 1;\r
+\r
+ /* Save the current exception, if any. */\r
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);\r
+\r
+ res = gen_close(gen, NULL);\r
+\r
+ if (res == NULL)\r
+ PyErr_WriteUnraisable(self);\r
+ else\r
+ Py_DECREF(res);\r
+\r
+ /* Restore the saved exception. */\r
+ PyErr_Restore(error_type, error_value, error_traceback);\r
+\r
+ /* Undo the temporary resurrection; can't use DECREF here, it would\r
+ * cause a recursive call.\r
+ */\r
+ assert(self->ob_refcnt > 0);\r
+ if (--self->ob_refcnt == 0)\r
+ return; /* this is the normal path out */\r
+\r
+ /* close() resurrected it! Make it look like the original Py_DECREF\r
+ * never happened.\r
+ */\r
+ {\r
+ Py_ssize_t refcnt = self->ob_refcnt;\r
+ _Py_NewReference(self);\r
+ self->ob_refcnt = refcnt;\r
+ }\r
+ assert(PyType_IS_GC(self->ob_type) &&\r
+ _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);\r
+\r
+ /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so\r
+ * we need to undo that. */\r
+ _Py_DEC_REFTOTAL;\r
+ /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object\r
+ * chain, so no more to do there.\r
+ * If COUNT_ALLOCS, the original decref bumped tp_frees, and\r
+ * _Py_NewReference bumped tp_allocs: both of those need to be\r
+ * undone.\r
+ */\r
+#ifdef COUNT_ALLOCS\r
+ --self->ob_type->tp_frees;\r
+ --self->ob_type->tp_allocs;\r
+#endif\r
+}\r
+\r
+\r
+\r
+PyDoc_STRVAR(throw_doc,\r
+"throw(typ[,val[,tb]]) -> raise exception in generator,\n\\r
+return next yielded value or raise StopIteration.");\r
+\r
+static PyObject *\r
+gen_throw(PyGenObject *gen, PyObject *args)\r
+{\r
+ PyObject *typ;\r
+ PyObject *tb = NULL;\r
+ PyObject *val = NULL;\r
+\r
+ if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))\r
+ return NULL;\r
+\r
+ /* First, check the traceback argument, replacing None with\r
+ NULL. */\r
+ if (tb == Py_None)\r
+ tb = NULL;\r
+ else if (tb != NULL && !PyTraceBack_Check(tb)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "throw() third argument must be a traceback object");\r
+ return NULL;\r
+ }\r
+\r
+ Py_INCREF(typ);\r
+ Py_XINCREF(val);\r
+ Py_XINCREF(tb);\r
+\r
+ if (PyExceptionClass_Check(typ)) {\r
+ PyErr_NormalizeException(&typ, &val, &tb);\r
+ }\r
+\r
+ else if (PyExceptionInstance_Check(typ)) {\r
+ /* Raising an instance. The value should be a dummy. */\r
+ if (val && val != Py_None) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "instance exception may not have a separate value");\r
+ goto failed_throw;\r
+ }\r
+ else {\r
+ /* Normalize to raise <class>, <instance> */\r
+ Py_XDECREF(val);\r
+ val = typ;\r
+ typ = PyExceptionInstance_Class(typ);\r
+ Py_INCREF(typ);\r
+ }\r
+ }\r
+ else {\r
+ /* Not something you can raise. throw() fails. */\r
+ PyErr_Format(PyExc_TypeError,\r
+ "exceptions must be classes, or instances, not %s",\r
+ typ->ob_type->tp_name);\r
+ goto failed_throw;\r
+ }\r
+\r
+ PyErr_Restore(typ, val, tb);\r
+ return gen_send_ex(gen, Py_None, 1);\r
+\r
+failed_throw:\r
+ /* Didn't use our arguments, so restore their original refcounts */\r
+ Py_DECREF(typ);\r
+ Py_XDECREF(val);\r
+ Py_XDECREF(tb);\r
+ return NULL;\r
+}\r
+\r
+\r
+static PyObject *\r
+gen_iternext(PyGenObject *gen)\r
+{\r
+ return gen_send_ex(gen, NULL, 0);\r
+}\r
+\r
+\r
+static PyObject *\r
+gen_repr(PyGenObject *gen)\r
+{\r
+ char *code_name;\r
+ code_name = PyString_AsString(((PyCodeObject *)gen->gi_code)->co_name);\r
+ if (code_name == NULL)\r
+ return NULL;\r
+ return PyString_FromFormat("<generator object %.200s at %p>",\r
+ code_name, gen);\r
+}\r
+\r
+\r
+static PyObject *\r
+gen_get_name(PyGenObject *gen)\r
+{\r
+ PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name;\r
+ Py_INCREF(name);\r
+ return name;\r
+}\r
+\r
+\r
+PyDoc_STRVAR(gen__name__doc__,\r
+"Return the name of the generator's associated code object.");\r
+\r
+static PyGetSetDef gen_getsetlist[] = {\r
+ {"__name__", (getter)gen_get_name, NULL, gen__name__doc__},\r
+ {NULL}\r
+};\r
+\r
+\r
+static PyMemberDef gen_memberlist[] = {\r
+ {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), RO},\r
+ {"gi_running", T_INT, offsetof(PyGenObject, gi_running), RO},\r
+ {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), RO},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+static PyMethodDef gen_methods[] = {\r
+ {"send",(PyCFunction)gen_send, METH_O, send_doc},\r
+ {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},\r
+ {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},\r
+ {NULL, NULL} /* Sentinel */\r
+};\r
+\r
+PyTypeObject PyGen_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "generator", /* tp_name */\r
+ sizeof(PyGenObject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)gen_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)gen_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)gen_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)gen_iternext, /* tp_iternext */\r
+ gen_methods, /* tp_methods */\r
+ gen_memberlist, /* tp_members */\r
+ gen_getsetlist, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ 0, /* tp_new */\r
+ 0, /* tp_free */\r
+ 0, /* tp_is_gc */\r
+ 0, /* tp_bases */\r
+ 0, /* tp_mro */\r
+ 0, /* tp_cache */\r
+ 0, /* tp_subclasses */\r
+ 0, /* tp_weaklist */\r
+ gen_del, /* tp_del */\r
+};\r
+\r
+PyObject *\r
+PyGen_New(PyFrameObject *f)\r
+{\r
+ PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);\r
+ if (gen == NULL) {\r
+ Py_DECREF(f);\r
+ return NULL;\r
+ }\r
+ gen->gi_frame = f;\r
+ Py_INCREF(f->f_code);\r
+ gen->gi_code = (PyObject *)(f->f_code);\r
+ gen->gi_running = 0;\r
+ gen->gi_weakreflist = NULL;\r
+ _PyObject_GC_TRACK(gen);\r
+ return (PyObject *)gen;\r
+}\r
+\r
+int\r
+PyGen_NeedsFinalizing(PyGenObject *gen)\r
+{\r
+ int i;\r
+ PyFrameObject *f = gen->gi_frame;\r
+\r
+ if (f == NULL || f->f_stacktop == NULL || f->f_iblock <= 0)\r
+ return 0; /* no frame or empty blockstack == no finalization */\r
+\r
+ /* Any block type besides a loop requires cleanup. */\r
+ i = f->f_iblock;\r
+ while (--i >= 0) {\r
+ if (f->f_blockstack[i].b_type != SETUP_LOOP)\r
+ return 1;\r
+ }\r
+\r
+ /* No blocks except loops, it's safe to skip finalization. */\r
+ return 0;\r
+}\r
--- /dev/null
+\r
+/* Integer object implementation */\r
+\r
+#include "Python.h"\r
+#include <ctype.h>\r
+#include <float.h>\r
+\r
+static PyObject *int_int(PyIntObject *v);\r
+\r
+long\r
+PyInt_GetMax(void)\r
+{\r
+ return LONG_MAX; /* To initialize sys.maxint */\r
+}\r
+\r
+/* Integers are quite normal objects, to make object handling uniform.\r
+ (Using odd pointers to represent integers would save much space\r
+ but require extra checks for this special case throughout the code.)\r
+ Since a typical Python program spends much of its time allocating\r
+ and deallocating integers, these operations should be very fast.\r
+ Therefore we use a dedicated allocation scheme with a much lower\r
+ overhead (in space and time) than straight malloc(): a simple\r
+ dedicated free list, filled when necessary with memory from malloc().\r
+\r
+ block_list is a singly-linked list of all PyIntBlocks ever allocated,\r
+ linked via their next members. PyIntBlocks are never returned to the\r
+ system before shutdown (PyInt_Fini).\r
+\r
+ free_list is a singly-linked list of available PyIntObjects, linked\r
+ via abuse of their ob_type members.\r
+*/\r
+\r
+#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */\r
+#define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */\r
+#define N_INTOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyIntObject))\r
+\r
+struct _intblock {\r
+ struct _intblock *next;\r
+ PyIntObject objects[N_INTOBJECTS];\r
+};\r
+\r
+typedef struct _intblock PyIntBlock;\r
+\r
+static PyIntBlock *block_list = NULL;\r
+static PyIntObject *free_list = NULL;\r
+\r
+static PyIntObject *\r
+fill_free_list(void)\r
+{\r
+ PyIntObject *p, *q;\r
+ /* Python's object allocator isn't appropriate for large blocks. */\r
+ p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));\r
+ if (p == NULL)\r
+ return (PyIntObject *) PyErr_NoMemory();\r
+ ((PyIntBlock *)p)->next = block_list;\r
+ block_list = (PyIntBlock *)p;\r
+ /* Link the int objects together, from rear to front, then return\r
+ the address of the last int object in the block. */\r
+ p = &((PyIntBlock *)p)->objects[0];\r
+ q = p + N_INTOBJECTS;\r
+ while (--q > p)\r
+ Py_TYPE(q) = (struct _typeobject *)(q-1);\r
+ Py_TYPE(q) = NULL;\r
+ return p + N_INTOBJECTS - 1;\r
+}\r
+\r
+#ifndef NSMALLPOSINTS\r
+#define NSMALLPOSINTS 257\r
+#endif\r
+#ifndef NSMALLNEGINTS\r
+#define NSMALLNEGINTS 5\r
+#endif\r
+#if NSMALLNEGINTS + NSMALLPOSINTS > 0\r
+/* References to small integers are saved in this array so that they\r
+ can be shared.\r
+ The integers that are saved are those in the range\r
+ -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).\r
+*/\r
+static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];\r
+#endif\r
+#ifdef COUNT_ALLOCS\r
+Py_ssize_t quick_int_allocs;\r
+Py_ssize_t quick_neg_int_allocs;\r
+#endif\r
+\r
+PyObject *\r
+PyInt_FromLong(long ival)\r
+{\r
+ register PyIntObject *v;\r
+#if NSMALLNEGINTS + NSMALLPOSINTS > 0\r
+ if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {\r
+ v = small_ints[ival + NSMALLNEGINTS];\r
+ Py_INCREF(v);\r
+#ifdef COUNT_ALLOCS\r
+ if (ival >= 0)\r
+ quick_int_allocs++;\r
+ else\r
+ quick_neg_int_allocs++;\r
+#endif\r
+ return (PyObject *) v;\r
+ }\r
+#endif\r
+ if (free_list == NULL) {\r
+ if ((free_list = fill_free_list()) == NULL)\r
+ return NULL;\r
+ }\r
+ /* Inline PyObject_New */\r
+ v = free_list;\r
+ free_list = (PyIntObject *)Py_TYPE(v);\r
+ PyObject_INIT(v, &PyInt_Type);\r
+ v->ob_ival = ival;\r
+ return (PyObject *) v;\r
+}\r
+\r
+PyObject *\r
+PyInt_FromSize_t(size_t ival)\r
+{\r
+ if (ival <= LONG_MAX)\r
+ return PyInt_FromLong((long)ival);\r
+ return _PyLong_FromSize_t(ival);\r
+}\r
+\r
+PyObject *\r
+PyInt_FromSsize_t(Py_ssize_t ival)\r
+{\r
+ if (ival >= LONG_MIN && ival <= LONG_MAX)\r
+ return PyInt_FromLong((long)ival);\r
+ return _PyLong_FromSsize_t(ival);\r
+}\r
+\r
+static void\r
+int_dealloc(PyIntObject *v)\r
+{\r
+ if (PyInt_CheckExact(v)) {\r
+ Py_TYPE(v) = (struct _typeobject *)free_list;\r
+ free_list = v;\r
+ }\r
+ else\r
+ Py_TYPE(v)->tp_free((PyObject *)v);\r
+}\r
+\r
+static void\r
+int_free(PyIntObject *v)\r
+{\r
+ Py_TYPE(v) = (struct _typeobject *)free_list;\r
+ free_list = v;\r
+}\r
+\r
+long\r
+PyInt_AsLong(register PyObject *op)\r
+{\r
+ PyNumberMethods *nb;\r
+ PyIntObject *io;\r
+ long val;\r
+\r
+ if (op && PyInt_Check(op))\r
+ return PyInt_AS_LONG((PyIntObject*) op);\r
+\r
+ if (op == NULL || (nb = Py_TYPE(op)->tp_as_number) == NULL ||\r
+ nb->nb_int == NULL) {\r
+ PyErr_SetString(PyExc_TypeError, "an integer is required");\r
+ return -1;\r
+ }\r
+\r
+ io = (PyIntObject*) (*nb->nb_int) (op);\r
+ if (io == NULL)\r
+ return -1;\r
+ if (!PyInt_Check(io)) {\r
+ if (PyLong_Check(io)) {\r
+ /* got a long? => retry int conversion */\r
+ val = PyLong_AsLong((PyObject *)io);\r
+ Py_DECREF(io);\r
+ if ((val == -1) && PyErr_Occurred())\r
+ return -1;\r
+ return val;\r
+ }\r
+ else\r
+ {\r
+ Py_DECREF(io);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__int__ method should return an integer");\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ val = PyInt_AS_LONG(io);\r
+ Py_DECREF(io);\r
+\r
+ return val;\r
+}\r
+\r
+int\r
+_PyInt_AsInt(PyObject *obj)\r
+{\r
+ long result = PyInt_AsLong(obj);\r
+ if (result == -1 && PyErr_Occurred())\r
+ return -1;\r
+ if (result > INT_MAX || result < INT_MIN) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "Python int too large to convert to C int");\r
+ return -1;\r
+ }\r
+ return (int)result;\r
+}\r
+\r
+Py_ssize_t\r
+PyInt_AsSsize_t(register PyObject *op)\r
+{\r
+#if SIZEOF_SIZE_T != SIZEOF_LONG\r
+ PyNumberMethods *nb;\r
+ PyObject *io;\r
+ Py_ssize_t val;\r
+#endif\r
+\r
+ if (op == NULL) {\r
+ PyErr_SetString(PyExc_TypeError, "an integer is required");\r
+ return -1;\r
+ }\r
+\r
+ if (PyInt_Check(op))\r
+ return PyInt_AS_LONG((PyIntObject*) op);\r
+ if (PyLong_Check(op))\r
+ return _PyLong_AsSsize_t(op);\r
+#if SIZEOF_SIZE_T == SIZEOF_LONG\r
+ return PyInt_AsLong(op);\r
+#else\r
+\r
+ if ((nb = Py_TYPE(op)->tp_as_number) == NULL ||\r
+ (nb->nb_int == NULL && nb->nb_long == 0)) {\r
+ PyErr_SetString(PyExc_TypeError, "an integer is required");\r
+ return -1;\r
+ }\r
+\r
+ if (nb->nb_long != 0)\r
+ io = (*nb->nb_long)(op);\r
+ else\r
+ io = (*nb->nb_int)(op);\r
+ if (io == NULL)\r
+ return -1;\r
+ if (!PyInt_Check(io)) {\r
+ if (PyLong_Check(io)) {\r
+ /* got a long? => retry int conversion */\r
+ val = _PyLong_AsSsize_t(io);\r
+ Py_DECREF(io);\r
+ if ((val == -1) && PyErr_Occurred())\r
+ return -1;\r
+ return val;\r
+ }\r
+ else\r
+ {\r
+ Py_DECREF(io);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__int__ method should return an integer");\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ val = PyInt_AS_LONG(io);\r
+ Py_DECREF(io);\r
+\r
+ return val;\r
+#endif\r
+}\r
+\r
+unsigned long\r
+PyInt_AsUnsignedLongMask(register PyObject *op)\r
+{\r
+ PyNumberMethods *nb;\r
+ PyIntObject *io;\r
+ unsigned long val;\r
+\r
+ if (op && PyInt_Check(op))\r
+ return PyInt_AS_LONG((PyIntObject*) op);\r
+ if (op && PyLong_Check(op))\r
+ return PyLong_AsUnsignedLongMask(op);\r
+\r
+ if (op == NULL || (nb = Py_TYPE(op)->tp_as_number) == NULL ||\r
+ nb->nb_int == NULL) {\r
+ PyErr_SetString(PyExc_TypeError, "an integer is required");\r
+ return (unsigned long)-1;\r
+ }\r
+\r
+ io = (PyIntObject*) (*nb->nb_int) (op);\r
+ if (io == NULL)\r
+ return (unsigned long)-1;\r
+ if (!PyInt_Check(io)) {\r
+ if (PyLong_Check(io)) {\r
+ val = PyLong_AsUnsignedLongMask((PyObject *)io);\r
+ Py_DECREF(io);\r
+ if (PyErr_Occurred())\r
+ return (unsigned long)-1;\r
+ return val;\r
+ }\r
+ else\r
+ {\r
+ Py_DECREF(io);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__int__ method should return an integer");\r
+ return (unsigned long)-1;\r
+ }\r
+ }\r
+\r
+ val = PyInt_AS_LONG(io);\r
+ Py_DECREF(io);\r
+\r
+ return val;\r
+}\r
+\r
+#ifdef HAVE_LONG_LONG\r
+unsigned PY_LONG_LONG\r
+PyInt_AsUnsignedLongLongMask(register PyObject *op)\r
+{\r
+ PyNumberMethods *nb;\r
+ PyIntObject *io;\r
+ unsigned PY_LONG_LONG val;\r
+\r
+ if (op && PyInt_Check(op))\r
+ return PyInt_AS_LONG((PyIntObject*) op);\r
+ if (op && PyLong_Check(op))\r
+ return PyLong_AsUnsignedLongLongMask(op);\r
+\r
+ if (op == NULL || (nb = Py_TYPE(op)->tp_as_number) == NULL ||\r
+ nb->nb_int == NULL) {\r
+ PyErr_SetString(PyExc_TypeError, "an integer is required");\r
+ return (unsigned PY_LONG_LONG)-1;\r
+ }\r
+\r
+ io = (PyIntObject*) (*nb->nb_int) (op);\r
+ if (io == NULL)\r
+ return (unsigned PY_LONG_LONG)-1;\r
+ if (!PyInt_Check(io)) {\r
+ if (PyLong_Check(io)) {\r
+ val = PyLong_AsUnsignedLongLongMask((PyObject *)io);\r
+ Py_DECREF(io);\r
+ if (PyErr_Occurred())\r
+ return (unsigned PY_LONG_LONG)-1;\r
+ return val;\r
+ }\r
+ else\r
+ {\r
+ Py_DECREF(io);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__int__ method should return an integer");\r
+ return (unsigned PY_LONG_LONG)-1;\r
+ }\r
+ }\r
+\r
+ val = PyInt_AS_LONG(io);\r
+ Py_DECREF(io);\r
+\r
+ return val;\r
+}\r
+#endif\r
+\r
+PyObject *\r
+PyInt_FromString(char *s, char **pend, int base)\r
+{\r
+ char *end;\r
+ long x;\r
+ Py_ssize_t slen;\r
+ PyObject *sobj, *srepr;\r
+\r
+ if ((base != 0 && base < 2) || base > 36) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "int() base must be >= 2 and <= 36");\r
+ return NULL;\r
+ }\r
+\r
+ while (*s && isspace(Py_CHARMASK(*s)))\r
+ s++;\r
+ errno = 0;\r
+ if (base == 0 && s[0] == '0') {\r
+ x = (long) PyOS_strtoul(s, &end, base);\r
+ if (x < 0)\r
+ return PyLong_FromString(s, pend, base);\r
+ }\r
+ else\r
+ x = PyOS_strtol(s, &end, base);\r
+ if (end == s || !isalnum(Py_CHARMASK(end[-1])))\r
+ goto bad;\r
+ while (*end && isspace(Py_CHARMASK(*end)))\r
+ end++;\r
+ if (*end != '\0') {\r
+ bad:\r
+ slen = strlen(s) < 200 ? strlen(s) : 200;\r
+ sobj = PyString_FromStringAndSize(s, slen);\r
+ if (sobj == NULL)\r
+ return NULL;\r
+ srepr = PyObject_Repr(sobj);\r
+ Py_DECREF(sobj);\r
+ if (srepr == NULL)\r
+ return NULL;\r
+ PyErr_Format(PyExc_ValueError,\r
+ "invalid literal for int() with base %d: %s",\r
+ base, PyString_AS_STRING(srepr));\r
+ Py_DECREF(srepr);\r
+ return NULL;\r
+ }\r
+ else if (errno != 0)\r
+ return PyLong_FromString(s, pend, base);\r
+ if (pend)\r
+ *pend = end;\r
+ return PyInt_FromLong(x);\r
+}\r
+\r
+#ifdef Py_USING_UNICODE\r
+PyObject *\r
+PyInt_FromUnicode(Py_UNICODE *s, Py_ssize_t length, int base)\r
+{\r
+ PyObject *result;\r
+ char *buffer = (char *)PyMem_MALLOC(length+1);\r
+\r
+ if (buffer == NULL)\r
+ return PyErr_NoMemory();\r
+\r
+ if (PyUnicode_EncodeDecimal(s, length, buffer, NULL)) {\r
+ PyMem_FREE(buffer);\r
+ return NULL;\r
+ }\r
+ result = PyInt_FromString(buffer, NULL, base);\r
+ PyMem_FREE(buffer);\r
+ return result;\r
+}\r
+#endif\r
+\r
+/* Methods */\r
+\r
+/* Integers are seen as the "smallest" of all numeric types and thus\r
+ don't have any knowledge about conversion of other types to\r
+ integers. */\r
+\r
+#define CONVERT_TO_LONG(obj, lng) \\r
+ if (PyInt_Check(obj)) { \\r
+ lng = PyInt_AS_LONG(obj); \\r
+ } \\r
+ else { \\r
+ Py_INCREF(Py_NotImplemented); \\r
+ return Py_NotImplemented; \\r
+ }\r
+\r
+/* ARGSUSED */\r
+static int\r
+int_print(PyIntObject *v, FILE *fp, int flags)\r
+ /* flags -- not used but required by interface */\r
+{\r
+ long int_val = v->ob_ival;\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "%ld", int_val);\r
+ Py_END_ALLOW_THREADS\r
+ return 0;\r
+}\r
+\r
+static int\r
+int_compare(PyIntObject *v, PyIntObject *w)\r
+{\r
+ register long i = v->ob_ival;\r
+ register long j = w->ob_ival;\r
+ return (i < j) ? -1 : (i > j) ? 1 : 0;\r
+}\r
+\r
+static long\r
+int_hash(PyIntObject *v)\r
+{\r
+ /* XXX If this is changed, you also need to change the way\r
+ Python's long, float and complex types are hashed. */\r
+ long x = v -> ob_ival;\r
+ if (x == -1)\r
+ x = -2;\r
+ return x;\r
+}\r
+\r
+static PyObject *\r
+int_add(PyIntObject *v, PyIntObject *w)\r
+{\r
+ register long a, b, x;\r
+ CONVERT_TO_LONG(v, a);\r
+ CONVERT_TO_LONG(w, b);\r
+ /* casts in the line below avoid undefined behaviour on overflow */\r
+ x = (long)((unsigned long)a + b);\r
+ if ((x^a) >= 0 || (x^b) >= 0)\r
+ return PyInt_FromLong(x);\r
+ return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w);\r
+}\r
+\r
+static PyObject *\r
+int_sub(PyIntObject *v, PyIntObject *w)\r
+{\r
+ register long a, b, x;\r
+ CONVERT_TO_LONG(v, a);\r
+ CONVERT_TO_LONG(w, b);\r
+ /* casts in the line below avoid undefined behaviour on overflow */\r
+ x = (long)((unsigned long)a - b);\r
+ if ((x^a) >= 0 || (x^~b) >= 0)\r
+ return PyInt_FromLong(x);\r
+ return PyLong_Type.tp_as_number->nb_subtract((PyObject *)v,\r
+ (PyObject *)w);\r
+}\r
+\r
+/*\r
+Integer overflow checking for * is painful: Python tried a couple ways, but\r
+they didn't work on all platforms, or failed in endcases (a product of\r
+-sys.maxint-1 has been a particular pain).\r
+\r
+Here's another way:\r
+\r
+The native long product x*y is either exactly right or *way* off, being\r
+just the last n bits of the true product, where n is the number of bits\r
+in a long (the delivered product is the true product plus i*2**n for\r
+some integer i).\r
+\r
+The native double product (double)x * (double)y is subject to three\r
+rounding errors: on a sizeof(long)==8 box, each cast to double can lose\r
+info, and even on a sizeof(long)==4 box, the multiplication can lose info.\r
+But, unlike the native long product, it's not in *range* trouble: even\r
+if sizeof(long)==32 (256-bit longs), the product easily fits in the\r
+dynamic range of a double. So the leading 50 (or so) bits of the double\r
+product are correct.\r
+\r
+We check these two ways against each other, and declare victory if they're\r
+approximately the same. Else, because the native long product is the only\r
+one that can lose catastrophic amounts of information, it's the native long\r
+product that must have overflowed.\r
+*/\r
+\r
+static PyObject *\r
+int_mul(PyObject *v, PyObject *w)\r
+{\r
+ long a, b;\r
+ long longprod; /* a*b in native long arithmetic */\r
+ double doubled_longprod; /* (double)longprod */\r
+ double doubleprod; /* (double)a * (double)b */\r
+\r
+ CONVERT_TO_LONG(v, a);\r
+ CONVERT_TO_LONG(w, b);\r
+ /* casts in the next line avoid undefined behaviour on overflow */\r
+ longprod = (long)((unsigned long)a * b);\r
+ doubleprod = (double)a * (double)b;\r
+ doubled_longprod = (double)longprod;\r
+\r
+ /* Fast path for normal case: small multiplicands, and no info\r
+ is lost in either method. */\r
+ if (doubled_longprod == doubleprod)\r
+ return PyInt_FromLong(longprod);\r
+\r
+ /* Somebody somewhere lost info. Close enough, or way off? Note\r
+ that a != 0 and b != 0 (else doubled_longprod == doubleprod == 0).\r
+ The difference either is or isn't significant compared to the\r
+ true value (of which doubleprod is a good approximation).\r
+ */\r
+ {\r
+ const double diff = doubled_longprod - doubleprod;\r
+ const double absdiff = diff >= 0.0 ? diff : -diff;\r
+ const double absprod = doubleprod >= 0.0 ? doubleprod :\r
+ -doubleprod;\r
+ /* absdiff/absprod <= 1/32 iff\r
+ 32 * absdiff <= absprod -- 5 good bits is "close enough" */\r
+ if (32.0 * absdiff <= absprod)\r
+ return PyInt_FromLong(longprod);\r
+ else\r
+ return PyLong_Type.tp_as_number->nb_multiply(v, w);\r
+ }\r
+}\r
+\r
+/* Integer overflow checking for unary negation: on a 2's-complement\r
+ * box, -x overflows iff x is the most negative long. In this case we\r
+ * get -x == x. However, -x is undefined (by C) if x /is/ the most\r
+ * negative long (it's a signed overflow case), and some compilers care.\r
+ * So we cast x to unsigned long first. However, then other compilers\r
+ * warn about applying unary minus to an unsigned operand. Hence the\r
+ * weird "0-".\r
+ */\r
+#define UNARY_NEG_WOULD_OVERFLOW(x) \\r
+ ((x) < 0 && (unsigned long)(x) == 0-(unsigned long)(x))\r
+\r
+/* Return type of i_divmod */\r
+enum divmod_result {\r
+ DIVMOD_OK, /* Correct result */\r
+ DIVMOD_OVERFLOW, /* Overflow, try again using longs */\r
+ DIVMOD_ERROR /* Exception raised */\r
+};\r
+\r
+static enum divmod_result\r
+i_divmod(register long x, register long y,\r
+ long *p_xdivy, long *p_xmody)\r
+{\r
+ long xdivy, xmody;\r
+\r
+ if (y == 0) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError,\r
+ "integer division or modulo by zero");\r
+ return DIVMOD_ERROR;\r
+ }\r
+ /* (-sys.maxint-1)/-1 is the only overflow case. */\r
+ if (y == -1 && UNARY_NEG_WOULD_OVERFLOW(x))\r
+ return DIVMOD_OVERFLOW;\r
+ xdivy = x / y;\r
+ /* xdiv*y can overflow on platforms where x/y gives floor(x/y)\r
+ * for x and y with differing signs. (This is unusual\r
+ * behaviour, and C99 prohibits it, but it's allowed by C89;\r
+ * for an example of overflow, take x = LONG_MIN, y = 5 or x =\r
+ * LONG_MAX, y = -5.) However, x - xdivy*y is always\r
+ * representable as a long, since it lies strictly between\r
+ * -abs(y) and abs(y). We add casts to avoid intermediate\r
+ * overflow.\r
+ */\r
+ xmody = (long)(x - (unsigned long)xdivy * y);\r
+ /* If the signs of x and y differ, and the remainder is non-0,\r
+ * C89 doesn't define whether xdivy is now the floor or the\r
+ * ceiling of the infinitely precise quotient. We want the floor,\r
+ * and we have it iff the remainder's sign matches y's.\r
+ */\r
+ if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {\r
+ xmody += y;\r
+ --xdivy;\r
+ assert(xmody && ((y ^ xmody) >= 0));\r
+ }\r
+ *p_xdivy = xdivy;\r
+ *p_xmody = xmody;\r
+ return DIVMOD_OK;\r
+}\r
+\r
+static PyObject *\r
+int_div(PyIntObject *x, PyIntObject *y)\r
+{\r
+ long xi, yi;\r
+ long d, m;\r
+ CONVERT_TO_LONG(x, xi);\r
+ CONVERT_TO_LONG(y, yi);\r
+ switch (i_divmod(xi, yi, &d, &m)) {\r
+ case DIVMOD_OK:\r
+ return PyInt_FromLong(d);\r
+ case DIVMOD_OVERFLOW:\r
+ return PyLong_Type.tp_as_number->nb_divide((PyObject *)x,\r
+ (PyObject *)y);\r
+ default:\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+int_classic_div(PyIntObject *x, PyIntObject *y)\r
+{\r
+ long xi, yi;\r
+ long d, m;\r
+ CONVERT_TO_LONG(x, xi);\r
+ CONVERT_TO_LONG(y, yi);\r
+ if (Py_DivisionWarningFlag &&\r
+ PyErr_Warn(PyExc_DeprecationWarning, "classic int division") < 0)\r
+ return NULL;\r
+ switch (i_divmod(xi, yi, &d, &m)) {\r
+ case DIVMOD_OK:\r
+ return PyInt_FromLong(d);\r
+ case DIVMOD_OVERFLOW:\r
+ return PyLong_Type.tp_as_number->nb_divide((PyObject *)x,\r
+ (PyObject *)y);\r
+ default:\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+int_true_divide(PyIntObject *x, PyIntObject *y)\r
+{\r
+ long xi, yi;\r
+ /* If they aren't both ints, give someone else a chance. In\r
+ particular, this lets int/long get handled by longs, which\r
+ underflows to 0 gracefully if the long is too big to convert\r
+ to float. */\r
+ CONVERT_TO_LONG(x, xi);\r
+ CONVERT_TO_LONG(y, yi);\r
+ if (yi == 0) {\r
+ PyErr_SetString(PyExc_ZeroDivisionError,\r
+ "division by zero");\r
+ return NULL;\r
+ }\r
+ if (xi == 0)\r
+ return PyFloat_FromDouble(yi < 0 ? -0.0 : 0.0);\r
+\r
+#define WIDTH_OF_ULONG (CHAR_BIT*SIZEOF_LONG)\r
+#if DBL_MANT_DIG < WIDTH_OF_ULONG\r
+ if ((xi >= 0 ? 0UL + xi : 0UL - xi) >> DBL_MANT_DIG ||\r
+ (yi >= 0 ? 0UL + yi : 0UL - yi) >> DBL_MANT_DIG)\r
+ /* Large x or y. Use long integer arithmetic. */\r
+ return PyLong_Type.tp_as_number->nb_true_divide(\r
+ (PyObject *)x, (PyObject *)y);\r
+ else\r
+#endif\r
+ /* Both ints can be exactly represented as doubles. Do a\r
+ floating-point division. */\r
+ return PyFloat_FromDouble((double)xi / (double)yi);\r
+}\r
+\r
+static PyObject *\r
+int_mod(PyIntObject *x, PyIntObject *y)\r
+{\r
+ long xi, yi;\r
+ long d, m;\r
+ CONVERT_TO_LONG(x, xi);\r
+ CONVERT_TO_LONG(y, yi);\r
+ switch (i_divmod(xi, yi, &d, &m)) {\r
+ case DIVMOD_OK:\r
+ return PyInt_FromLong(m);\r
+ case DIVMOD_OVERFLOW:\r
+ return PyLong_Type.tp_as_number->nb_remainder((PyObject *)x,\r
+ (PyObject *)y);\r
+ default:\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+int_divmod(PyIntObject *x, PyIntObject *y)\r
+{\r
+ long xi, yi;\r
+ long d, m;\r
+ CONVERT_TO_LONG(x, xi);\r
+ CONVERT_TO_LONG(y, yi);\r
+ switch (i_divmod(xi, yi, &d, &m)) {\r
+ case DIVMOD_OK:\r
+ return Py_BuildValue("(ll)", d, m);\r
+ case DIVMOD_OVERFLOW:\r
+ return PyLong_Type.tp_as_number->nb_divmod((PyObject *)x,\r
+ (PyObject *)y);\r
+ default:\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z)\r
+{\r
+ register long iv, iw, iz=0, ix, temp, prev;\r
+ CONVERT_TO_LONG(v, iv);\r
+ CONVERT_TO_LONG(w, iw);\r
+ if (iw < 0) {\r
+ if ((PyObject *)z != Py_None) {\r
+ PyErr_SetString(PyExc_TypeError, "pow() 2nd argument "\r
+ "cannot be negative when 3rd argument specified");\r
+ return NULL;\r
+ }\r
+ /* Return a float. This works because we know that\r
+ this calls float_pow() which converts its\r
+ arguments to double. */\r
+ return PyFloat_Type.tp_as_number->nb_power(\r
+ (PyObject *)v, (PyObject *)w, (PyObject *)z);\r
+ }\r
+ if ((PyObject *)z != Py_None) {\r
+ CONVERT_TO_LONG(z, iz);\r
+ if (iz == 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "pow() 3rd argument cannot be 0");\r
+ return NULL;\r
+ }\r
+ }\r
+ /*\r
+ * XXX: The original exponentiation code stopped looping\r
+ * when temp hit zero; this code will continue onwards\r
+ * unnecessarily, but at least it won't cause any errors.\r
+ * Hopefully the speed improvement from the fast exponentiation\r
+ * will compensate for the slight inefficiency.\r
+ * XXX: Better handling of overflows is desperately needed.\r
+ */\r
+ temp = iv;\r
+ ix = 1;\r
+ while (iw > 0) {\r
+ prev = ix; /* Save value for overflow check */\r
+ if (iw & 1) {\r
+ /*\r
+ * The (unsigned long) cast below ensures that the multiplication\r
+ * is interpreted as an unsigned operation rather than a signed one\r
+ * (C99 6.3.1.8p1), thus avoiding the perils of undefined behaviour\r
+ * from signed arithmetic overflow (C99 6.5p5). See issue #12973.\r
+ */\r
+ ix = (unsigned long)ix * temp;\r
+ if (temp == 0)\r
+ break; /* Avoid ix / 0 */\r
+ if (ix / temp != prev) {\r
+ return PyLong_Type.tp_as_number->nb_power(\r
+ (PyObject *)v,\r
+ (PyObject *)w,\r
+ (PyObject *)z);\r
+ }\r
+ }\r
+ iw >>= 1; /* Shift exponent down by 1 bit */\r
+ if (iw==0) break;\r
+ prev = temp;\r
+ temp = (unsigned long)temp * temp; /* Square the value of temp */\r
+ if (prev != 0 && temp / prev != prev) {\r
+ return PyLong_Type.tp_as_number->nb_power(\r
+ (PyObject *)v, (PyObject *)w, (PyObject *)z);\r
+ }\r
+ if (iz) {\r
+ /* If we did a multiplication, perform a modulo */\r
+ ix = ix % iz;\r
+ temp = temp % iz;\r
+ }\r
+ }\r
+ if (iz) {\r
+ long div, mod;\r
+ switch (i_divmod(ix, iz, &div, &mod)) {\r
+ case DIVMOD_OK:\r
+ ix = mod;\r
+ break;\r
+ case DIVMOD_OVERFLOW:\r
+ return PyLong_Type.tp_as_number->nb_power(\r
+ (PyObject *)v, (PyObject *)w, (PyObject *)z);\r
+ default:\r
+ return NULL;\r
+ }\r
+ }\r
+ return PyInt_FromLong(ix);\r
+}\r
+\r
+static PyObject *\r
+int_neg(PyIntObject *v)\r
+{\r
+ register long a;\r
+ a = v->ob_ival;\r
+ /* check for overflow */\r
+ if (UNARY_NEG_WOULD_OVERFLOW(a)) {\r
+ PyObject *o = PyLong_FromLong(a);\r
+ if (o != NULL) {\r
+ PyObject *result = PyNumber_Negative(o);\r
+ Py_DECREF(o);\r
+ return result;\r
+ }\r
+ return NULL;\r
+ }\r
+ return PyInt_FromLong(-a);\r
+}\r
+\r
+static PyObject *\r
+int_abs(PyIntObject *v)\r
+{\r
+ if (v->ob_ival >= 0)\r
+ return int_int(v);\r
+ else\r
+ return int_neg(v);\r
+}\r
+\r
+static int\r
+int_nonzero(PyIntObject *v)\r
+{\r
+ return v->ob_ival != 0;\r
+}\r
+\r
+static PyObject *\r
+int_invert(PyIntObject *v)\r
+{\r
+ return PyInt_FromLong(~v->ob_ival);\r
+}\r
+\r
+static PyObject *\r
+int_lshift(PyIntObject *v, PyIntObject *w)\r
+{\r
+ long a, b, c;\r
+ PyObject *vv, *ww, *result;\r
+\r
+ CONVERT_TO_LONG(v, a);\r
+ CONVERT_TO_LONG(w, b);\r
+ if (b < 0) {\r
+ PyErr_SetString(PyExc_ValueError, "negative shift count");\r
+ return NULL;\r
+ }\r
+ if (a == 0 || b == 0)\r
+ return int_int(v);\r
+ if (b >= LONG_BIT) {\r
+ vv = PyLong_FromLong(PyInt_AS_LONG(v));\r
+ if (vv == NULL)\r
+ return NULL;\r
+ ww = PyLong_FromLong(PyInt_AS_LONG(w));\r
+ if (ww == NULL) {\r
+ Py_DECREF(vv);\r
+ return NULL;\r
+ }\r
+ result = PyNumber_Lshift(vv, ww);\r
+ Py_DECREF(vv);\r
+ Py_DECREF(ww);\r
+ return result;\r
+ }\r
+ c = a << b;\r
+ if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) {\r
+ vv = PyLong_FromLong(PyInt_AS_LONG(v));\r
+ if (vv == NULL)\r
+ return NULL;\r
+ ww = PyLong_FromLong(PyInt_AS_LONG(w));\r
+ if (ww == NULL) {\r
+ Py_DECREF(vv);\r
+ return NULL;\r
+ }\r
+ result = PyNumber_Lshift(vv, ww);\r
+ Py_DECREF(vv);\r
+ Py_DECREF(ww);\r
+ return result;\r
+ }\r
+ return PyInt_FromLong(c);\r
+}\r
+\r
+static PyObject *\r
+int_rshift(PyIntObject *v, PyIntObject *w)\r
+{\r
+ register long a, b;\r
+ CONVERT_TO_LONG(v, a);\r
+ CONVERT_TO_LONG(w, b);\r
+ if (b < 0) {\r
+ PyErr_SetString(PyExc_ValueError, "negative shift count");\r
+ return NULL;\r
+ }\r
+ if (a == 0 || b == 0)\r
+ return int_int(v);\r
+ if (b >= LONG_BIT) {\r
+ if (a < 0)\r
+ a = -1;\r
+ else\r
+ a = 0;\r
+ }\r
+ else {\r
+ a = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b);\r
+ }\r
+ return PyInt_FromLong(a);\r
+}\r
+\r
+static PyObject *\r
+int_and(PyIntObject *v, PyIntObject *w)\r
+{\r
+ register long a, b;\r
+ CONVERT_TO_LONG(v, a);\r
+ CONVERT_TO_LONG(w, b);\r
+ return PyInt_FromLong(a & b);\r
+}\r
+\r
+static PyObject *\r
+int_xor(PyIntObject *v, PyIntObject *w)\r
+{\r
+ register long a, b;\r
+ CONVERT_TO_LONG(v, a);\r
+ CONVERT_TO_LONG(w, b);\r
+ return PyInt_FromLong(a ^ b);\r
+}\r
+\r
+static PyObject *\r
+int_or(PyIntObject *v, PyIntObject *w)\r
+{\r
+ register long a, b;\r
+ CONVERT_TO_LONG(v, a);\r
+ CONVERT_TO_LONG(w, b);\r
+ return PyInt_FromLong(a | b);\r
+}\r
+\r
+static int\r
+int_coerce(PyObject **pv, PyObject **pw)\r
+{\r
+ if (PyInt_Check(*pw)) {\r
+ Py_INCREF(*pv);\r
+ Py_INCREF(*pw);\r
+ return 0;\r
+ }\r
+ return 1; /* Can't do it */\r
+}\r
+\r
+static PyObject *\r
+int_int(PyIntObject *v)\r
+{\r
+ if (PyInt_CheckExact(v))\r
+ Py_INCREF(v);\r
+ else\r
+ v = (PyIntObject *)PyInt_FromLong(v->ob_ival);\r
+ return (PyObject *)v;\r
+}\r
+\r
+static PyObject *\r
+int_long(PyIntObject *v)\r
+{\r
+ return PyLong_FromLong((v -> ob_ival));\r
+}\r
+\r
+static const unsigned char BitLengthTable[32] = {\r
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,\r
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5\r
+};\r
+\r
+static int\r
+bits_in_ulong(unsigned long d)\r
+{\r
+ int d_bits = 0;\r
+ while (d >= 32) {\r
+ d_bits += 6;\r
+ d >>= 6;\r
+ }\r
+ d_bits += (int)BitLengthTable[d];\r
+ return d_bits;\r
+}\r
+\r
+#if 8*SIZEOF_LONG-1 <= DBL_MANT_DIG\r
+/* Every Python int can be exactly represented as a float. */\r
+\r
+static PyObject *\r
+int_float(PyIntObject *v)\r
+{\r
+ return PyFloat_FromDouble((double)(v -> ob_ival));\r
+}\r
+\r
+#else\r
+/* Here not all Python ints are exactly representable as floats, so we may\r
+ have to round. We do this manually, since the C standards don't specify\r
+ whether converting an integer to a float rounds up or down */\r
+\r
+static PyObject *\r
+int_float(PyIntObject *v)\r
+{\r
+ unsigned long abs_ival, lsb;\r
+ int round_up;\r
+\r
+ if (v->ob_ival < 0)\r
+ abs_ival = 0U-(unsigned long)v->ob_ival;\r
+ else\r
+ abs_ival = (unsigned long)v->ob_ival;\r
+ if (abs_ival < (1L << DBL_MANT_DIG))\r
+ /* small integer; no need to round */\r
+ return PyFloat_FromDouble((double)v->ob_ival);\r
+\r
+ /* Round abs_ival to MANT_DIG significant bits, using the\r
+ round-half-to-even rule. abs_ival & lsb picks out the 'rounding'\r
+ bit: the first bit after the most significant MANT_DIG bits of\r
+ abs_ival. We round up if this bit is set, provided that either:\r
+\r
+ (1) abs_ival isn't exactly halfway between two floats, in which\r
+ case at least one of the bits following the rounding bit must be\r
+ set; i.e., abs_ival & lsb-1 != 0, or:\r
+\r
+ (2) the resulting rounded value has least significant bit 0; or\r
+ in other words the bit above the rounding bit is set (this is the\r
+ 'to-even' bit of round-half-to-even); i.e., abs_ival & 2*lsb != 0\r
+\r
+ The condition "(1) or (2)" equates to abs_ival & 3*lsb-1 != 0. */\r
+\r
+ lsb = 1L << (bits_in_ulong(abs_ival)-DBL_MANT_DIG-1);\r
+ round_up = (abs_ival & lsb) && (abs_ival & (3*lsb-1));\r
+ abs_ival &= -2*lsb;\r
+ if (round_up)\r
+ abs_ival += 2*lsb;\r
+ return PyFloat_FromDouble(v->ob_ival < 0 ?\r
+ -(double)abs_ival :\r
+ (double)abs_ival);\r
+}\r
+\r
+#endif\r
+\r
+static PyObject *\r
+int_oct(PyIntObject *v)\r
+{\r
+ return _PyInt_Format(v, 8, 0);\r
+}\r
+\r
+static PyObject *\r
+int_hex(PyIntObject *v)\r
+{\r
+ return _PyInt_Format(v, 16, 0);\r
+}\r
+\r
+static PyObject *\r
+int_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);\r
+\r
+static PyObject *\r
+int_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *x = NULL;\r
+ int base = -909;\r
+ static char *kwlist[] = {"x", "base", 0};\r
+\r
+ if (type != &PyInt_Type)\r
+ return int_subtype_new(type, args, kwds); /* Wimp out */\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist,\r
+ &x, &base))\r
+ return NULL;\r
+ if (x == NULL) {\r
+ if (base != -909) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "int() missing string argument");\r
+ return NULL;\r
+ }\r
+ return PyInt_FromLong(0L);\r
+ }\r
+ if (base == -909)\r
+ return PyNumber_Int(x);\r
+ if (PyString_Check(x)) {\r
+ /* Since PyInt_FromString doesn't have a length parameter,\r
+ * check here for possible NULs in the string. */\r
+ char *string = PyString_AS_STRING(x);\r
+ if (strlen(string) != PyString_Size(x)) {\r
+ /* create a repr() of the input string,\r
+ * just like PyInt_FromString does */\r
+ PyObject *srepr;\r
+ srepr = PyObject_Repr(x);\r
+ if (srepr == NULL)\r
+ return NULL;\r
+ PyErr_Format(PyExc_ValueError,\r
+ "invalid literal for int() with base %d: %s",\r
+ base, PyString_AS_STRING(srepr));\r
+ Py_DECREF(srepr);\r
+ return NULL;\r
+ }\r
+ return PyInt_FromString(string, NULL, base);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(x))\r
+ return PyInt_FromUnicode(PyUnicode_AS_UNICODE(x),\r
+ PyUnicode_GET_SIZE(x),\r
+ base);\r
+#endif\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "int() can't convert non-string with explicit base");\r
+ return NULL;\r
+}\r
+\r
+/* Wimpy, slow approach to tp_new calls for subtypes of int:\r
+ first create a regular int from whatever arguments we got,\r
+ then allocate a subtype instance and initialize its ob_ival\r
+ from the regular int. The regular int is then thrown away.\r
+*/\r
+static PyObject *\r
+int_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *tmp, *newobj;\r
+ long ival;\r
+\r
+ assert(PyType_IsSubtype(type, &PyInt_Type));\r
+ tmp = int_new(&PyInt_Type, args, kwds);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ if (!PyInt_Check(tmp)) {\r
+ ival = PyLong_AsLong(tmp);\r
+ if (ival == -1 && PyErr_Occurred()) {\r
+ Py_DECREF(tmp);\r
+ return NULL;\r
+ }\r
+ } else {\r
+ ival = ((PyIntObject *)tmp)->ob_ival;\r
+ }\r
+\r
+ newobj = type->tp_alloc(type, 0);\r
+ if (newobj == NULL) {\r
+ Py_DECREF(tmp);\r
+ return NULL;\r
+ }\r
+ ((PyIntObject *)newobj)->ob_ival = ival;\r
+ Py_DECREF(tmp);\r
+ return newobj;\r
+}\r
+\r
+static PyObject *\r
+int_getnewargs(PyIntObject *v)\r
+{\r
+ return Py_BuildValue("(l)", v->ob_ival);\r
+}\r
+\r
+static PyObject *\r
+int_get0(PyIntObject *v, void *context) {\r
+ return PyInt_FromLong(0L);\r
+}\r
+\r
+static PyObject *\r
+int_get1(PyIntObject *v, void *context) {\r
+ return PyInt_FromLong(1L);\r
+}\r
+\r
+/* Convert an integer to a decimal string. On many platforms, this\r
+ will be significantly faster than the general arbitrary-base\r
+ conversion machinery in _PyInt_Format, thanks to optimization\r
+ opportunities offered by division by a compile-time constant. */\r
+static PyObject *\r
+int_to_decimal_string(PyIntObject *v) {\r
+ char buf[sizeof(long)*CHAR_BIT/3+6], *p, *bufend;\r
+ long n = v->ob_ival;\r
+ unsigned long absn;\r
+ p = bufend = buf + sizeof(buf);\r
+ absn = n < 0 ? 0UL - n : n;\r
+ do {\r
+ *--p = '0' + (char)(absn % 10);\r
+ absn /= 10;\r
+ } while (absn);\r
+ if (n < 0)\r
+ *--p = '-';\r
+ return PyString_FromStringAndSize(p, bufend - p);\r
+}\r
+\r
+/* Convert an integer to the given base. Returns a string.\r
+ If base is 2, 8 or 16, add the proper prefix '0b', '0o' or '0x'.\r
+ If newstyle is zero, then use the pre-2.6 behavior of octal having\r
+ a leading "0" */\r
+PyAPI_FUNC(PyObject*)\r
+_PyInt_Format(PyIntObject *v, int base, int newstyle)\r
+{\r
+ /* There are no doubt many, many ways to optimize this, using code\r
+ similar to _PyLong_Format */\r
+ long n = v->ob_ival;\r
+ int negative = n < 0;\r
+ int is_zero = n == 0;\r
+\r
+ /* For the reasoning behind this size, see\r
+ http://c-faq.com/misc/hexio.html. Then, add a few bytes for\r
+ the possible sign and prefix "0[box]" */\r
+ char buf[sizeof(n)*CHAR_BIT+6];\r
+\r
+ /* Start by pointing to the end of the buffer. We fill in from\r
+ the back forward. */\r
+ char* p = &buf[sizeof(buf)];\r
+\r
+ assert(base >= 2 && base <= 36);\r
+\r
+ /* Special case base 10, for speed */\r
+ if (base == 10)\r
+ return int_to_decimal_string(v);\r
+\r
+ do {\r
+ /* I'd use i_divmod, except it doesn't produce the results\r
+ I want when n is negative. So just duplicate the salient\r
+ part here. */\r
+ long div = n / base;\r
+ long mod = n - div * base;\r
+\r
+ /* convert abs(mod) to the right character in [0-9, a-z] */\r
+ char cdigit = (char)(mod < 0 ? -mod : mod);\r
+ cdigit += (cdigit < 10) ? '0' : 'a'-10;\r
+ *--p = cdigit;\r
+\r
+ n = div;\r
+ } while(n);\r
+\r
+ if (base == 2) {\r
+ *--p = 'b';\r
+ *--p = '0';\r
+ }\r
+ else if (base == 8) {\r
+ if (newstyle) {\r
+ *--p = 'o';\r
+ *--p = '0';\r
+ }\r
+ else\r
+ if (!is_zero)\r
+ *--p = '0';\r
+ }\r
+ else if (base == 16) {\r
+ *--p = 'x';\r
+ *--p = '0';\r
+ }\r
+ else {\r
+ *--p = '#';\r
+ *--p = '0' + base%10;\r
+ if (base > 10)\r
+ *--p = '0' + base/10;\r
+ }\r
+ if (negative)\r
+ *--p = '-';\r
+\r
+ return PyString_FromStringAndSize(p, &buf[sizeof(buf)] - p);\r
+}\r
+\r
+static PyObject *\r
+int__format__(PyObject *self, PyObject *args)\r
+{\r
+ PyObject *format_spec;\r
+\r
+ if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))\r
+ return NULL;\r
+ if (PyBytes_Check(format_spec))\r
+ return _PyInt_FormatAdvanced(self,\r
+ PyBytes_AS_STRING(format_spec),\r
+ PyBytes_GET_SIZE(format_spec));\r
+ if (PyUnicode_Check(format_spec)) {\r
+ /* Convert format_spec to a str */\r
+ PyObject *result;\r
+ PyObject *str_spec = PyObject_Str(format_spec);\r
+\r
+ if (str_spec == NULL)\r
+ return NULL;\r
+\r
+ result = _PyInt_FormatAdvanced(self,\r
+ PyBytes_AS_STRING(str_spec),\r
+ PyBytes_GET_SIZE(str_spec));\r
+\r
+ Py_DECREF(str_spec);\r
+ return result;\r
+ }\r
+ PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+int_bit_length(PyIntObject *v)\r
+{\r
+ unsigned long n;\r
+\r
+ if (v->ob_ival < 0)\r
+ /* avoid undefined behaviour when v->ob_ival == -LONG_MAX-1 */\r
+ n = 0U-(unsigned long)v->ob_ival;\r
+ else\r
+ n = (unsigned long)v->ob_ival;\r
+\r
+ return PyInt_FromLong(bits_in_ulong(n));\r
+}\r
+\r
+PyDoc_STRVAR(int_bit_length_doc,\r
+"int.bit_length() -> int\n\\r
+\n\\r
+Number of bits necessary to represent self in binary.\n\\r
+>>> bin(37)\n\\r
+'0b100101'\n\\r
+>>> (37).bit_length()\n\\r
+6");\r
+\r
+#if 0\r
+static PyObject *\r
+int_is_finite(PyObject *v)\r
+{\r
+ Py_RETURN_TRUE;\r
+}\r
+#endif\r
+\r
+static PyMethodDef int_methods[] = {\r
+ {"conjugate", (PyCFunction)int_int, METH_NOARGS,\r
+ "Returns self, the complex conjugate of any int."},\r
+ {"bit_length", (PyCFunction)int_bit_length, METH_NOARGS,\r
+ int_bit_length_doc},\r
+#if 0\r
+ {"is_finite", (PyCFunction)int_is_finite, METH_NOARGS,\r
+ "Returns always True."},\r
+#endif\r
+ {"__trunc__", (PyCFunction)int_int, METH_NOARGS,\r
+ "Truncating an Integral returns itself."},\r
+ {"__getnewargs__", (PyCFunction)int_getnewargs, METH_NOARGS},\r
+ {"__format__", (PyCFunction)int__format__, METH_VARARGS},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyGetSetDef int_getset[] = {\r
+ {"real",\r
+ (getter)int_int, (setter)NULL,\r
+ "the real part of a complex number",\r
+ NULL},\r
+ {"imag",\r
+ (getter)int_get0, (setter)NULL,\r
+ "the imaginary part of a complex number",\r
+ NULL},\r
+ {"numerator",\r
+ (getter)int_int, (setter)NULL,\r
+ "the numerator of a rational number in lowest terms",\r
+ NULL},\r
+ {"denominator",\r
+ (getter)int_get1, (setter)NULL,\r
+ "the denominator of a rational number in lowest terms",\r
+ NULL},\r
+ {NULL} /* Sentinel */\r
+};\r
+\r
+PyDoc_STRVAR(int_doc,\r
+"int(x=0) -> int or long\n\\r
+int(x, base=10) -> int or long\n\\r
+\n\\r
+Convert a number or string to an integer, or return 0 if no arguments\n\\r
+are given. If x is floating point, the conversion truncates towards zero.\n\\r
+If x is outside the integer range, the function returns a long instead.\n\\r
+\n\\r
+If x is not a number or if base is given, then x must be a string or\n\\r
+Unicode object representing an integer literal in the given base. The\n\\r
+literal can be preceded by '+' or '-' and be surrounded by whitespace.\n\\r
+The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to\n\\r
+interpret the base from the string as an integer literal.\n\\r
+>>> int('0b100', base=0)\n\\r
+4");\r
+\r
+static PyNumberMethods int_as_number = {\r
+ (binaryfunc)int_add, /*nb_add*/\r
+ (binaryfunc)int_sub, /*nb_subtract*/\r
+ (binaryfunc)int_mul, /*nb_multiply*/\r
+ (binaryfunc)int_classic_div, /*nb_divide*/\r
+ (binaryfunc)int_mod, /*nb_remainder*/\r
+ (binaryfunc)int_divmod, /*nb_divmod*/\r
+ (ternaryfunc)int_pow, /*nb_power*/\r
+ (unaryfunc)int_neg, /*nb_negative*/\r
+ (unaryfunc)int_int, /*nb_positive*/\r
+ (unaryfunc)int_abs, /*nb_absolute*/\r
+ (inquiry)int_nonzero, /*nb_nonzero*/\r
+ (unaryfunc)int_invert, /*nb_invert*/\r
+ (binaryfunc)int_lshift, /*nb_lshift*/\r
+ (binaryfunc)int_rshift, /*nb_rshift*/\r
+ (binaryfunc)int_and, /*nb_and*/\r
+ (binaryfunc)int_xor, /*nb_xor*/\r
+ (binaryfunc)int_or, /*nb_or*/\r
+ int_coerce, /*nb_coerce*/\r
+ (unaryfunc)int_int, /*nb_int*/\r
+ (unaryfunc)int_long, /*nb_long*/\r
+ (unaryfunc)int_float, /*nb_float*/\r
+ (unaryfunc)int_oct, /*nb_oct*/\r
+ (unaryfunc)int_hex, /*nb_hex*/\r
+ 0, /*nb_inplace_add*/\r
+ 0, /*nb_inplace_subtract*/\r
+ 0, /*nb_inplace_multiply*/\r
+ 0, /*nb_inplace_divide*/\r
+ 0, /*nb_inplace_remainder*/\r
+ 0, /*nb_inplace_power*/\r
+ 0, /*nb_inplace_lshift*/\r
+ 0, /*nb_inplace_rshift*/\r
+ 0, /*nb_inplace_and*/\r
+ 0, /*nb_inplace_xor*/\r
+ 0, /*nb_inplace_or*/\r
+ (binaryfunc)int_div, /* nb_floor_divide */\r
+ (binaryfunc)int_true_divide, /* nb_true_divide */\r
+ 0, /* nb_inplace_floor_divide */\r
+ 0, /* nb_inplace_true_divide */\r
+ (unaryfunc)int_int, /* nb_index */\r
+};\r
+\r
+PyTypeObject PyInt_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "int",\r
+ sizeof(PyIntObject),\r
+ 0,\r
+ (destructor)int_dealloc, /* tp_dealloc */\r
+ (printfunc)int_print, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)int_compare, /* tp_compare */\r
+ (reprfunc)int_to_decimal_string, /* tp_repr */\r
+ &int_as_number, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)int_hash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ (reprfunc)int_to_decimal_string, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |\r
+ Py_TPFLAGS_BASETYPE | Py_TPFLAGS_INT_SUBCLASS, /* tp_flags */\r
+ int_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ int_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ int_getset, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ int_new, /* tp_new */\r
+ (freefunc)int_free, /* tp_free */\r
+};\r
+\r
+int\r
+_PyInt_Init(void)\r
+{\r
+ PyIntObject *v;\r
+ int ival;\r
+#if NSMALLNEGINTS + NSMALLPOSINTS > 0\r
+ for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++) {\r
+ if (!free_list && (free_list = fill_free_list()) == NULL)\r
+ return 0;\r
+ /* PyObject_New is inlined */\r
+ v = free_list;\r
+ free_list = (PyIntObject *)Py_TYPE(v);\r
+ PyObject_INIT(v, &PyInt_Type);\r
+ v->ob_ival = ival;\r
+ small_ints[ival + NSMALLNEGINTS] = v;\r
+ }\r
+#endif\r
+ return 1;\r
+}\r
+\r
+int\r
+PyInt_ClearFreeList(void)\r
+{\r
+ PyIntObject *p;\r
+ PyIntBlock *list, *next;\r
+ int i;\r
+ int u; /* remaining unfreed ints per block */\r
+ int freelist_size = 0;\r
+\r
+ list = block_list;\r
+ block_list = NULL;\r
+ free_list = NULL;\r
+ while (list != NULL) {\r
+ u = 0;\r
+ for (i = 0, p = &list->objects[0];\r
+ i < N_INTOBJECTS;\r
+ i++, p++) {\r
+ if (PyInt_CheckExact(p) && p->ob_refcnt != 0)\r
+ u++;\r
+ }\r
+ next = list->next;\r
+ if (u) {\r
+ list->next = block_list;\r
+ block_list = list;\r
+ for (i = 0, p = &list->objects[0];\r
+ i < N_INTOBJECTS;\r
+ i++, p++) {\r
+ if (!PyInt_CheckExact(p) ||\r
+ p->ob_refcnt == 0) {\r
+ Py_TYPE(p) = (struct _typeobject *)\r
+ free_list;\r
+ free_list = p;\r
+ }\r
+#if NSMALLNEGINTS + NSMALLPOSINTS > 0\r
+ else if (-NSMALLNEGINTS <= p->ob_ival &&\r
+ p->ob_ival < NSMALLPOSINTS &&\r
+ small_ints[p->ob_ival +\r
+ NSMALLNEGINTS] == NULL) {\r
+ Py_INCREF(p);\r
+ small_ints[p->ob_ival +\r
+ NSMALLNEGINTS] = p;\r
+ }\r
+#endif\r
+ }\r
+ }\r
+ else {\r
+ PyMem_FREE(list);\r
+ }\r
+ freelist_size += u;\r
+ list = next;\r
+ }\r
+\r
+ return freelist_size;\r
+}\r
+\r
+void\r
+PyInt_Fini(void)\r
+{\r
+ PyIntObject *p;\r
+ PyIntBlock *list;\r
+ int i;\r
+ int u; /* total unfreed ints per block */\r
+\r
+#if NSMALLNEGINTS + NSMALLPOSINTS > 0\r
+ PyIntObject **q;\r
+\r
+ i = NSMALLNEGINTS + NSMALLPOSINTS;\r
+ q = small_ints;\r
+ while (--i >= 0) {\r
+ Py_XDECREF(*q);\r
+ *q++ = NULL;\r
+ }\r
+#endif\r
+ u = PyInt_ClearFreeList();\r
+ if (!Py_VerboseFlag)\r
+ return;\r
+ fprintf(stderr, "# cleanup ints");\r
+ if (!u) {\r
+ fprintf(stderr, "\n");\r
+ }\r
+ else {\r
+ fprintf(stderr,\r
+ ": %d unfreed int%s\n",\r
+ u, u == 1 ? "" : "s");\r
+ }\r
+ if (Py_VerboseFlag > 1) {\r
+ list = block_list;\r
+ while (list != NULL) {\r
+ for (i = 0, p = &list->objects[0];\r
+ i < N_INTOBJECTS;\r
+ i++, p++) {\r
+ if (PyInt_CheckExact(p) && p->ob_refcnt != 0)\r
+ /* XXX(twouters) cast refcount to\r
+ long until %zd is universally\r
+ available\r
+ */\r
+ fprintf(stderr,\r
+ "# <int at %p, refcnt=%ld, val=%ld>\n",\r
+ p, (long)p->ob_refcnt,\r
+ p->ob_ival);\r
+ }\r
+ list = list->next;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/* Iterator objects */\r
+\r
+#include "Python.h"\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ long it_index;\r
+ PyObject *it_seq; /* Set to NULL when iterator is exhausted */\r
+} seqiterobject;\r
+\r
+PyObject *\r
+PySeqIter_New(PyObject *seq)\r
+{\r
+ seqiterobject *it;\r
+\r
+ if (!PySequence_Check(seq)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+ it->it_index = 0;\r
+ Py_INCREF(seq);\r
+ it->it_seq = seq;\r
+ _PyObject_GC_TRACK(it);\r
+ return (PyObject *)it;\r
+}\r
+\r
+static void\r
+iter_dealloc(seqiterobject *it)\r
+{\r
+ _PyObject_GC_UNTRACK(it);\r
+ Py_XDECREF(it->it_seq);\r
+ PyObject_GC_Del(it);\r
+}\r
+\r
+static int\r
+iter_traverse(seqiterobject *it, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(it->it_seq);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+iter_iternext(PyObject *iterator)\r
+{\r
+ seqiterobject *it;\r
+ PyObject *seq;\r
+ PyObject *result;\r
+\r
+ assert(PySeqIter_Check(iterator));\r
+ it = (seqiterobject *)iterator;\r
+ seq = it->it_seq;\r
+ if (seq == NULL)\r
+ return NULL;\r
+\r
+ result = PySequence_GetItem(seq, it->it_index);\r
+ if (result != NULL) {\r
+ it->it_index++;\r
+ return result;\r
+ }\r
+ if (PyErr_ExceptionMatches(PyExc_IndexError) ||\r
+ PyErr_ExceptionMatches(PyExc_StopIteration))\r
+ {\r
+ PyErr_Clear();\r
+ Py_DECREF(seq);\r
+ it->it_seq = NULL;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+iter_len(seqiterobject *it)\r
+{\r
+ Py_ssize_t seqsize, len;\r
+\r
+ if (it->it_seq) {\r
+ seqsize = PySequence_Size(it->it_seq);\r
+ if (seqsize == -1)\r
+ return NULL;\r
+ len = seqsize - it->it_index;\r
+ if (len >= 0)\r
+ return PyInt_FromSsize_t(len);\r
+ }\r
+ return PyInt_FromLong(0);\r
+}\r
+\r
+PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
+\r
+static PyMethodDef seqiter_methods[] = {\r
+ {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PySeqIter_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "iterator", /* tp_name */\r
+ sizeof(seqiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)iter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)iter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ iter_iternext, /* tp_iternext */\r
+ seqiter_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+};\r
+\r
+/* -------------------------------------- */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyObject *it_callable; /* Set to NULL when iterator is exhausted */\r
+ PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */\r
+} calliterobject;\r
+\r
+PyObject *\r
+PyCallIter_New(PyObject *callable, PyObject *sentinel)\r
+{\r
+ calliterobject *it;\r
+ it = PyObject_GC_New(calliterobject, &PyCallIter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+ Py_INCREF(callable);\r
+ it->it_callable = callable;\r
+ Py_INCREF(sentinel);\r
+ it->it_sentinel = sentinel;\r
+ _PyObject_GC_TRACK(it);\r
+ return (PyObject *)it;\r
+}\r
+static void\r
+calliter_dealloc(calliterobject *it)\r
+{\r
+ _PyObject_GC_UNTRACK(it);\r
+ Py_XDECREF(it->it_callable);\r
+ Py_XDECREF(it->it_sentinel);\r
+ PyObject_GC_Del(it);\r
+}\r
+\r
+static int\r
+calliter_traverse(calliterobject *it, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(it->it_callable);\r
+ Py_VISIT(it->it_sentinel);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+calliter_iternext(calliterobject *it)\r
+{\r
+ if (it->it_callable != NULL) {\r
+ PyObject *args = PyTuple_New(0);\r
+ PyObject *result;\r
+ if (args == NULL)\r
+ return NULL;\r
+ result = PyObject_Call(it->it_callable, args, NULL);\r
+ Py_DECREF(args);\r
+ if (result != NULL) {\r
+ int ok;\r
+ ok = PyObject_RichCompareBool(result,\r
+ it->it_sentinel,\r
+ Py_EQ);\r
+ if (ok == 0)\r
+ return result; /* Common case, fast path */\r
+ Py_DECREF(result);\r
+ if (ok > 0) {\r
+ Py_CLEAR(it->it_callable);\r
+ Py_CLEAR(it->it_sentinel);\r
+ }\r
+ }\r
+ else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {\r
+ PyErr_Clear();\r
+ Py_CLEAR(it->it_callable);\r
+ Py_CLEAR(it->it_sentinel);\r
+ }\r
+ }\r
+ return NULL;\r
+}\r
+\r
+PyTypeObject PyCallIter_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "callable-iterator", /* tp_name */\r
+ sizeof(calliterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)calliter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)calliter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)calliter_iternext, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+};\r
--- /dev/null
+/* List object implementation */\r
+\r
+#include "Python.h"\r
+\r
+#ifdef STDC_HEADERS\r
+#include <stddef.h>\r
+#else\r
+#include <sys/types.h> /* For size_t */\r
+#endif\r
+\r
+/* Ensure ob_item has room for at least newsize elements, and set\r
+ * ob_size to newsize. If newsize > ob_size on entry, the content\r
+ * of the new slots at exit is undefined heap trash; it's the caller's\r
+ * responsibility to overwrite them with sane values.\r
+ * The number of allocated elements may grow, shrink, or stay the same.\r
+ * Failure is impossible if newsize <= self.allocated on entry, although\r
+ * that partly relies on an assumption that the system realloc() never\r
+ * fails when passed a number of bytes <= the number of bytes last\r
+ * allocated (the C standard doesn't guarantee this, but it's hard to\r
+ * imagine a realloc implementation where it wouldn't be true).\r
+ * Note that self->ob_item may change, and even if newsize is less\r
+ * than ob_size on entry.\r
+ */\r
+static int\r
+list_resize(PyListObject *self, Py_ssize_t newsize)\r
+{\r
+ PyObject **items;\r
+ size_t new_allocated;\r
+ Py_ssize_t allocated = self->allocated;\r
+\r
+ /* Bypass realloc() when a previous overallocation is large enough\r
+ to accommodate the newsize. If the newsize falls lower than half\r
+ the allocated size, then proceed with the realloc() to shrink the list.\r
+ */\r
+ if (allocated >= newsize && newsize >= (allocated >> 1)) {\r
+ assert(self->ob_item != NULL || newsize == 0);\r
+ Py_SIZE(self) = newsize;\r
+ return 0;\r
+ }\r
+\r
+ /* This over-allocates proportional to the list size, making room\r
+ * for additional growth. The over-allocation is mild, but is\r
+ * enough to give linear-time amortized behavior over a long\r
+ * sequence of appends() in the presence of a poorly-performing\r
+ * system realloc().\r
+ * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...\r
+ */\r
+ new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);\r
+\r
+ /* check for integer overflow */\r
+ if (new_allocated > PY_SIZE_MAX - newsize) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ } else {\r
+ new_allocated += newsize;\r
+ }\r
+\r
+ if (newsize == 0)\r
+ new_allocated = 0;\r
+ items = self->ob_item;\r
+ if (new_allocated <= (PY_SIZE_MAX / sizeof(PyObject *)))\r
+ PyMem_RESIZE(items, PyObject *, new_allocated);\r
+ else\r
+ items = NULL;\r
+ if (items == NULL) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ self->ob_item = items;\r
+ Py_SIZE(self) = newsize;\r
+ self->allocated = new_allocated;\r
+ return 0;\r
+}\r
+\r
+/* Debug statistic to compare allocations with reuse through the free list */\r
+#undef SHOW_ALLOC_COUNT\r
+#ifdef SHOW_ALLOC_COUNT\r
+static size_t count_alloc = 0;\r
+static size_t count_reuse = 0;\r
+\r
+static void\r
+show_alloc(void)\r
+{\r
+ fprintf(stderr, "List allocations: %" PY_FORMAT_SIZE_T "d\n",\r
+ count_alloc);\r
+ fprintf(stderr, "List reuse through freelist: %" PY_FORMAT_SIZE_T\r
+ "d\n", count_reuse);\r
+ fprintf(stderr, "%.2f%% reuse rate\n\n",\r
+ (100.0*count_reuse/(count_alloc+count_reuse)));\r
+}\r
+#endif\r
+\r
+/* Empty list reuse scheme to save calls to malloc and free */\r
+#ifndef PyList_MAXFREELIST\r
+#define PyList_MAXFREELIST 80\r
+#endif\r
+static PyListObject *free_list[PyList_MAXFREELIST];\r
+static int numfree = 0;\r
+\r
+void\r
+PyList_Fini(void)\r
+{\r
+ PyListObject *op;\r
+\r
+ while (numfree) {\r
+ op = free_list[--numfree];\r
+ assert(PyList_CheckExact(op));\r
+ PyObject_GC_Del(op);\r
+ }\r
+}\r
+\r
+PyObject *\r
+PyList_New(Py_ssize_t size)\r
+{\r
+ PyListObject *op;\r
+ size_t nbytes;\r
+#ifdef SHOW_ALLOC_COUNT\r
+ static int initialized = 0;\r
+ if (!initialized) {\r
+ Py_AtExit(show_alloc);\r
+ initialized = 1;\r
+ }\r
+#endif\r
+\r
+ if (size < 0) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ /* Check for overflow without an actual overflow,\r
+ * which can cause compiler to optimise out */\r
+ if ((size_t)size > PY_SIZE_MAX / sizeof(PyObject *))\r
+ return PyErr_NoMemory();\r
+ nbytes = size * sizeof(PyObject *);\r
+ if (numfree) {\r
+ numfree--;\r
+ op = free_list[numfree];\r
+ _Py_NewReference((PyObject *)op);\r
+#ifdef SHOW_ALLOC_COUNT\r
+ count_reuse++;\r
+#endif\r
+ } else {\r
+ op = PyObject_GC_New(PyListObject, &PyList_Type);\r
+ if (op == NULL)\r
+ return NULL;\r
+#ifdef SHOW_ALLOC_COUNT\r
+ count_alloc++;\r
+#endif\r
+ }\r
+ if (size <= 0)\r
+ op->ob_item = NULL;\r
+ else {\r
+ op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);\r
+ if (op->ob_item == NULL) {\r
+ Py_DECREF(op);\r
+ return PyErr_NoMemory();\r
+ }\r
+ memset(op->ob_item, 0, nbytes);\r
+ }\r
+ Py_SIZE(op) = size;\r
+ op->allocated = size;\r
+ _PyObject_GC_TRACK(op);\r
+ return (PyObject *) op;\r
+}\r
+\r
+Py_ssize_t\r
+PyList_Size(PyObject *op)\r
+{\r
+ if (!PyList_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ else\r
+ return Py_SIZE(op);\r
+}\r
+\r
+static PyObject *indexerr = NULL;\r
+\r
+PyObject *\r
+PyList_GetItem(PyObject *op, Py_ssize_t i)\r
+{\r
+ if (!PyList_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ if (i < 0 || i >= Py_SIZE(op)) {\r
+ if (indexerr == NULL) {\r
+ indexerr = PyString_FromString(\r
+ "list index out of range");\r
+ if (indexerr == NULL)\r
+ return NULL;\r
+ }\r
+ PyErr_SetObject(PyExc_IndexError, indexerr);\r
+ return NULL;\r
+ }\r
+ return ((PyListObject *)op) -> ob_item[i];\r
+}\r
+\r
+int\r
+PyList_SetItem(register PyObject *op, register Py_ssize_t i,\r
+ register PyObject *newitem)\r
+{\r
+ register PyObject *olditem;\r
+ register PyObject **p;\r
+ if (!PyList_Check(op)) {\r
+ Py_XDECREF(newitem);\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ if (i < 0 || i >= Py_SIZE(op)) {\r
+ Py_XDECREF(newitem);\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "list assignment index out of range");\r
+ return -1;\r
+ }\r
+ p = ((PyListObject *)op) -> ob_item + i;\r
+ olditem = *p;\r
+ *p = newitem;\r
+ Py_XDECREF(olditem);\r
+ return 0;\r
+}\r
+\r
+static int\r
+ins1(PyListObject *self, Py_ssize_t where, PyObject *v)\r
+{\r
+ Py_ssize_t i, n = Py_SIZE(self);\r
+ PyObject **items;\r
+ if (v == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ if (n == PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "cannot add more objects to list");\r
+ return -1;\r
+ }\r
+\r
+ if (list_resize(self, n+1) == -1)\r
+ return -1;\r
+\r
+ if (where < 0) {\r
+ where += n;\r
+ if (where < 0)\r
+ where = 0;\r
+ }\r
+ if (where > n)\r
+ where = n;\r
+ items = self->ob_item;\r
+ for (i = n; --i >= where; )\r
+ items[i+1] = items[i];\r
+ Py_INCREF(v);\r
+ items[where] = v;\r
+ return 0;\r
+}\r
+\r
+int\r
+PyList_Insert(PyObject *op, Py_ssize_t where, PyObject *newitem)\r
+{\r
+ if (!PyList_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return ins1((PyListObject *)op, where, newitem);\r
+}\r
+\r
+static int\r
+app1(PyListObject *self, PyObject *v)\r
+{\r
+ Py_ssize_t n = PyList_GET_SIZE(self);\r
+\r
+ assert (v != NULL);\r
+ if (n == PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "cannot add more objects to list");\r
+ return -1;\r
+ }\r
+\r
+ if (list_resize(self, n+1) == -1)\r
+ return -1;\r
+\r
+ Py_INCREF(v);\r
+ PyList_SET_ITEM(self, n, v);\r
+ return 0;\r
+}\r
+\r
+int\r
+PyList_Append(PyObject *op, PyObject *newitem)\r
+{\r
+ if (PyList_Check(op) && (newitem != NULL))\r
+ return app1((PyListObject *)op, newitem);\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+}\r
+\r
+/* Methods */\r
+\r
+static void\r
+list_dealloc(PyListObject *op)\r
+{\r
+ Py_ssize_t i;\r
+ PyObject_GC_UnTrack(op);\r
+ Py_TRASHCAN_SAFE_BEGIN(op)\r
+ if (op->ob_item != NULL) {\r
+ /* Do it backwards, for Christian Tismer.\r
+ There's a simple test case where somehow this reduces\r
+ thrashing when a *very* large list is created and\r
+ immediately deleted. */\r
+ i = Py_SIZE(op);\r
+ while (--i >= 0) {\r
+ Py_XDECREF(op->ob_item[i]);\r
+ }\r
+ PyMem_FREE(op->ob_item);\r
+ }\r
+ if (numfree < PyList_MAXFREELIST && PyList_CheckExact(op))\r
+ free_list[numfree++] = op;\r
+ else\r
+ Py_TYPE(op)->tp_free((PyObject *)op);\r
+ Py_TRASHCAN_SAFE_END(op)\r
+}\r
+\r
+static int\r
+list_print(PyListObject *op, FILE *fp, int flags)\r
+{\r
+ int rc;\r
+ Py_ssize_t i;\r
+ PyObject *item;\r
+\r
+ rc = Py_ReprEnter((PyObject*)op);\r
+ if (rc != 0) {\r
+ if (rc < 0)\r
+ return rc;\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "[...]");\r
+ Py_END_ALLOW_THREADS\r
+ return 0;\r
+ }\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "[");\r
+ Py_END_ALLOW_THREADS\r
+ for (i = 0; i < Py_SIZE(op); i++) {\r
+ item = op->ob_item[i];\r
+ Py_INCREF(item);\r
+ if (i > 0) {\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, ", ");\r
+ Py_END_ALLOW_THREADS\r
+ }\r
+ if (PyObject_Print(item, fp, 0) != 0) {\r
+ Py_DECREF(item);\r
+ Py_ReprLeave((PyObject *)op);\r
+ return -1;\r
+ }\r
+ Py_DECREF(item);\r
+ }\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "]");\r
+ Py_END_ALLOW_THREADS\r
+ Py_ReprLeave((PyObject *)op);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+list_repr(PyListObject *v)\r
+{\r
+ Py_ssize_t i;\r
+ PyObject *s, *temp;\r
+ PyObject *pieces = NULL, *result = NULL;\r
+\r
+ i = Py_ReprEnter((PyObject*)v);\r
+ if (i != 0) {\r
+ return i > 0 ? PyString_FromString("[...]") : NULL;\r
+ }\r
+\r
+ if (Py_SIZE(v) == 0) {\r
+ result = PyString_FromString("[]");\r
+ goto Done;\r
+ }\r
+\r
+ pieces = PyList_New(0);\r
+ if (pieces == NULL)\r
+ goto Done;\r
+\r
+ /* Do repr() on each element. Note that this may mutate the list,\r
+ so must refetch the list size on each iteration. */\r
+ for (i = 0; i < Py_SIZE(v); ++i) {\r
+ int status;\r
+ if (Py_EnterRecursiveCall(" while getting the repr of a list"))\r
+ goto Done;\r
+ s = PyObject_Repr(v->ob_item[i]);\r
+ Py_LeaveRecursiveCall();\r
+ if (s == NULL)\r
+ goto Done;\r
+ status = PyList_Append(pieces, s);\r
+ Py_DECREF(s); /* append created a new ref */\r
+ if (status < 0)\r
+ goto Done;\r
+ }\r
+\r
+ /* Add "[]" decorations to the first and last items. */\r
+ assert(PyList_GET_SIZE(pieces) > 0);\r
+ s = PyString_FromString("[");\r
+ if (s == NULL)\r
+ goto Done;\r
+ temp = PyList_GET_ITEM(pieces, 0);\r
+ PyString_ConcatAndDel(&s, temp);\r
+ PyList_SET_ITEM(pieces, 0, s);\r
+ if (s == NULL)\r
+ goto Done;\r
+\r
+ s = PyString_FromString("]");\r
+ if (s == NULL)\r
+ goto Done;\r
+ temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);\r
+ PyString_ConcatAndDel(&temp, s);\r
+ PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);\r
+ if (temp == NULL)\r
+ goto Done;\r
+\r
+ /* Paste them all together with ", " between. */\r
+ s = PyString_FromString(", ");\r
+ if (s == NULL)\r
+ goto Done;\r
+ result = _PyString_Join(s, pieces);\r
+ Py_DECREF(s);\r
+\r
+Done:\r
+ Py_XDECREF(pieces);\r
+ Py_ReprLeave((PyObject *)v);\r
+ return result;\r
+}\r
+\r
+static Py_ssize_t\r
+list_length(PyListObject *a)\r
+{\r
+ return Py_SIZE(a);\r
+}\r
+\r
+static int\r
+list_contains(PyListObject *a, PyObject *el)\r
+{\r
+ Py_ssize_t i;\r
+ int cmp;\r
+\r
+ for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)\r
+ cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),\r
+ Py_EQ);\r
+ return cmp;\r
+}\r
+\r
+static PyObject *\r
+list_item(PyListObject *a, Py_ssize_t i)\r
+{\r
+ if (i < 0 || i >= Py_SIZE(a)) {\r
+ if (indexerr == NULL) {\r
+ indexerr = PyString_FromString(\r
+ "list index out of range");\r
+ if (indexerr == NULL)\r
+ return NULL;\r
+ }\r
+ PyErr_SetObject(PyExc_IndexError, indexerr);\r
+ return NULL;\r
+ }\r
+ Py_INCREF(a->ob_item[i]);\r
+ return a->ob_item[i];\r
+}\r
+\r
+static PyObject *\r
+list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)\r
+{\r
+ PyListObject *np;\r
+ PyObject **src, **dest;\r
+ Py_ssize_t i, len;\r
+ if (ilow < 0)\r
+ ilow = 0;\r
+ else if (ilow > Py_SIZE(a))\r
+ ilow = Py_SIZE(a);\r
+ if (ihigh < ilow)\r
+ ihigh = ilow;\r
+ else if (ihigh > Py_SIZE(a))\r
+ ihigh = Py_SIZE(a);\r
+ len = ihigh - ilow;\r
+ np = (PyListObject *) PyList_New(len);\r
+ if (np == NULL)\r
+ return NULL;\r
+\r
+ src = a->ob_item + ilow;\r
+ dest = np->ob_item;\r
+ for (i = 0; i < len; i++) {\r
+ PyObject *v = src[i];\r
+ Py_INCREF(v);\r
+ dest[i] = v;\r
+ }\r
+ return (PyObject *)np;\r
+}\r
+\r
+PyObject *\r
+PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)\r
+{\r
+ if (!PyList_Check(a)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return list_slice((PyListObject *)a, ilow, ihigh);\r
+}\r
+\r
+static PyObject *\r
+list_concat(PyListObject *a, PyObject *bb)\r
+{\r
+ Py_ssize_t size;\r
+ Py_ssize_t i;\r
+ PyObject **src, **dest;\r
+ PyListObject *np;\r
+ if (!PyList_Check(bb)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can only concatenate list (not \"%.200s\") to list",\r
+ bb->ob_type->tp_name);\r
+ return NULL;\r
+ }\r
+#define b ((PyListObject *)bb)\r
+ size = Py_SIZE(a) + Py_SIZE(b);\r
+ if (size < 0)\r
+ return PyErr_NoMemory();\r
+ np = (PyListObject *) PyList_New(size);\r
+ if (np == NULL) {\r
+ return NULL;\r
+ }\r
+ src = a->ob_item;\r
+ dest = np->ob_item;\r
+ for (i = 0; i < Py_SIZE(a); i++) {\r
+ PyObject *v = src[i];\r
+ Py_INCREF(v);\r
+ dest[i] = v;\r
+ }\r
+ src = b->ob_item;\r
+ dest = np->ob_item + Py_SIZE(a);\r
+ for (i = 0; i < Py_SIZE(b); i++) {\r
+ PyObject *v = src[i];\r
+ Py_INCREF(v);\r
+ dest[i] = v;\r
+ }\r
+ return (PyObject *)np;\r
+#undef b\r
+}\r
+\r
+static PyObject *\r
+list_repeat(PyListObject *a, Py_ssize_t n)\r
+{\r
+ Py_ssize_t i, j;\r
+ Py_ssize_t size;\r
+ PyListObject *np;\r
+ PyObject **p, **items;\r
+ PyObject *elem;\r
+ if (n < 0)\r
+ n = 0;\r
+ if (n > 0 && Py_SIZE(a) > PY_SSIZE_T_MAX / n)\r
+ return PyErr_NoMemory();\r
+ size = Py_SIZE(a) * n;\r
+ if (size == 0)\r
+ return PyList_New(0);\r
+ np = (PyListObject *) PyList_New(size);\r
+ if (np == NULL)\r
+ return NULL;\r
+\r
+ items = np->ob_item;\r
+ if (Py_SIZE(a) == 1) {\r
+ elem = a->ob_item[0];\r
+ for (i = 0; i < n; i++) {\r
+ items[i] = elem;\r
+ Py_INCREF(elem);\r
+ }\r
+ return (PyObject *) np;\r
+ }\r
+ p = np->ob_item;\r
+ items = a->ob_item;\r
+ for (i = 0; i < n; i++) {\r
+ for (j = 0; j < Py_SIZE(a); j++) {\r
+ *p = items[j];\r
+ Py_INCREF(*p);\r
+ p++;\r
+ }\r
+ }\r
+ return (PyObject *) np;\r
+}\r
+\r
+static int\r
+list_clear(PyListObject *a)\r
+{\r
+ Py_ssize_t i;\r
+ PyObject **item = a->ob_item;\r
+ if (item != NULL) {\r
+ /* Because XDECREF can recursively invoke operations on\r
+ this list, we make it empty first. */\r
+ i = Py_SIZE(a);\r
+ Py_SIZE(a) = 0;\r
+ a->ob_item = NULL;\r
+ a->allocated = 0;\r
+ while (--i >= 0) {\r
+ Py_XDECREF(item[i]);\r
+ }\r
+ PyMem_FREE(item);\r
+ }\r
+ /* Never fails; the return value can be ignored.\r
+ Note that there is no guarantee that the list is actually empty\r
+ at this point, because XDECREF may have populated it again! */\r
+ return 0;\r
+}\r
+\r
+/* a[ilow:ihigh] = v if v != NULL.\r
+ * del a[ilow:ihigh] if v == NULL.\r
+ *\r
+ * Special speed gimmick: when v is NULL and ihigh - ilow <= 8, it's\r
+ * guaranteed the call cannot fail.\r
+ */\r
+static int\r
+list_ass_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)\r
+{\r
+ /* Because [X]DECREF can recursively invoke list operations on\r
+ this list, we must postpone all [X]DECREF activity until\r
+ after the list is back in its canonical shape. Therefore\r
+ we must allocate an additional array, 'recycle', into which\r
+ we temporarily copy the items that are deleted from the\r
+ list. :-( */\r
+ PyObject *recycle_on_stack[8];\r
+ PyObject **recycle = recycle_on_stack; /* will allocate more if needed */\r
+ PyObject **item;\r
+ PyObject **vitem = NULL;\r
+ PyObject *v_as_SF = NULL; /* PySequence_Fast(v) */\r
+ Py_ssize_t n; /* # of elements in replacement list */\r
+ Py_ssize_t norig; /* # of elements in list getting replaced */\r
+ Py_ssize_t d; /* Change in size */\r
+ Py_ssize_t k;\r
+ size_t s;\r
+ int result = -1; /* guilty until proved innocent */\r
+#define b ((PyListObject *)v)\r
+ if (v == NULL)\r
+ n = 0;\r
+ else {\r
+ if (a == b) {\r
+ /* Special case "a[i:j] = a" -- copy b first */\r
+ v = list_slice(b, 0, Py_SIZE(b));\r
+ if (v == NULL)\r
+ return result;\r
+ result = list_ass_slice(a, ilow, ihigh, v);\r
+ Py_DECREF(v);\r
+ return result;\r
+ }\r
+ v_as_SF = PySequence_Fast(v, "can only assign an iterable");\r
+ if(v_as_SF == NULL)\r
+ goto Error;\r
+ n = PySequence_Fast_GET_SIZE(v_as_SF);\r
+ vitem = PySequence_Fast_ITEMS(v_as_SF);\r
+ }\r
+ if (ilow < 0)\r
+ ilow = 0;\r
+ else if (ilow > Py_SIZE(a))\r
+ ilow = Py_SIZE(a);\r
+\r
+ if (ihigh < ilow)\r
+ ihigh = ilow;\r
+ else if (ihigh > Py_SIZE(a))\r
+ ihigh = Py_SIZE(a);\r
+\r
+ norig = ihigh - ilow;\r
+ assert(norig >= 0);\r
+ d = n - norig;\r
+ if (Py_SIZE(a) + d == 0) {\r
+ Py_XDECREF(v_as_SF);\r
+ return list_clear(a);\r
+ }\r
+ item = a->ob_item;\r
+ /* recycle the items that we are about to remove */\r
+ s = norig * sizeof(PyObject *);\r
+ if (s > sizeof(recycle_on_stack)) {\r
+ recycle = (PyObject **)PyMem_MALLOC(s);\r
+ if (recycle == NULL) {\r
+ PyErr_NoMemory();\r
+ goto Error;\r
+ }\r
+ }\r
+ memcpy(recycle, &item[ilow], s);\r
+\r
+ if (d < 0) { /* Delete -d items */\r
+ memmove(&item[ihigh+d], &item[ihigh],\r
+ (Py_SIZE(a) - ihigh)*sizeof(PyObject *));\r
+ list_resize(a, Py_SIZE(a) + d);\r
+ item = a->ob_item;\r
+ }\r
+ else if (d > 0) { /* Insert d items */\r
+ k = Py_SIZE(a);\r
+ if (list_resize(a, k+d) < 0)\r
+ goto Error;\r
+ item = a->ob_item;\r
+ memmove(&item[ihigh+d], &item[ihigh],\r
+ (k - ihigh)*sizeof(PyObject *));\r
+ }\r
+ for (k = 0; k < n; k++, ilow++) {\r
+ PyObject *w = vitem[k];\r
+ Py_XINCREF(w);\r
+ item[ilow] = w;\r
+ }\r
+ for (k = norig - 1; k >= 0; --k)\r
+ Py_XDECREF(recycle[k]);\r
+ result = 0;\r
+ Error:\r
+ if (recycle != recycle_on_stack)\r
+ PyMem_FREE(recycle);\r
+ Py_XDECREF(v_as_SF);\r
+ return result;\r
+#undef b\r
+}\r
+\r
+int\r
+PyList_SetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)\r
+{\r
+ if (!PyList_Check(a)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return list_ass_slice((PyListObject *)a, ilow, ihigh, v);\r
+}\r
+\r
+static PyObject *\r
+list_inplace_repeat(PyListObject *self, Py_ssize_t n)\r
+{\r
+ PyObject **items;\r
+ Py_ssize_t size, i, j, p;\r
+\r
+\r
+ size = PyList_GET_SIZE(self);\r
+ if (size == 0 || n == 1) {\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+ }\r
+\r
+ if (n < 1) {\r
+ (void)list_clear(self);\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+ }\r
+\r
+ if (size > PY_SSIZE_T_MAX / n) {\r
+ return PyErr_NoMemory();\r
+ }\r
+\r
+ if (list_resize(self, size*n) == -1)\r
+ return NULL;\r
+\r
+ p = size;\r
+ items = self->ob_item;\r
+ for (i = 1; i < n; i++) { /* Start counting at 1, not 0 */\r
+ for (j = 0; j < size; j++) {\r
+ PyObject *o = items[j];\r
+ Py_INCREF(o);\r
+ items[p++] = o;\r
+ }\r
+ }\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+}\r
+\r
+static int\r
+list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v)\r
+{\r
+ PyObject *old_value;\r
+ if (i < 0 || i >= Py_SIZE(a)) {\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "list assignment index out of range");\r
+ return -1;\r
+ }\r
+ if (v == NULL)\r
+ return list_ass_slice(a, i, i+1, v);\r
+ Py_INCREF(v);\r
+ old_value = a->ob_item[i];\r
+ a->ob_item[i] = v;\r
+ Py_DECREF(old_value);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+listinsert(PyListObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t i;\r
+ PyObject *v;\r
+ if (!PyArg_ParseTuple(args, "nO:insert", &i, &v))\r
+ return NULL;\r
+ if (ins1(self, i, v) == 0)\r
+ Py_RETURN_NONE;\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+listappend(PyListObject *self, PyObject *v)\r
+{\r
+ if (app1(self, v) == 0)\r
+ Py_RETURN_NONE;\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+listextend(PyListObject *self, PyObject *b)\r
+{\r
+ PyObject *it; /* iter(v) */\r
+ Py_ssize_t m; /* size of self */\r
+ Py_ssize_t n; /* guess for size of b */\r
+ Py_ssize_t mn; /* m + n */\r
+ Py_ssize_t i;\r
+ PyObject *(*iternext)(PyObject *);\r
+\r
+ /* Special cases:\r
+ 1) lists and tuples which can use PySequence_Fast ops\r
+ 2) extending self to self requires making a copy first\r
+ */\r
+ if (PyList_CheckExact(b) || PyTuple_CheckExact(b) || (PyObject *)self == b) {\r
+ PyObject **src, **dest;\r
+ b = PySequence_Fast(b, "argument must be iterable");\r
+ if (!b)\r
+ return NULL;\r
+ n = PySequence_Fast_GET_SIZE(b);\r
+ if (n == 0) {\r
+ /* short circuit when b is empty */\r
+ Py_DECREF(b);\r
+ Py_RETURN_NONE;\r
+ }\r
+ m = Py_SIZE(self);\r
+ if (list_resize(self, m + n) == -1) {\r
+ Py_DECREF(b);\r
+ return NULL;\r
+ }\r
+ /* note that we may still have self == b here for the\r
+ * situation a.extend(a), but the following code works\r
+ * in that case too. Just make sure to resize self\r
+ * before calling PySequence_Fast_ITEMS.\r
+ */\r
+ /* populate the end of self with b's items */\r
+ src = PySequence_Fast_ITEMS(b);\r
+ dest = self->ob_item + m;\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *o = src[i];\r
+ Py_INCREF(o);\r
+ dest[i] = o;\r
+ }\r
+ Py_DECREF(b);\r
+ Py_RETURN_NONE;\r
+ }\r
+\r
+ it = PyObject_GetIter(b);\r
+ if (it == NULL)\r
+ return NULL;\r
+ iternext = *it->ob_type->tp_iternext;\r
+\r
+ /* Guess a result list size. */\r
+ n = _PyObject_LengthHint(b, 8);\r
+ if (n == -1) {\r
+ Py_DECREF(it);\r
+ return NULL;\r
+ }\r
+ m = Py_SIZE(self);\r
+ mn = m + n;\r
+ if (mn >= m) {\r
+ /* Make room. */\r
+ if (list_resize(self, mn) == -1)\r
+ goto error;\r
+ /* Make the list sane again. */\r
+ Py_SIZE(self) = m;\r
+ }\r
+ /* Else m + n overflowed; on the chance that n lied, and there really\r
+ * is enough room, ignore it. If n was telling the truth, we'll\r
+ * eventually run out of memory during the loop.\r
+ */\r
+\r
+ /* Run iterator to exhaustion. */\r
+ for (;;) {\r
+ PyObject *item = iternext(it);\r
+ if (item == NULL) {\r
+ if (PyErr_Occurred()) {\r
+ if (PyErr_ExceptionMatches(PyExc_StopIteration))\r
+ PyErr_Clear();\r
+ else\r
+ goto error;\r
+ }\r
+ break;\r
+ }\r
+ if (Py_SIZE(self) < self->allocated) {\r
+ /* steals ref */\r
+ PyList_SET_ITEM(self, Py_SIZE(self), item);\r
+ ++Py_SIZE(self);\r
+ }\r
+ else {\r
+ int status = app1(self, item);\r
+ Py_DECREF(item); /* append creates a new ref */\r
+ if (status < 0)\r
+ goto error;\r
+ }\r
+ }\r
+\r
+ /* Cut back result list if initial guess was too large. */\r
+ if (Py_SIZE(self) < self->allocated)\r
+ list_resize(self, Py_SIZE(self)); /* shrinking can't fail */\r
+\r
+ Py_DECREF(it);\r
+ Py_RETURN_NONE;\r
+\r
+ error:\r
+ Py_DECREF(it);\r
+ return NULL;\r
+}\r
+\r
+PyObject *\r
+_PyList_Extend(PyListObject *self, PyObject *b)\r
+{\r
+ return listextend(self, b);\r
+}\r
+\r
+static PyObject *\r
+list_inplace_concat(PyListObject *self, PyObject *other)\r
+{\r
+ PyObject *result;\r
+\r
+ result = listextend(self, other);\r
+ if (result == NULL)\r
+ return result;\r
+ Py_DECREF(result);\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+}\r
+\r
+static PyObject *\r
+listpop(PyListObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t i = -1;\r
+ PyObject *v;\r
+ int status;\r
+\r
+ if (!PyArg_ParseTuple(args, "|n:pop", &i))\r
+ return NULL;\r
+\r
+ if (Py_SIZE(self) == 0) {\r
+ /* Special-case most common failure cause */\r
+ PyErr_SetString(PyExc_IndexError, "pop from empty list");\r
+ return NULL;\r
+ }\r
+ if (i < 0)\r
+ i += Py_SIZE(self);\r
+ if (i < 0 || i >= Py_SIZE(self)) {\r
+ PyErr_SetString(PyExc_IndexError, "pop index out of range");\r
+ return NULL;\r
+ }\r
+ v = self->ob_item[i];\r
+ if (i == Py_SIZE(self) - 1) {\r
+ status = list_resize(self, Py_SIZE(self) - 1);\r
+ assert(status >= 0);\r
+ return v; /* and v now owns the reference the list had */\r
+ }\r
+ Py_INCREF(v);\r
+ status = list_ass_slice(self, i, i+1, (PyObject *)NULL);\r
+ assert(status >= 0);\r
+ /* Use status, so that in a release build compilers don't\r
+ * complain about the unused name.\r
+ */\r
+ (void) status;\r
+\r
+ return v;\r
+}\r
+\r
+/* Reverse a slice of a list in place, from lo up to (exclusive) hi. */\r
+static void\r
+reverse_slice(PyObject **lo, PyObject **hi)\r
+{\r
+ assert(lo && hi);\r
+\r
+ --hi;\r
+ while (lo < hi) {\r
+ PyObject *t = *lo;\r
+ *lo = *hi;\r
+ *hi = t;\r
+ ++lo;\r
+ --hi;\r
+ }\r
+}\r
+\r
+/* Lots of code for an adaptive, stable, natural mergesort. There are many\r
+ * pieces to this algorithm; read listsort.txt for overviews and details.\r
+ */\r
+\r
+/* Comparison function. Takes care of calling a user-supplied\r
+ * comparison function (any callable Python object), which must not be\r
+ * NULL (use the ISLT macro if you don't know, or call PyObject_RichCompareBool\r
+ * with Py_LT if you know it's NULL).\r
+ * Returns -1 on error, 1 if x < y, 0 if x >= y.\r
+ */\r
+static int\r
+islt(PyObject *x, PyObject *y, PyObject *compare)\r
+{\r
+ PyObject *res;\r
+ PyObject *args;\r
+ Py_ssize_t i;\r
+\r
+ assert(compare != NULL);\r
+ /* Call the user's comparison function and translate the 3-way\r
+ * result into true or false (or error).\r
+ */\r
+ args = PyTuple_New(2);\r
+ if (args == NULL)\r
+ return -1;\r
+ Py_INCREF(x);\r
+ Py_INCREF(y);\r
+ PyTuple_SET_ITEM(args, 0, x);\r
+ PyTuple_SET_ITEM(args, 1, y);\r
+ res = PyObject_Call(compare, args, NULL);\r
+ Py_DECREF(args);\r
+ if (res == NULL)\r
+ return -1;\r
+ if (!PyInt_Check(res)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "comparison function must return int, not %.200s",\r
+ res->ob_type->tp_name);\r
+ Py_DECREF(res);\r
+ return -1;\r
+ }\r
+ i = PyInt_AsLong(res);\r
+ Py_DECREF(res);\r
+ return i < 0;\r
+}\r
+\r
+/* If COMPARE is NULL, calls PyObject_RichCompareBool with Py_LT, else calls\r
+ * islt. This avoids a layer of function call in the usual case, and\r
+ * sorting does many comparisons.\r
+ * Returns -1 on error, 1 if x < y, 0 if x >= y.\r
+ */\r
+#define ISLT(X, Y, COMPARE) ((COMPARE) == NULL ? \\r
+ PyObject_RichCompareBool(X, Y, Py_LT) : \\r
+ islt(X, Y, COMPARE))\r
+\r
+/* Compare X to Y via "<". Goto "fail" if the comparison raises an\r
+ error. Else "k" is set to true iff X<Y, and an "if (k)" block is\r
+ started. It makes more sense in context <wink>. X and Y are PyObject*s.\r
+*/\r
+#define IFLT(X, Y) if ((k = ISLT(X, Y, compare)) < 0) goto fail; \\r
+ if (k)\r
+\r
+/* binarysort is the best method for sorting small arrays: it does\r
+ few compares, but can do data movement quadratic in the number of\r
+ elements.\r
+ [lo, hi) is a contiguous slice of a list, and is sorted via\r
+ binary insertion. This sort is stable.\r
+ On entry, must have lo <= start <= hi, and that [lo, start) is already\r
+ sorted (pass start == lo if you don't know!).\r
+ If islt() complains return -1, else 0.\r
+ Even in case of error, the output slice will be some permutation of\r
+ the input (nothing is lost or duplicated).\r
+*/\r
+static int\r
+binarysort(PyObject **lo, PyObject **hi, PyObject **start, PyObject *compare)\r
+ /* compare -- comparison function object, or NULL for default */\r
+{\r
+ register Py_ssize_t k;\r
+ register PyObject **l, **p, **r;\r
+ register PyObject *pivot;\r
+\r
+ assert(lo <= start && start <= hi);\r
+ /* assert [lo, start) is sorted */\r
+ if (lo == start)\r
+ ++start;\r
+ for (; start < hi; ++start) {\r
+ /* set l to where *start belongs */\r
+ l = lo;\r
+ r = start;\r
+ pivot = *r;\r
+ /* Invariants:\r
+ * pivot >= all in [lo, l).\r
+ * pivot < all in [r, start).\r
+ * The second is vacuously true at the start.\r
+ */\r
+ assert(l < r);\r
+ do {\r
+ p = l + ((r - l) >> 1);\r
+ IFLT(pivot, *p)\r
+ r = p;\r
+ else\r
+ l = p+1;\r
+ } while (l < r);\r
+ assert(l == r);\r
+ /* The invariants still hold, so pivot >= all in [lo, l) and\r
+ pivot < all in [l, start), so pivot belongs at l. Note\r
+ that if there are elements equal to pivot, l points to the\r
+ first slot after them -- that's why this sort is stable.\r
+ Slide over to make room.\r
+ Caution: using memmove is much slower under MSVC 5;\r
+ we're not usually moving many slots. */\r
+ for (p = start; p > l; --p)\r
+ *p = *(p-1);\r
+ *l = pivot;\r
+ }\r
+ return 0;\r
+\r
+ fail:\r
+ return -1;\r
+}\r
+\r
+/*\r
+Return the length of the run beginning at lo, in the slice [lo, hi). lo < hi\r
+is required on entry. "A run" is the longest ascending sequence, with\r
+\r
+ lo[0] <= lo[1] <= lo[2] <= ...\r
+\r
+or the longest descending sequence, with\r
+\r
+ lo[0] > lo[1] > lo[2] > ...\r
+\r
+Boolean *descending is set to 0 in the former case, or to 1 in the latter.\r
+For its intended use in a stable mergesort, the strictness of the defn of\r
+"descending" is needed so that the caller can safely reverse a descending\r
+sequence without violating stability (strict > ensures there are no equal\r
+elements to get out of order).\r
+\r
+Returns -1 in case of error.\r
+*/\r
+static Py_ssize_t\r
+count_run(PyObject **lo, PyObject **hi, PyObject *compare, int *descending)\r
+{\r
+ Py_ssize_t k;\r
+ Py_ssize_t n;\r
+\r
+ assert(lo < hi);\r
+ *descending = 0;\r
+ ++lo;\r
+ if (lo == hi)\r
+ return 1;\r
+\r
+ n = 2;\r
+ IFLT(*lo, *(lo-1)) {\r
+ *descending = 1;\r
+ for (lo = lo+1; lo < hi; ++lo, ++n) {\r
+ IFLT(*lo, *(lo-1))\r
+ ;\r
+ else\r
+ break;\r
+ }\r
+ }\r
+ else {\r
+ for (lo = lo+1; lo < hi; ++lo, ++n) {\r
+ IFLT(*lo, *(lo-1))\r
+ break;\r
+ }\r
+ }\r
+\r
+ return n;\r
+fail:\r
+ return -1;\r
+}\r
+\r
+/*\r
+Locate the proper position of key in a sorted vector; if the vector contains\r
+an element equal to key, return the position immediately to the left of\r
+the leftmost equal element. [gallop_right() does the same except returns\r
+the position to the right of the rightmost equal element (if any).]\r
+\r
+"a" is a sorted vector with n elements, starting at a[0]. n must be > 0.\r
+\r
+"hint" is an index at which to begin the search, 0 <= hint < n. The closer\r
+hint is to the final result, the faster this runs.\r
+\r
+The return value is the int k in 0..n such that\r
+\r
+ a[k-1] < key <= a[k]\r
+\r
+pretending that *(a-1) is minus infinity and a[n] is plus infinity. IOW,\r
+key belongs at index k; or, IOW, the first k elements of a should precede\r
+key, and the last n-k should follow key.\r
+\r
+Returns -1 on error. See listsort.txt for info on the method.\r
+*/\r
+static Py_ssize_t\r
+gallop_left(PyObject *key, PyObject **a, Py_ssize_t n, Py_ssize_t hint, PyObject *compare)\r
+{\r
+ Py_ssize_t ofs;\r
+ Py_ssize_t lastofs;\r
+ Py_ssize_t k;\r
+\r
+ assert(key && a && n > 0 && hint >= 0 && hint < n);\r
+\r
+ a += hint;\r
+ lastofs = 0;\r
+ ofs = 1;\r
+ IFLT(*a, key) {\r
+ /* a[hint] < key -- gallop right, until\r
+ * a[hint + lastofs] < key <= a[hint + ofs]\r
+ */\r
+ const Py_ssize_t maxofs = n - hint; /* &a[n-1] is highest */\r
+ while (ofs < maxofs) {\r
+ IFLT(a[ofs], key) {\r
+ lastofs = ofs;\r
+ ofs = (ofs << 1) + 1;\r
+ if (ofs <= 0) /* int overflow */\r
+ ofs = maxofs;\r
+ }\r
+ else /* key <= a[hint + ofs] */\r
+ break;\r
+ }\r
+ if (ofs > maxofs)\r
+ ofs = maxofs;\r
+ /* Translate back to offsets relative to &a[0]. */\r
+ lastofs += hint;\r
+ ofs += hint;\r
+ }\r
+ else {\r
+ /* key <= a[hint] -- gallop left, until\r
+ * a[hint - ofs] < key <= a[hint - lastofs]\r
+ */\r
+ const Py_ssize_t maxofs = hint + 1; /* &a[0] is lowest */\r
+ while (ofs < maxofs) {\r
+ IFLT(*(a-ofs), key)\r
+ break;\r
+ /* key <= a[hint - ofs] */\r
+ lastofs = ofs;\r
+ ofs = (ofs << 1) + 1;\r
+ if (ofs <= 0) /* int overflow */\r
+ ofs = maxofs;\r
+ }\r
+ if (ofs > maxofs)\r
+ ofs = maxofs;\r
+ /* Translate back to positive offsets relative to &a[0]. */\r
+ k = lastofs;\r
+ lastofs = hint - ofs;\r
+ ofs = hint - k;\r
+ }\r
+ a -= hint;\r
+\r
+ assert(-1 <= lastofs && lastofs < ofs && ofs <= n);\r
+ /* Now a[lastofs] < key <= a[ofs], so key belongs somewhere to the\r
+ * right of lastofs but no farther right than ofs. Do a binary\r
+ * search, with invariant a[lastofs-1] < key <= a[ofs].\r
+ */\r
+ ++lastofs;\r
+ while (lastofs < ofs) {\r
+ Py_ssize_t m = lastofs + ((ofs - lastofs) >> 1);\r
+\r
+ IFLT(a[m], key)\r
+ lastofs = m+1; /* a[m] < key */\r
+ else\r
+ ofs = m; /* key <= a[m] */\r
+ }\r
+ assert(lastofs == ofs); /* so a[ofs-1] < key <= a[ofs] */\r
+ return ofs;\r
+\r
+fail:\r
+ return -1;\r
+}\r
+\r
+/*\r
+Exactly like gallop_left(), except that if key already exists in a[0:n],\r
+finds the position immediately to the right of the rightmost equal value.\r
+\r
+The return value is the int k in 0..n such that\r
+\r
+ a[k-1] <= key < a[k]\r
+\r
+or -1 if error.\r
+\r
+The code duplication is massive, but this is enough different given that\r
+we're sticking to "<" comparisons that it's much harder to follow if\r
+written as one routine with yet another "left or right?" flag.\r
+*/\r
+static Py_ssize_t\r
+gallop_right(PyObject *key, PyObject **a, Py_ssize_t n, Py_ssize_t hint, PyObject *compare)\r
+{\r
+ Py_ssize_t ofs;\r
+ Py_ssize_t lastofs;\r
+ Py_ssize_t k;\r
+\r
+ assert(key && a && n > 0 && hint >= 0 && hint < n);\r
+\r
+ a += hint;\r
+ lastofs = 0;\r
+ ofs = 1;\r
+ IFLT(key, *a) {\r
+ /* key < a[hint] -- gallop left, until\r
+ * a[hint - ofs] <= key < a[hint - lastofs]\r
+ */\r
+ const Py_ssize_t maxofs = hint + 1; /* &a[0] is lowest */\r
+ while (ofs < maxofs) {\r
+ IFLT(key, *(a-ofs)) {\r
+ lastofs = ofs;\r
+ ofs = (ofs << 1) + 1;\r
+ if (ofs <= 0) /* int overflow */\r
+ ofs = maxofs;\r
+ }\r
+ else /* a[hint - ofs] <= key */\r
+ break;\r
+ }\r
+ if (ofs > maxofs)\r
+ ofs = maxofs;\r
+ /* Translate back to positive offsets relative to &a[0]. */\r
+ k = lastofs;\r
+ lastofs = hint - ofs;\r
+ ofs = hint - k;\r
+ }\r
+ else {\r
+ /* a[hint] <= key -- gallop right, until\r
+ * a[hint + lastofs] <= key < a[hint + ofs]\r
+ */\r
+ const Py_ssize_t maxofs = n - hint; /* &a[n-1] is highest */\r
+ while (ofs < maxofs) {\r
+ IFLT(key, a[ofs])\r
+ break;\r
+ /* a[hint + ofs] <= key */\r
+ lastofs = ofs;\r
+ ofs = (ofs << 1) + 1;\r
+ if (ofs <= 0) /* int overflow */\r
+ ofs = maxofs;\r
+ }\r
+ if (ofs > maxofs)\r
+ ofs = maxofs;\r
+ /* Translate back to offsets relative to &a[0]. */\r
+ lastofs += hint;\r
+ ofs += hint;\r
+ }\r
+ a -= hint;\r
+\r
+ assert(-1 <= lastofs && lastofs < ofs && ofs <= n);\r
+ /* Now a[lastofs] <= key < a[ofs], so key belongs somewhere to the\r
+ * right of lastofs but no farther right than ofs. Do a binary\r
+ * search, with invariant a[lastofs-1] <= key < a[ofs].\r
+ */\r
+ ++lastofs;\r
+ while (lastofs < ofs) {\r
+ Py_ssize_t m = lastofs + ((ofs - lastofs) >> 1);\r
+\r
+ IFLT(key, a[m])\r
+ ofs = m; /* key < a[m] */\r
+ else\r
+ lastofs = m+1; /* a[m] <= key */\r
+ }\r
+ assert(lastofs == ofs); /* so a[ofs-1] <= key < a[ofs] */\r
+ return ofs;\r
+\r
+fail:\r
+ return -1;\r
+}\r
+\r
+/* The maximum number of entries in a MergeState's pending-runs stack.\r
+ * This is enough to sort arrays of size up to about\r
+ * 32 * phi ** MAX_MERGE_PENDING\r
+ * where phi ~= 1.618. 85 is ridiculouslylarge enough, good for an array\r
+ * with 2**64 elements.\r
+ */\r
+#define MAX_MERGE_PENDING 85\r
+\r
+/* When we get into galloping mode, we stay there until both runs win less\r
+ * often than MIN_GALLOP consecutive times. See listsort.txt for more info.\r
+ */\r
+#define MIN_GALLOP 7\r
+\r
+/* Avoid malloc for small temp arrays. */\r
+#define MERGESTATE_TEMP_SIZE 256\r
+\r
+/* One MergeState exists on the stack per invocation of mergesort. It's just\r
+ * a convenient way to pass state around among the helper functions.\r
+ */\r
+struct s_slice {\r
+ PyObject **base;\r
+ Py_ssize_t len;\r
+};\r
+\r
+typedef struct s_MergeState {\r
+ /* The user-supplied comparison function. or NULL if none given. */\r
+ PyObject *compare;\r
+\r
+ /* This controls when we get *into* galloping mode. It's initialized\r
+ * to MIN_GALLOP. merge_lo and merge_hi tend to nudge it higher for\r
+ * random data, and lower for highly structured data.\r
+ */\r
+ Py_ssize_t min_gallop;\r
+\r
+ /* 'a' is temp storage to help with merges. It contains room for\r
+ * alloced entries.\r
+ */\r
+ PyObject **a; /* may point to temparray below */\r
+ Py_ssize_t alloced;\r
+\r
+ /* A stack of n pending runs yet to be merged. Run #i starts at\r
+ * address base[i] and extends for len[i] elements. It's always\r
+ * true (so long as the indices are in bounds) that\r
+ *\r
+ * pending[i].base + pending[i].len == pending[i+1].base\r
+ *\r
+ * so we could cut the storage for this, but it's a minor amount,\r
+ * and keeping all the info explicit simplifies the code.\r
+ */\r
+ int n;\r
+ struct s_slice pending[MAX_MERGE_PENDING];\r
+\r
+ /* 'a' points to this when possible, rather than muck with malloc. */\r
+ PyObject *temparray[MERGESTATE_TEMP_SIZE];\r
+} MergeState;\r
+\r
+/* Conceptually a MergeState's constructor. */\r
+static void\r
+merge_init(MergeState *ms, PyObject *compare)\r
+{\r
+ assert(ms != NULL);\r
+ ms->compare = compare;\r
+ ms->a = ms->temparray;\r
+ ms->alloced = MERGESTATE_TEMP_SIZE;\r
+ ms->n = 0;\r
+ ms->min_gallop = MIN_GALLOP;\r
+}\r
+\r
+/* Free all the temp memory owned by the MergeState. This must be called\r
+ * when you're done with a MergeState, and may be called before then if\r
+ * you want to free the temp memory early.\r
+ */\r
+static void\r
+merge_freemem(MergeState *ms)\r
+{\r
+ assert(ms != NULL);\r
+ if (ms->a != ms->temparray)\r
+ PyMem_Free(ms->a);\r
+ ms->a = ms->temparray;\r
+ ms->alloced = MERGESTATE_TEMP_SIZE;\r
+}\r
+\r
+/* Ensure enough temp memory for 'need' array slots is available.\r
+ * Returns 0 on success and -1 if the memory can't be gotten.\r
+ */\r
+static int\r
+merge_getmem(MergeState *ms, Py_ssize_t need)\r
+{\r
+ assert(ms != NULL);\r
+ if (need <= ms->alloced)\r
+ return 0;\r
+ /* Don't realloc! That can cost cycles to copy the old data, but\r
+ * we don't care what's in the block.\r
+ */\r
+ merge_freemem(ms);\r
+ if ((size_t)need > PY_SSIZE_T_MAX / sizeof(PyObject*)) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ ms->a = (PyObject **)PyMem_Malloc(need * sizeof(PyObject*));\r
+ if (ms->a) {\r
+ ms->alloced = need;\r
+ return 0;\r
+ }\r
+ PyErr_NoMemory();\r
+ merge_freemem(ms); /* reset to sane state */\r
+ return -1;\r
+}\r
+#define MERGE_GETMEM(MS, NEED) ((NEED) <= (MS)->alloced ? 0 : \\r
+ merge_getmem(MS, NEED))\r
+\r
+/* Merge the na elements starting at pa with the nb elements starting at pb\r
+ * in a stable way, in-place. na and nb must be > 0, and pa + na == pb.\r
+ * Must also have that *pb < *pa, that pa[na-1] belongs at the end of the\r
+ * merge, and should have na <= nb. See listsort.txt for more info.\r
+ * Return 0 if successful, -1 if error.\r
+ */\r
+static Py_ssize_t\r
+merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na,\r
+ PyObject **pb, Py_ssize_t nb)\r
+{\r
+ Py_ssize_t k;\r
+ PyObject *compare;\r
+ PyObject **dest;\r
+ int result = -1; /* guilty until proved innocent */\r
+ Py_ssize_t min_gallop;\r
+\r
+ assert(ms && pa && pb && na > 0 && nb > 0 && pa + na == pb);\r
+ if (MERGE_GETMEM(ms, na) < 0)\r
+ return -1;\r
+ memcpy(ms->a, pa, na * sizeof(PyObject*));\r
+ dest = pa;\r
+ pa = ms->a;\r
+\r
+ *dest++ = *pb++;\r
+ --nb;\r
+ if (nb == 0)\r
+ goto Succeed;\r
+ if (na == 1)\r
+ goto CopyB;\r
+\r
+ min_gallop = ms->min_gallop;\r
+ compare = ms->compare;\r
+ for (;;) {\r
+ Py_ssize_t acount = 0; /* # of times A won in a row */\r
+ Py_ssize_t bcount = 0; /* # of times B won in a row */\r
+\r
+ /* Do the straightforward thing until (if ever) one run\r
+ * appears to win consistently.\r
+ */\r
+ for (;;) {\r
+ assert(na > 1 && nb > 0);\r
+ k = ISLT(*pb, *pa, compare);\r
+ if (k) {\r
+ if (k < 0)\r
+ goto Fail;\r
+ *dest++ = *pb++;\r
+ ++bcount;\r
+ acount = 0;\r
+ --nb;\r
+ if (nb == 0)\r
+ goto Succeed;\r
+ if (bcount >= min_gallop)\r
+ break;\r
+ }\r
+ else {\r
+ *dest++ = *pa++;\r
+ ++acount;\r
+ bcount = 0;\r
+ --na;\r
+ if (na == 1)\r
+ goto CopyB;\r
+ if (acount >= min_gallop)\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* One run is winning so consistently that galloping may\r
+ * be a huge win. So try that, and continue galloping until\r
+ * (if ever) neither run appears to be winning consistently\r
+ * anymore.\r
+ */\r
+ ++min_gallop;\r
+ do {\r
+ assert(na > 1 && nb > 0);\r
+ min_gallop -= min_gallop > 1;\r
+ ms->min_gallop = min_gallop;\r
+ k = gallop_right(*pb, pa, na, 0, compare);\r
+ acount = k;\r
+ if (k) {\r
+ if (k < 0)\r
+ goto Fail;\r
+ memcpy(dest, pa, k * sizeof(PyObject *));\r
+ dest += k;\r
+ pa += k;\r
+ na -= k;\r
+ if (na == 1)\r
+ goto CopyB;\r
+ /* na==0 is impossible now if the comparison\r
+ * function is consistent, but we can't assume\r
+ * that it is.\r
+ */\r
+ if (na == 0)\r
+ goto Succeed;\r
+ }\r
+ *dest++ = *pb++;\r
+ --nb;\r
+ if (nb == 0)\r
+ goto Succeed;\r
+\r
+ k = gallop_left(*pa, pb, nb, 0, compare);\r
+ bcount = k;\r
+ if (k) {\r
+ if (k < 0)\r
+ goto Fail;\r
+ memmove(dest, pb, k * sizeof(PyObject *));\r
+ dest += k;\r
+ pb += k;\r
+ nb -= k;\r
+ if (nb == 0)\r
+ goto Succeed;\r
+ }\r
+ *dest++ = *pa++;\r
+ --na;\r
+ if (na == 1)\r
+ goto CopyB;\r
+ } while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);\r
+ ++min_gallop; /* penalize it for leaving galloping mode */\r
+ ms->min_gallop = min_gallop;\r
+ }\r
+Succeed:\r
+ result = 0;\r
+Fail:\r
+ if (na)\r
+ memcpy(dest, pa, na * sizeof(PyObject*));\r
+ return result;\r
+CopyB:\r
+ assert(na == 1 && nb > 0);\r
+ /* The last element of pa belongs at the end of the merge. */\r
+ memmove(dest, pb, nb * sizeof(PyObject *));\r
+ dest[nb] = *pa;\r
+ return 0;\r
+}\r
+\r
+/* Merge the na elements starting at pa with the nb elements starting at pb\r
+ * in a stable way, in-place. na and nb must be > 0, and pa + na == pb.\r
+ * Must also have that *pb < *pa, that pa[na-1] belongs at the end of the\r
+ * merge, and should have na >= nb. See listsort.txt for more info.\r
+ * Return 0 if successful, -1 if error.\r
+ */\r
+static Py_ssize_t\r
+merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t nb)\r
+{\r
+ Py_ssize_t k;\r
+ PyObject *compare;\r
+ PyObject **dest;\r
+ int result = -1; /* guilty until proved innocent */\r
+ PyObject **basea;\r
+ PyObject **baseb;\r
+ Py_ssize_t min_gallop;\r
+\r
+ assert(ms && pa && pb && na > 0 && nb > 0 && pa + na == pb);\r
+ if (MERGE_GETMEM(ms, nb) < 0)\r
+ return -1;\r
+ dest = pb + nb - 1;\r
+ memcpy(ms->a, pb, nb * sizeof(PyObject*));\r
+ basea = pa;\r
+ baseb = ms->a;\r
+ pb = ms->a + nb - 1;\r
+ pa += na - 1;\r
+\r
+ *dest-- = *pa--;\r
+ --na;\r
+ if (na == 0)\r
+ goto Succeed;\r
+ if (nb == 1)\r
+ goto CopyA;\r
+\r
+ min_gallop = ms->min_gallop;\r
+ compare = ms->compare;\r
+ for (;;) {\r
+ Py_ssize_t acount = 0; /* # of times A won in a row */\r
+ Py_ssize_t bcount = 0; /* # of times B won in a row */\r
+\r
+ /* Do the straightforward thing until (if ever) one run\r
+ * appears to win consistently.\r
+ */\r
+ for (;;) {\r
+ assert(na > 0 && nb > 1);\r
+ k = ISLT(*pb, *pa, compare);\r
+ if (k) {\r
+ if (k < 0)\r
+ goto Fail;\r
+ *dest-- = *pa--;\r
+ ++acount;\r
+ bcount = 0;\r
+ --na;\r
+ if (na == 0)\r
+ goto Succeed;\r
+ if (acount >= min_gallop)\r
+ break;\r
+ }\r
+ else {\r
+ *dest-- = *pb--;\r
+ ++bcount;\r
+ acount = 0;\r
+ --nb;\r
+ if (nb == 1)\r
+ goto CopyA;\r
+ if (bcount >= min_gallop)\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* One run is winning so consistently that galloping may\r
+ * be a huge win. So try that, and continue galloping until\r
+ * (if ever) neither run appears to be winning consistently\r
+ * anymore.\r
+ */\r
+ ++min_gallop;\r
+ do {\r
+ assert(na > 0 && nb > 1);\r
+ min_gallop -= min_gallop > 1;\r
+ ms->min_gallop = min_gallop;\r
+ k = gallop_right(*pb, basea, na, na-1, compare);\r
+ if (k < 0)\r
+ goto Fail;\r
+ k = na - k;\r
+ acount = k;\r
+ if (k) {\r
+ dest -= k;\r
+ pa -= k;\r
+ memmove(dest+1, pa+1, k * sizeof(PyObject *));\r
+ na -= k;\r
+ if (na == 0)\r
+ goto Succeed;\r
+ }\r
+ *dest-- = *pb--;\r
+ --nb;\r
+ if (nb == 1)\r
+ goto CopyA;\r
+\r
+ k = gallop_left(*pa, baseb, nb, nb-1, compare);\r
+ if (k < 0)\r
+ goto Fail;\r
+ k = nb - k;\r
+ bcount = k;\r
+ if (k) {\r
+ dest -= k;\r
+ pb -= k;\r
+ memcpy(dest+1, pb+1, k * sizeof(PyObject *));\r
+ nb -= k;\r
+ if (nb == 1)\r
+ goto CopyA;\r
+ /* nb==0 is impossible now if the comparison\r
+ * function is consistent, but we can't assume\r
+ * that it is.\r
+ */\r
+ if (nb == 0)\r
+ goto Succeed;\r
+ }\r
+ *dest-- = *pa--;\r
+ --na;\r
+ if (na == 0)\r
+ goto Succeed;\r
+ } while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);\r
+ ++min_gallop; /* penalize it for leaving galloping mode */\r
+ ms->min_gallop = min_gallop;\r
+ }\r
+Succeed:\r
+ result = 0;\r
+Fail:\r
+ if (nb)\r
+ memcpy(dest-(nb-1), baseb, nb * sizeof(PyObject*));\r
+ return result;\r
+CopyA:\r
+ assert(nb == 1 && na > 0);\r
+ /* The first element of pb belongs at the front of the merge. */\r
+ dest -= na;\r
+ pa -= na;\r
+ memmove(dest+1, pa+1, na * sizeof(PyObject *));\r
+ *dest = *pb;\r
+ return 0;\r
+}\r
+\r
+/* Merge the two runs at stack indices i and i+1.\r
+ * Returns 0 on success, -1 on error.\r
+ */\r
+static Py_ssize_t\r
+merge_at(MergeState *ms, Py_ssize_t i)\r
+{\r
+ PyObject **pa, **pb;\r
+ Py_ssize_t na, nb;\r
+ Py_ssize_t k;\r
+ PyObject *compare;\r
+\r
+ assert(ms != NULL);\r
+ assert(ms->n >= 2);\r
+ assert(i >= 0);\r
+ assert(i == ms->n - 2 || i == ms->n - 3);\r
+\r
+ pa = ms->pending[i].base;\r
+ na = ms->pending[i].len;\r
+ pb = ms->pending[i+1].base;\r
+ nb = ms->pending[i+1].len;\r
+ assert(na > 0 && nb > 0);\r
+ assert(pa + na == pb);\r
+\r
+ /* Record the length of the combined runs; if i is the 3rd-last\r
+ * run now, also slide over the last run (which isn't involved\r
+ * in this merge). The current run i+1 goes away in any case.\r
+ */\r
+ ms->pending[i].len = na + nb;\r
+ if (i == ms->n - 3)\r
+ ms->pending[i+1] = ms->pending[i+2];\r
+ --ms->n;\r
+\r
+ /* Where does b start in a? Elements in a before that can be\r
+ * ignored (already in place).\r
+ */\r
+ compare = ms->compare;\r
+ k = gallop_right(*pb, pa, na, 0, compare);\r
+ if (k < 0)\r
+ return -1;\r
+ pa += k;\r
+ na -= k;\r
+ if (na == 0)\r
+ return 0;\r
+\r
+ /* Where does a end in b? Elements in b after that can be\r
+ * ignored (already in place).\r
+ */\r
+ nb = gallop_left(pa[na-1], pb, nb, nb-1, compare);\r
+ if (nb <= 0)\r
+ return nb;\r
+\r
+ /* Merge what remains of the runs, using a temp array with\r
+ * min(na, nb) elements.\r
+ */\r
+ if (na <= nb)\r
+ return merge_lo(ms, pa, na, pb, nb);\r
+ else\r
+ return merge_hi(ms, pa, na, pb, nb);\r
+}\r
+\r
+/* Examine the stack of runs waiting to be merged, merging adjacent runs\r
+ * until the stack invariants are re-established:\r
+ *\r
+ * 1. len[-3] > len[-2] + len[-1]\r
+ * 2. len[-2] > len[-1]\r
+ *\r
+ * See listsort.txt for more info.\r
+ *\r
+ * Returns 0 on success, -1 on error.\r
+ */\r
+static int\r
+merge_collapse(MergeState *ms)\r
+{\r
+ struct s_slice *p = ms->pending;\r
+\r
+ assert(ms);\r
+ while (ms->n > 1) {\r
+ Py_ssize_t n = ms->n - 2;\r
+ if ((n > 0 && p[n-1].len <= p[n].len + p[n+1].len) ||\r
+ (n > 1 && p[n-2].len <= p[n-1].len + p[n].len)) {\r
+ if (p[n-1].len < p[n+1].len)\r
+ --n;\r
+ if (merge_at(ms, n) < 0)\r
+ return -1;\r
+ }\r
+ else if (p[n].len <= p[n+1].len) {\r
+ if (merge_at(ms, n) < 0)\r
+ return -1;\r
+ }\r
+ else\r
+ break;\r
+ }\r
+ return 0;\r
+}\r
+\r
+/* Regardless of invariants, merge all runs on the stack until only one\r
+ * remains. This is used at the end of the mergesort.\r
+ *\r
+ * Returns 0 on success, -1 on error.\r
+ */\r
+static int\r
+merge_force_collapse(MergeState *ms)\r
+{\r
+ struct s_slice *p = ms->pending;\r
+\r
+ assert(ms);\r
+ while (ms->n > 1) {\r
+ Py_ssize_t n = ms->n - 2;\r
+ if (n > 0 && p[n-1].len < p[n+1].len)\r
+ --n;\r
+ if (merge_at(ms, n) < 0)\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+/* Compute a good value for the minimum run length; natural runs shorter\r
+ * than this are boosted artificially via binary insertion.\r
+ *\r
+ * If n < 64, return n (it's too small to bother with fancy stuff).\r
+ * Else if n is an exact power of 2, return 32.\r
+ * Else return an int k, 32 <= k <= 64, such that n/k is close to, but\r
+ * strictly less than, an exact power of 2.\r
+ *\r
+ * See listsort.txt for more info.\r
+ */\r
+static Py_ssize_t\r
+merge_compute_minrun(Py_ssize_t n)\r
+{\r
+ Py_ssize_t r = 0; /* becomes 1 if any 1 bits are shifted off */\r
+\r
+ assert(n >= 0);\r
+ while (n >= 64) {\r
+ r |= n & 1;\r
+ n >>= 1;\r
+ }\r
+ return n + r;\r
+}\r
+\r
+/* Special wrapper to support stable sorting using the decorate-sort-undecorate\r
+ pattern. Holds a key which is used for comparisons and the original record\r
+ which is returned during the undecorate phase. By exposing only the key\r
+ during comparisons, the underlying sort stability characteristics are left\r
+ unchanged. Also, if a custom comparison function is used, it will only see\r
+ the key instead of a full record. */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyObject *key;\r
+ PyObject *value;\r
+} sortwrapperobject;\r
+\r
+PyDoc_STRVAR(sortwrapper_doc, "Object wrapper with a custom sort key.");\r
+static PyObject *\r
+sortwrapper_richcompare(sortwrapperobject *, sortwrapperobject *, int);\r
+static void\r
+sortwrapper_dealloc(sortwrapperobject *);\r
+\r
+static PyTypeObject sortwrapper_type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "sortwrapper", /* tp_name */\r
+ sizeof(sortwrapperobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)sortwrapper_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT |\r
+ Py_TPFLAGS_HAVE_RICHCOMPARE, /* tp_flags */\r
+ sortwrapper_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ (richcmpfunc)sortwrapper_richcompare, /* tp_richcompare */\r
+};\r
+\r
+\r
+static PyObject *\r
+sortwrapper_richcompare(sortwrapperobject *a, sortwrapperobject *b, int op)\r
+{\r
+ if (!PyObject_TypeCheck(b, &sortwrapper_type)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected a sortwrapperobject");\r
+ return NULL;\r
+ }\r
+ return PyObject_RichCompare(a->key, b->key, op);\r
+}\r
+\r
+static void\r
+sortwrapper_dealloc(sortwrapperobject *so)\r
+{\r
+ Py_XDECREF(so->key);\r
+ Py_XDECREF(so->value);\r
+ PyObject_Del(so);\r
+}\r
+\r
+/* Returns a new reference to a sortwrapper.\r
+ Consumes the references to the two underlying objects. */\r
+\r
+static PyObject *\r
+build_sortwrapper(PyObject *key, PyObject *value)\r
+{\r
+ sortwrapperobject *so;\r
+\r
+ so = PyObject_New(sortwrapperobject, &sortwrapper_type);\r
+ if (so == NULL)\r
+ return NULL;\r
+ so->key = key;\r
+ so->value = value;\r
+ return (PyObject *)so;\r
+}\r
+\r
+/* Returns a new reference to the value underlying the wrapper. */\r
+static PyObject *\r
+sortwrapper_getvalue(PyObject *so)\r
+{\r
+ PyObject *value;\r
+\r
+ if (!PyObject_TypeCheck(so, &sortwrapper_type)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected a sortwrapperobject");\r
+ return NULL;\r
+ }\r
+ value = ((sortwrapperobject *)so)->value;\r
+ Py_INCREF(value);\r
+ return value;\r
+}\r
+\r
+/* Wrapper for user specified cmp functions in combination with a\r
+ specified key function. Makes sure the cmp function is presented\r
+ with the actual key instead of the sortwrapper */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyObject *func;\r
+} cmpwrapperobject;\r
+\r
+static void\r
+cmpwrapper_dealloc(cmpwrapperobject *co)\r
+{\r
+ Py_XDECREF(co->func);\r
+ PyObject_Del(co);\r
+}\r
+\r
+static PyObject *\r
+cmpwrapper_call(cmpwrapperobject *co, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *x, *y, *xx, *yy;\r
+\r
+ if (!PyArg_UnpackTuple(args, "", 2, 2, &x, &y))\r
+ return NULL;\r
+ if (!PyObject_TypeCheck(x, &sortwrapper_type) ||\r
+ !PyObject_TypeCheck(y, &sortwrapper_type)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected a sortwrapperobject");\r
+ return NULL;\r
+ }\r
+ xx = ((sortwrapperobject *)x)->key;\r
+ yy = ((sortwrapperobject *)y)->key;\r
+ return PyObject_CallFunctionObjArgs(co->func, xx, yy, NULL);\r
+}\r
+\r
+PyDoc_STRVAR(cmpwrapper_doc, "cmp() wrapper for sort with custom keys.");\r
+\r
+static PyTypeObject cmpwrapper_type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "cmpwrapper", /* tp_name */\r
+ sizeof(cmpwrapperobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)cmpwrapper_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ (ternaryfunc)cmpwrapper_call, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT, /* tp_flags */\r
+ cmpwrapper_doc, /* tp_doc */\r
+};\r
+\r
+static PyObject *\r
+build_cmpwrapper(PyObject *cmpfunc)\r
+{\r
+ cmpwrapperobject *co;\r
+\r
+ co = PyObject_New(cmpwrapperobject, &cmpwrapper_type);\r
+ if (co == NULL)\r
+ return NULL;\r
+ Py_INCREF(cmpfunc);\r
+ co->func = cmpfunc;\r
+ return (PyObject *)co;\r
+}\r
+\r
+/* An adaptive, stable, natural mergesort. See listsort.txt.\r
+ * Returns Py_None on success, NULL on error. Even in case of error, the\r
+ * list will be some permutation of its input state (nothing is lost or\r
+ * duplicated).\r
+ */\r
+static PyObject *\r
+listsort(PyListObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ MergeState ms;\r
+ PyObject **lo, **hi;\r
+ Py_ssize_t nremaining;\r
+ Py_ssize_t minrun;\r
+ Py_ssize_t saved_ob_size, saved_allocated;\r
+ PyObject **saved_ob_item;\r
+ PyObject **final_ob_item;\r
+ PyObject *compare = NULL;\r
+ PyObject *result = NULL; /* guilty until proved innocent */\r
+ int reverse = 0;\r
+ PyObject *keyfunc = NULL;\r
+ Py_ssize_t i;\r
+ PyObject *key, *value, *kvpair;\r
+ static char *kwlist[] = {"cmp", "key", "reverse", 0};\r
+\r
+ assert(self != NULL);\r
+ assert (PyList_Check(self));\r
+ if (args != NULL) {\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:sort",\r
+ kwlist, &compare, &keyfunc, &reverse))\r
+ return NULL;\r
+ }\r
+ if (compare == Py_None)\r
+ compare = NULL;\r
+ if (compare != NULL &&\r
+ PyErr_WarnPy3k("the cmp argument is not supported in 3.x", 1) < 0)\r
+ return NULL;\r
+ if (keyfunc == Py_None)\r
+ keyfunc = NULL;\r
+ if (compare != NULL && keyfunc != NULL) {\r
+ compare = build_cmpwrapper(compare);\r
+ if (compare == NULL)\r
+ return NULL;\r
+ } else\r
+ Py_XINCREF(compare);\r
+\r
+ /* The list is temporarily made empty, so that mutations performed\r
+ * by comparison functions can't affect the slice of memory we're\r
+ * sorting (allowing mutations during sorting is a core-dump\r
+ * factory, since ob_item may change).\r
+ */\r
+ saved_ob_size = Py_SIZE(self);\r
+ saved_ob_item = self->ob_item;\r
+ saved_allocated = self->allocated;\r
+ Py_SIZE(self) = 0;\r
+ self->ob_item = NULL;\r
+ self->allocated = -1; /* any operation will reset it to >= 0 */\r
+\r
+ if (keyfunc != NULL) {\r
+ for (i=0 ; i < saved_ob_size ; i++) {\r
+ value = saved_ob_item[i];\r
+ key = PyObject_CallFunctionObjArgs(keyfunc, value,\r
+ NULL);\r
+ if (key == NULL) {\r
+ for (i=i-1 ; i>=0 ; i--) {\r
+ kvpair = saved_ob_item[i];\r
+ value = sortwrapper_getvalue(kvpair);\r
+ saved_ob_item[i] = value;\r
+ Py_DECREF(kvpair);\r
+ }\r
+ goto dsu_fail;\r
+ }\r
+ kvpair = build_sortwrapper(key, value);\r
+ if (kvpair == NULL)\r
+ goto dsu_fail;\r
+ saved_ob_item[i] = kvpair;\r
+ }\r
+ }\r
+\r
+ /* Reverse sort stability achieved by initially reversing the list,\r
+ applying a stable forward sort, then reversing the final result. */\r
+ if (reverse && saved_ob_size > 1)\r
+ reverse_slice(saved_ob_item, saved_ob_item + saved_ob_size);\r
+\r
+ merge_init(&ms, compare);\r
+\r
+ nremaining = saved_ob_size;\r
+ if (nremaining < 2)\r
+ goto succeed;\r
+\r
+ /* March over the array once, left to right, finding natural runs,\r
+ * and extending short natural runs to minrun elements.\r
+ */\r
+ lo = saved_ob_item;\r
+ hi = lo + nremaining;\r
+ minrun = merge_compute_minrun(nremaining);\r
+ do {\r
+ int descending;\r
+ Py_ssize_t n;\r
+\r
+ /* Identify next run. */\r
+ n = count_run(lo, hi, compare, &descending);\r
+ if (n < 0)\r
+ goto fail;\r
+ if (descending)\r
+ reverse_slice(lo, lo + n);\r
+ /* If short, extend to min(minrun, nremaining). */\r
+ if (n < minrun) {\r
+ const Py_ssize_t force = nremaining <= minrun ?\r
+ nremaining : minrun;\r
+ if (binarysort(lo, lo + force, lo + n, compare) < 0)\r
+ goto fail;\r
+ n = force;\r
+ }\r
+ /* Push run onto pending-runs stack, and maybe merge. */\r
+ assert(ms.n < MAX_MERGE_PENDING);\r
+ ms.pending[ms.n].base = lo;\r
+ ms.pending[ms.n].len = n;\r
+ ++ms.n;\r
+ if (merge_collapse(&ms) < 0)\r
+ goto fail;\r
+ /* Advance to find next run. */\r
+ lo += n;\r
+ nremaining -= n;\r
+ } while (nremaining);\r
+ assert(lo == hi);\r
+\r
+ if (merge_force_collapse(&ms) < 0)\r
+ goto fail;\r
+ assert(ms.n == 1);\r
+ assert(ms.pending[0].base == saved_ob_item);\r
+ assert(ms.pending[0].len == saved_ob_size);\r
+\r
+succeed:\r
+ result = Py_None;\r
+fail:\r
+ if (keyfunc != NULL) {\r
+ for (i=0 ; i < saved_ob_size ; i++) {\r
+ kvpair = saved_ob_item[i];\r
+ value = sortwrapper_getvalue(kvpair);\r
+ saved_ob_item[i] = value;\r
+ Py_DECREF(kvpair);\r
+ }\r
+ }\r
+\r
+ if (self->allocated != -1 && result != NULL) {\r
+ /* The user mucked with the list during the sort,\r
+ * and we don't already have another error to report.\r
+ */\r
+ PyErr_SetString(PyExc_ValueError, "list modified during sort");\r
+ result = NULL;\r
+ }\r
+\r
+ if (reverse && saved_ob_size > 1)\r
+ reverse_slice(saved_ob_item, saved_ob_item + saved_ob_size);\r
+\r
+ merge_freemem(&ms);\r
+\r
+dsu_fail:\r
+ final_ob_item = self->ob_item;\r
+ i = Py_SIZE(self);\r
+ Py_SIZE(self) = saved_ob_size;\r
+ self->ob_item = saved_ob_item;\r
+ self->allocated = saved_allocated;\r
+ if (final_ob_item != NULL) {\r
+ /* we cannot use list_clear() for this because it does not\r
+ guarantee that the list is really empty when it returns */\r
+ while (--i >= 0) {\r
+ Py_XDECREF(final_ob_item[i]);\r
+ }\r
+ PyMem_FREE(final_ob_item);\r
+ }\r
+ Py_XDECREF(compare);\r
+ Py_XINCREF(result);\r
+ return result;\r
+}\r
+#undef IFLT\r
+#undef ISLT\r
+\r
+int\r
+PyList_Sort(PyObject *v)\r
+{\r
+ if (v == NULL || !PyList_Check(v)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ v = listsort((PyListObject *)v, (PyObject *)NULL, (PyObject *)NULL);\r
+ if (v == NULL)\r
+ return -1;\r
+ Py_DECREF(v);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+listreverse(PyListObject *self)\r
+{\r
+ if (Py_SIZE(self) > 1)\r
+ reverse_slice(self->ob_item, self->ob_item + Py_SIZE(self));\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+int\r
+PyList_Reverse(PyObject *v)\r
+{\r
+ PyListObject *self = (PyListObject *)v;\r
+\r
+ if (v == NULL || !PyList_Check(v)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ if (Py_SIZE(self) > 1)\r
+ reverse_slice(self->ob_item, self->ob_item + Py_SIZE(self));\r
+ return 0;\r
+}\r
+\r
+PyObject *\r
+PyList_AsTuple(PyObject *v)\r
+{\r
+ PyObject *w;\r
+ PyObject **p, **q;\r
+ Py_ssize_t n;\r
+ if (v == NULL || !PyList_Check(v)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ n = Py_SIZE(v);\r
+ w = PyTuple_New(n);\r
+ if (w == NULL)\r
+ return NULL;\r
+ p = ((PyTupleObject *)w)->ob_item;\r
+ q = ((PyListObject *)v)->ob_item;\r
+ while (--n >= 0) {\r
+ Py_INCREF(*q);\r
+ *p = *q;\r
+ p++;\r
+ q++;\r
+ }\r
+ return w;\r
+}\r
+\r
+static PyObject *\r
+listindex(PyListObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t i, start=0, stop=Py_SIZE(self);\r
+ PyObject *v, *format_tuple, *err_string;\r
+ static PyObject *err_format = NULL;\r
+\r
+ if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,\r
+ _PyEval_SliceIndex, &start,\r
+ _PyEval_SliceIndex, &stop))\r
+ return NULL;\r
+ if (start < 0) {\r
+ start += Py_SIZE(self);\r
+ if (start < 0)\r
+ start = 0;\r
+ }\r
+ if (stop < 0) {\r
+ stop += Py_SIZE(self);\r
+ if (stop < 0)\r
+ stop = 0;\r
+ }\r
+ for (i = start; i < stop && i < Py_SIZE(self); i++) {\r
+ int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);\r
+ if (cmp > 0)\r
+ return PyInt_FromSsize_t(i);\r
+ else if (cmp < 0)\r
+ return NULL;\r
+ }\r
+ if (err_format == NULL) {\r
+ err_format = PyString_FromString("%r is not in list");\r
+ if (err_format == NULL)\r
+ return NULL;\r
+ }\r
+ format_tuple = PyTuple_Pack(1, v);\r
+ if (format_tuple == NULL)\r
+ return NULL;\r
+ err_string = PyString_Format(err_format, format_tuple);\r
+ Py_DECREF(format_tuple);\r
+ if (err_string == NULL)\r
+ return NULL;\r
+ PyErr_SetObject(PyExc_ValueError, err_string);\r
+ Py_DECREF(err_string);\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+listcount(PyListObject *self, PyObject *v)\r
+{\r
+ Py_ssize_t count = 0;\r
+ Py_ssize_t i;\r
+\r
+ for (i = 0; i < Py_SIZE(self); i++) {\r
+ int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);\r
+ if (cmp > 0)\r
+ count++;\r
+ else if (cmp < 0)\r
+ return NULL;\r
+ }\r
+ return PyInt_FromSsize_t(count);\r
+}\r
+\r
+static PyObject *\r
+listremove(PyListObject *self, PyObject *v)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ for (i = 0; i < Py_SIZE(self); i++) {\r
+ int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);\r
+ if (cmp > 0) {\r
+ if (list_ass_slice(self, i, i+1,\r
+ (PyObject *)NULL) == 0)\r
+ Py_RETURN_NONE;\r
+ return NULL;\r
+ }\r
+ else if (cmp < 0)\r
+ return NULL;\r
+ }\r
+ PyErr_SetString(PyExc_ValueError, "list.remove(x): x not in list");\r
+ return NULL;\r
+}\r
+\r
+static int\r
+list_traverse(PyListObject *o, visitproc visit, void *arg)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ for (i = Py_SIZE(o); --i >= 0; )\r
+ Py_VISIT(o->ob_item[i]);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+list_richcompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyListObject *vl, *wl;\r
+ Py_ssize_t i;\r
+\r
+ if (!PyList_Check(v) || !PyList_Check(w)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+\r
+ vl = (PyListObject *)v;\r
+ wl = (PyListObject *)w;\r
+\r
+ if (Py_SIZE(vl) != Py_SIZE(wl) && (op == Py_EQ || op == Py_NE)) {\r
+ /* Shortcut: if the lengths differ, the lists differ */\r
+ PyObject *res;\r
+ if (op == Py_EQ)\r
+ res = Py_False;\r
+ else\r
+ res = Py_True;\r
+ Py_INCREF(res);\r
+ return res;\r
+ }\r
+\r
+ /* Search for the first index where items are different */\r
+ for (i = 0; i < Py_SIZE(vl) && i < Py_SIZE(wl); i++) {\r
+ int k = PyObject_RichCompareBool(vl->ob_item[i],\r
+ wl->ob_item[i], Py_EQ);\r
+ if (k < 0)\r
+ return NULL;\r
+ if (!k)\r
+ break;\r
+ }\r
+\r
+ if (i >= Py_SIZE(vl) || i >= Py_SIZE(wl)) {\r
+ /* No more items to compare -- compare sizes */\r
+ Py_ssize_t vs = Py_SIZE(vl);\r
+ Py_ssize_t ws = Py_SIZE(wl);\r
+ int cmp;\r
+ PyObject *res;\r
+ switch (op) {\r
+ case Py_LT: cmp = vs < ws; break;\r
+ case Py_LE: cmp = vs <= ws; break;\r
+ case Py_EQ: cmp = vs == ws; break;\r
+ case Py_NE: cmp = vs != ws; break;\r
+ case Py_GT: cmp = vs > ws; break;\r
+ case Py_GE: cmp = vs >= ws; break;\r
+ default: return NULL; /* cannot happen */\r
+ }\r
+ if (cmp)\r
+ res = Py_True;\r
+ else\r
+ res = Py_False;\r
+ Py_INCREF(res);\r
+ return res;\r
+ }\r
+\r
+ /* We have an item that differs -- shortcuts for EQ/NE */\r
+ if (op == Py_EQ) {\r
+ Py_INCREF(Py_False);\r
+ return Py_False;\r
+ }\r
+ if (op == Py_NE) {\r
+ Py_INCREF(Py_True);\r
+ return Py_True;\r
+ }\r
+\r
+ /* Compare the final item again using the proper operator */\r
+ return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);\r
+}\r
+\r
+static int\r
+list_init(PyListObject *self, PyObject *args, PyObject *kw)\r
+{\r
+ PyObject *arg = NULL;\r
+ static char *kwlist[] = {"sequence", 0};\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg))\r
+ return -1;\r
+\r
+ /* Verify list invariants established by PyType_GenericAlloc() */\r
+ assert(0 <= Py_SIZE(self));\r
+ assert(Py_SIZE(self) <= self->allocated || self->allocated == -1);\r
+ assert(self->ob_item != NULL ||\r
+ self->allocated == 0 || self->allocated == -1);\r
+\r
+ /* Empty previous contents */\r
+ if (self->ob_item != NULL) {\r
+ (void)list_clear(self);\r
+ }\r
+ if (arg != NULL) {\r
+ PyObject *rv = listextend(self, arg);\r
+ if (rv == NULL)\r
+ return -1;\r
+ Py_DECREF(rv);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+list_sizeof(PyListObject *self)\r
+{\r
+ Py_ssize_t res;\r
+\r
+ res = sizeof(PyListObject) + self->allocated * sizeof(void*);\r
+ return PyInt_FromSsize_t(res);\r
+}\r
+\r
+static PyObject *list_iter(PyObject *seq);\r
+static PyObject *list_reversed(PyListObject* seq, PyObject* unused);\r
+\r
+PyDoc_STRVAR(getitem_doc,\r
+"x.__getitem__(y) <==> x[y]");\r
+PyDoc_STRVAR(reversed_doc,\r
+"L.__reversed__() -- return a reverse iterator over the list");\r
+PyDoc_STRVAR(sizeof_doc,\r
+"L.__sizeof__() -- size of L in memory, in bytes");\r
+PyDoc_STRVAR(append_doc,\r
+"L.append(object) -- append object to end");\r
+PyDoc_STRVAR(extend_doc,\r
+"L.extend(iterable) -- extend list by appending elements from the iterable");\r
+PyDoc_STRVAR(insert_doc,\r
+"L.insert(index, object) -- insert object before index");\r
+PyDoc_STRVAR(pop_doc,\r
+"L.pop([index]) -> item -- remove and return item at index (default last).\n"\r
+"Raises IndexError if list is empty or index is out of range.");\r
+PyDoc_STRVAR(remove_doc,\r
+"L.remove(value) -- remove first occurrence of value.\n"\r
+"Raises ValueError if the value is not present.");\r
+PyDoc_STRVAR(index_doc,\r
+"L.index(value, [start, [stop]]) -> integer -- return first index of value.\n"\r
+"Raises ValueError if the value is not present.");\r
+PyDoc_STRVAR(count_doc,\r
+"L.count(value) -> integer -- return number of occurrences of value");\r
+PyDoc_STRVAR(reverse_doc,\r
+"L.reverse() -- reverse *IN PLACE*");\r
+PyDoc_STRVAR(sort_doc,\r
+"L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;\n\\r
+cmp(x, y) -> -1, 0, 1");\r
+\r
+static PyObject *list_subscript(PyListObject*, PyObject*);\r
+\r
+static PyMethodDef list_methods[] = {\r
+ {"__getitem__", (PyCFunction)list_subscript, METH_O|METH_COEXIST, getitem_doc},\r
+ {"__reversed__",(PyCFunction)list_reversed, METH_NOARGS, reversed_doc},\r
+ {"__sizeof__", (PyCFunction)list_sizeof, METH_NOARGS, sizeof_doc},\r
+ {"append", (PyCFunction)listappend, METH_O, append_doc},\r
+ {"insert", (PyCFunction)listinsert, METH_VARARGS, insert_doc},\r
+ {"extend", (PyCFunction)listextend, METH_O, extend_doc},\r
+ {"pop", (PyCFunction)listpop, METH_VARARGS, pop_doc},\r
+ {"remove", (PyCFunction)listremove, METH_O, remove_doc},\r
+ {"index", (PyCFunction)listindex, METH_VARARGS, index_doc},\r
+ {"count", (PyCFunction)listcount, METH_O, count_doc},\r
+ {"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc},\r
+ {"sort", (PyCFunction)listsort, METH_VARARGS | METH_KEYWORDS, sort_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PySequenceMethods list_as_sequence = {\r
+ (lenfunc)list_length, /* sq_length */\r
+ (binaryfunc)list_concat, /* sq_concat */\r
+ (ssizeargfunc)list_repeat, /* sq_repeat */\r
+ (ssizeargfunc)list_item, /* sq_item */\r
+ (ssizessizeargfunc)list_slice, /* sq_slice */\r
+ (ssizeobjargproc)list_ass_item, /* sq_ass_item */\r
+ (ssizessizeobjargproc)list_ass_slice, /* sq_ass_slice */\r
+ (objobjproc)list_contains, /* sq_contains */\r
+ (binaryfunc)list_inplace_concat, /* sq_inplace_concat */\r
+ (ssizeargfunc)list_inplace_repeat, /* sq_inplace_repeat */\r
+};\r
+\r
+PyDoc_STRVAR(list_doc,\r
+"list() -> new empty list\n"\r
+"list(iterable) -> new list initialized from iterable's items");\r
+\r
+\r
+static PyObject *\r
+list_subscript(PyListObject* self, PyObject* item)\r
+{\r
+ if (PyIndex_Check(item)) {\r
+ Py_ssize_t i;\r
+ i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ if (i < 0)\r
+ i += PyList_GET_SIZE(self);\r
+ return list_item(self, i);\r
+ }\r
+ else if (PySlice_Check(item)) {\r
+ Py_ssize_t start, stop, step, slicelength, cur, i;\r
+ PyObject* result;\r
+ PyObject* it;\r
+ PyObject **src, **dest;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject*)item, Py_SIZE(self),\r
+ &start, &stop, &step, &slicelength) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ if (slicelength <= 0) {\r
+ return PyList_New(0);\r
+ }\r
+ else if (step == 1) {\r
+ return list_slice(self, start, stop);\r
+ }\r
+ else {\r
+ result = PyList_New(slicelength);\r
+ if (!result) return NULL;\r
+\r
+ src = self->ob_item;\r
+ dest = ((PyListObject *)result)->ob_item;\r
+ for (cur = start, i = 0; i < slicelength;\r
+ cur += step, i++) {\r
+ it = src[cur];\r
+ Py_INCREF(it);\r
+ dest[i] = it;\r
+ }\r
+\r
+ return result;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "list indices must be integers, not %.200s",\r
+ item->ob_type->tp_name);\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static int\r
+list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)\r
+{\r
+ if (PyIndex_Check(item)) {\r
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return -1;\r
+ if (i < 0)\r
+ i += PyList_GET_SIZE(self);\r
+ return list_ass_item(self, i, value);\r
+ }\r
+ else if (PySlice_Check(item)) {\r
+ Py_ssize_t start, stop, step, slicelength;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject*)item, Py_SIZE(self),\r
+ &start, &stop, &step, &slicelength) < 0) {\r
+ return -1;\r
+ }\r
+\r
+ if (step == 1)\r
+ return list_ass_slice(self, start, stop, value);\r
+\r
+ /* Make sure s[5:2] = [..] inserts at the right place:\r
+ before 5, not before 2. */\r
+ if ((step < 0 && start < stop) ||\r
+ (step > 0 && start > stop))\r
+ stop = start;\r
+\r
+ if (value == NULL) {\r
+ /* delete slice */\r
+ PyObject **garbage;\r
+ size_t cur;\r
+ Py_ssize_t i;\r
+\r
+ if (slicelength <= 0)\r
+ return 0;\r
+\r
+ if (step < 0) {\r
+ stop = start + 1;\r
+ start = stop + step*(slicelength - 1) - 1;\r
+ step = -step;\r
+ }\r
+\r
+ assert((size_t)slicelength <=\r
+ PY_SIZE_MAX / sizeof(PyObject*));\r
+\r
+ garbage = (PyObject**)\r
+ PyMem_MALLOC(slicelength*sizeof(PyObject*));\r
+ if (!garbage) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+\r
+ /* drawing pictures might help understand these for\r
+ loops. Basically, we memmove the parts of the\r
+ list that are *not* part of the slice: step-1\r
+ items for each item that is part of the slice,\r
+ and then tail end of the list that was not\r
+ covered by the slice */\r
+ for (cur = start, i = 0;\r
+ cur < (size_t)stop;\r
+ cur += step, i++) {\r
+ Py_ssize_t lim = step - 1;\r
+\r
+ garbage[i] = PyList_GET_ITEM(self, cur);\r
+\r
+ if (cur + step >= (size_t)Py_SIZE(self)) {\r
+ lim = Py_SIZE(self) - cur - 1;\r
+ }\r
+\r
+ memmove(self->ob_item + cur - i,\r
+ self->ob_item + cur + 1,\r
+ lim * sizeof(PyObject *));\r
+ }\r
+ cur = start + slicelength*step;\r
+ if (cur < (size_t)Py_SIZE(self)) {\r
+ memmove(self->ob_item + cur - slicelength,\r
+ self->ob_item + cur,\r
+ (Py_SIZE(self) - cur) *\r
+ sizeof(PyObject *));\r
+ }\r
+\r
+ Py_SIZE(self) -= slicelength;\r
+ list_resize(self, Py_SIZE(self));\r
+\r
+ for (i = 0; i < slicelength; i++) {\r
+ Py_DECREF(garbage[i]);\r
+ }\r
+ PyMem_FREE(garbage);\r
+\r
+ return 0;\r
+ }\r
+ else {\r
+ /* assign slice */\r
+ PyObject *ins, *seq;\r
+ PyObject **garbage, **seqitems, **selfitems;\r
+ Py_ssize_t cur, i;\r
+\r
+ /* protect against a[::-1] = a */\r
+ if (self == (PyListObject*)value) {\r
+ seq = list_slice((PyListObject*)value, 0,\r
+ PyList_GET_SIZE(value));\r
+ }\r
+ else {\r
+ seq = PySequence_Fast(value,\r
+ "must assign iterable "\r
+ "to extended slice");\r
+ }\r
+ if (!seq)\r
+ return -1;\r
+\r
+ if (PySequence_Fast_GET_SIZE(seq) != slicelength) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "attempt to assign sequence of "\r
+ "size %zd to extended slice of "\r
+ "size %zd",\r
+ PySequence_Fast_GET_SIZE(seq),\r
+ slicelength);\r
+ Py_DECREF(seq);\r
+ return -1;\r
+ }\r
+\r
+ if (!slicelength) {\r
+ Py_DECREF(seq);\r
+ return 0;\r
+ }\r
+\r
+ garbage = (PyObject**)\r
+ PyMem_MALLOC(slicelength*sizeof(PyObject*));\r
+ if (!garbage) {\r
+ Py_DECREF(seq);\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+\r
+ selfitems = self->ob_item;\r
+ seqitems = PySequence_Fast_ITEMS(seq);\r
+ for (cur = start, i = 0; i < slicelength;\r
+ cur += step, i++) {\r
+ garbage[i] = selfitems[cur];\r
+ ins = seqitems[i];\r
+ Py_INCREF(ins);\r
+ selfitems[cur] = ins;\r
+ }\r
+\r
+ for (i = 0; i < slicelength; i++) {\r
+ Py_DECREF(garbage[i]);\r
+ }\r
+\r
+ PyMem_FREE(garbage);\r
+ Py_DECREF(seq);\r
+\r
+ return 0;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "list indices must be integers, not %.200s",\r
+ item->ob_type->tp_name);\r
+ return -1;\r
+ }\r
+}\r
+\r
+static PyMappingMethods list_as_mapping = {\r
+ (lenfunc)list_length,\r
+ (binaryfunc)list_subscript,\r
+ (objobjargproc)list_ass_subscript\r
+};\r
+\r
+PyTypeObject PyList_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "list",\r
+ sizeof(PyListObject),\r
+ 0,\r
+ (destructor)list_dealloc, /* tp_dealloc */\r
+ (printfunc)list_print, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)list_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &list_as_sequence, /* tp_as_sequence */\r
+ &list_as_mapping, /* tp_as_mapping */\r
+ (hashfunc)PyObject_HashNotImplemented, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS, /* tp_flags */\r
+ list_doc, /* tp_doc */\r
+ (traverseproc)list_traverse, /* tp_traverse */\r
+ (inquiry)list_clear, /* tp_clear */\r
+ list_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ list_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ list_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ (initproc)list_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ PyType_GenericNew, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
+\r
+\r
+/*********************** List Iterator **************************/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ long it_index;\r
+ PyListObject *it_seq; /* Set to NULL when iterator is exhausted */\r
+} listiterobject;\r
+\r
+static PyObject *list_iter(PyObject *);\r
+static void listiter_dealloc(listiterobject *);\r
+static int listiter_traverse(listiterobject *, visitproc, void *);\r
+static PyObject *listiter_next(listiterobject *);\r
+static PyObject *listiter_len(listiterobject *);\r
+\r
+PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
+\r
+static PyMethodDef listiter_methods[] = {\r
+ {"__length_hint__", (PyCFunction)listiter_len, METH_NOARGS, length_hint_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyListIter_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "listiterator", /* tp_name */\r
+ sizeof(listiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)listiter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)listiter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)listiter_next, /* tp_iternext */\r
+ listiter_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+};\r
+\r
+\r
+static PyObject *\r
+list_iter(PyObject *seq)\r
+{\r
+ listiterobject *it;\r
+\r
+ if (!PyList_Check(seq)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ it = PyObject_GC_New(listiterobject, &PyListIter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+ it->it_index = 0;\r
+ Py_INCREF(seq);\r
+ it->it_seq = (PyListObject *)seq;\r
+ _PyObject_GC_TRACK(it);\r
+ return (PyObject *)it;\r
+}\r
+\r
+static void\r
+listiter_dealloc(listiterobject *it)\r
+{\r
+ _PyObject_GC_UNTRACK(it);\r
+ Py_XDECREF(it->it_seq);\r
+ PyObject_GC_Del(it);\r
+}\r
+\r
+static int\r
+listiter_traverse(listiterobject *it, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(it->it_seq);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+listiter_next(listiterobject *it)\r
+{\r
+ PyListObject *seq;\r
+ PyObject *item;\r
+\r
+ assert(it != NULL);\r
+ seq = it->it_seq;\r
+ if (seq == NULL)\r
+ return NULL;\r
+ assert(PyList_Check(seq));\r
+\r
+ if (it->it_index < PyList_GET_SIZE(seq)) {\r
+ item = PyList_GET_ITEM(seq, it->it_index);\r
+ ++it->it_index;\r
+ Py_INCREF(item);\r
+ return item;\r
+ }\r
+\r
+ Py_DECREF(seq);\r
+ it->it_seq = NULL;\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+listiter_len(listiterobject *it)\r
+{\r
+ Py_ssize_t len;\r
+ if (it->it_seq) {\r
+ len = PyList_GET_SIZE(it->it_seq) - it->it_index;\r
+ if (len >= 0)\r
+ return PyInt_FromSsize_t(len);\r
+ }\r
+ return PyInt_FromLong(0);\r
+}\r
+/*********************** List Reverse Iterator **************************/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ Py_ssize_t it_index;\r
+ PyListObject *it_seq; /* Set to NULL when iterator is exhausted */\r
+} listreviterobject;\r
+\r
+static PyObject *list_reversed(PyListObject *, PyObject *);\r
+static void listreviter_dealloc(listreviterobject *);\r
+static int listreviter_traverse(listreviterobject *, visitproc, void *);\r
+static PyObject *listreviter_next(listreviterobject *);\r
+static PyObject *listreviter_len(listreviterobject *);\r
+\r
+static PyMethodDef listreviter_methods[] = {\r
+ {"__length_hint__", (PyCFunction)listreviter_len, METH_NOARGS, length_hint_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyListRevIter_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "listreverseiterator", /* tp_name */\r
+ sizeof(listreviterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)listreviter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)listreviter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)listreviter_next, /* tp_iternext */\r
+ listreviter_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *\r
+list_reversed(PyListObject *seq, PyObject *unused)\r
+{\r
+ listreviterobject *it;\r
+\r
+ it = PyObject_GC_New(listreviterobject, &PyListRevIter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+ assert(PyList_Check(seq));\r
+ it->it_index = PyList_GET_SIZE(seq) - 1;\r
+ Py_INCREF(seq);\r
+ it->it_seq = seq;\r
+ PyObject_GC_Track(it);\r
+ return (PyObject *)it;\r
+}\r
+\r
+static void\r
+listreviter_dealloc(listreviterobject *it)\r
+{\r
+ PyObject_GC_UnTrack(it);\r
+ Py_XDECREF(it->it_seq);\r
+ PyObject_GC_Del(it);\r
+}\r
+\r
+static int\r
+listreviter_traverse(listreviterobject *it, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(it->it_seq);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+listreviter_next(listreviterobject *it)\r
+{\r
+ PyObject *item;\r
+ Py_ssize_t index = it->it_index;\r
+ PyListObject *seq = it->it_seq;\r
+\r
+ if (index>=0 && index < PyList_GET_SIZE(seq)) {\r
+ item = PyList_GET_ITEM(seq, index);\r
+ it->it_index--;\r
+ Py_INCREF(item);\r
+ return item;\r
+ }\r
+ it->it_index = -1;\r
+ if (seq != NULL) {\r
+ it->it_seq = NULL;\r
+ Py_DECREF(seq);\r
+ }\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+listreviter_len(listreviterobject *it)\r
+{\r
+ Py_ssize_t len = it->it_index + 1;\r
+ if (it->it_seq == NULL || PyList_GET_SIZE(it->it_seq) < len)\r
+ len = 0;\r
+ return PyLong_FromSsize_t(len);\r
+}\r
--- /dev/null
+Intro\r
+-----\r
+This describes an adaptive, stable, natural mergesort, modestly called\r
+timsort (hey, I earned it <wink>). It has supernatural performance on many\r
+kinds of partially ordered arrays (less than lg(N!) comparisons needed, and\r
+as few as N-1), yet as fast as Python's previous highly tuned samplesort\r
+hybrid on random arrays.\r
+\r
+In a nutshell, the main routine marches over the array once, left to right,\r
+alternately identifying the next run, then merging it into the previous\r
+runs "intelligently". Everything else is complication for speed, and some\r
+hard-won measure of memory efficiency.\r
+\r
+\r
+Comparison with Python's Samplesort Hybrid\r
+------------------------------------------\r
++ timsort can require a temp array containing as many as N//2 pointers,\r
+ which means as many as 2*N extra bytes on 32-bit boxes. It can be\r
+ expected to require a temp array this large when sorting random data; on\r
+ data with significant structure, it may get away without using any extra\r
+ heap memory. This appears to be the strongest argument against it, but\r
+ compared to the size of an object, 2 temp bytes worst-case (also expected-\r
+ case for random data) doesn't scare me much.\r
+\r
+ It turns out that Perl is moving to a stable mergesort, and the code for\r
+ that appears always to require a temp array with room for at least N\r
+ pointers. (Note that I wouldn't want to do that even if space weren't an\r
+ issue; I believe its efforts at memory frugality also save timsort\r
+ significant pointer-copying costs, and allow it to have a smaller working\r
+ set.)\r
+\r
++ Across about four hours of generating random arrays, and sorting them\r
+ under both methods, samplesort required about 1.5% more comparisons\r
+ (the program is at the end of this file).\r
+\r
++ In real life, this may be faster or slower on random arrays than\r
+ samplesort was, depending on platform quirks. Since it does fewer\r
+ comparisons on average, it can be expected to do better the more\r
+ expensive a comparison function is. OTOH, it does more data movement\r
+ (pointer copying) than samplesort, and that may negate its small\r
+ comparison advantage (depending on platform quirks) unless comparison\r
+ is very expensive.\r
+\r
++ On arrays with many kinds of pre-existing order, this blows samplesort out\r
+ of the water. It's significantly faster than samplesort even on some\r
+ cases samplesort was special-casing the snot out of. I believe that lists\r
+ very often do have exploitable partial order in real life, and this is the\r
+ strongest argument in favor of timsort (indeed, samplesort's special cases\r
+ for extreme partial order are appreciated by real users, and timsort goes\r
+ much deeper than those, in particular naturally covering every case where\r
+ someone has suggested "and it would be cool if list.sort() had a special\r
+ case for this too ... and for that ...").\r
+\r
++ Here are exact comparison counts across all the tests in sortperf.py,\r
+ when run with arguments "15 20 1".\r
+\r
+ Column Key:\r
+ *sort: random data\r
+ \sort: descending data\r
+ /sort: ascending data\r
+ 3sort: ascending, then 3 random exchanges\r
+ +sort: ascending, then 10 random at the end\r
+ %sort: ascending, then randomly replace 1% of elements w/ random values\r
+ ~sort: many duplicates\r
+ =sort: all equal\r
+ !sort: worst case scenario\r
+\r
+ First the trivial cases, trivial for samplesort because it special-cased\r
+ them, and trivial for timsort because it naturally works on runs. Within\r
+ an "n" block, the first line gives the # of compares done by samplesort,\r
+ the second line by timsort, and the third line is the percentage by\r
+ which the samplesort count exceeds the timsort count:\r
+\r
+ n \sort /sort =sort\r
+------- ------ ------ ------\r
+ 32768 32768 32767 32767 samplesort\r
+ 32767 32767 32767 timsort\r
+ 0.00% 0.00% 0.00% (samplesort - timsort) / timsort\r
+\r
+ 65536 65536 65535 65535\r
+ 65535 65535 65535\r
+ 0.00% 0.00% 0.00%\r
+\r
+ 131072 131072 131071 131071\r
+ 131071 131071 131071\r
+ 0.00% 0.00% 0.00%\r
+\r
+ 262144 262144 262143 262143\r
+ 262143 262143 262143\r
+ 0.00% 0.00% 0.00%\r
+\r
+ 524288 524288 524287 524287\r
+ 524287 524287 524287\r
+ 0.00% 0.00% 0.00%\r
+\r
+1048576 1048576 1048575 1048575\r
+ 1048575 1048575 1048575\r
+ 0.00% 0.00% 0.00%\r
+\r
+ The algorithms are effectively identical in these cases, except that\r
+ timsort does one less compare in \sort.\r
+\r
+ Now for the more interesting cases. Where lg(x) is the logarithm of x to\r
+ the base 2 (e.g., lg(8)=3), lg(n!) is the information-theoretic limit for\r
+ the best any comparison-based sorting algorithm can do on average (across\r
+ all permutations). When a method gets significantly below that, it's\r
+ either astronomically lucky, or is finding exploitable structure in the\r
+ data.\r
+\r
+\r
+ n lg(n!) *sort 3sort +sort %sort ~sort !sort\r
+------- ------- ------ ------- ------- ------ ------- --------\r
+ 32768 444255 453096 453614 32908 452871 130491 469141 old\r
+ 448885 33016 33007 50426 182083 65534 new\r
+ 0.94% 1273.92% -0.30% 798.09% -28.33% 615.87% %ch from new\r
+\r
+ 65536 954037 972699 981940 65686 973104 260029 1004607\r
+ 962991 65821 65808 101667 364341 131070\r
+ 1.01% 1391.83% -0.19% 857.15% -28.63% 666.47%\r
+\r
+ 131072 2039137 2101881 2091491 131232 2092894 554790 2161379\r
+ 2057533 131410 131361 206193 728871 262142\r
+ 2.16% 1491.58% -0.10% 915.02% -23.88% 724.51%\r
+\r
+ 262144 4340409 4464460 4403233 262314 4445884 1107842 4584560\r
+ 4377402 262437 262459 416347 1457945 524286\r
+ 1.99% 1577.82% -0.06% 967.83% -24.01% 774.44%\r
+\r
+ 524288 9205096 9453356 9408463 524468 9441930 2218577 9692015\r
+ 9278734 524580 524633 837947 2916107 1048574\r
+ 1.88% 1693.52% -0.03% 1026.79% -23.92% 824.30%\r
+\r
+1048576 19458756 19950272 19838588 1048766 19912134 4430649 20434212\r
+ 19606028 1048958 1048941 1694896 5832445 2097150\r
+ 1.76% 1791.27% -0.02% 1074.83% -24.03% 874.38%\r
+\r
+ Discussion of cases:\r
+\r
+ *sort: There's no structure in random data to exploit, so the theoretical\r
+ limit is lg(n!). Both methods get close to that, and timsort is hugging\r
+ it (indeed, in a *marginal* sense, it's a spectacular improvement --\r
+ there's only about 1% left before hitting the wall, and timsort knows\r
+ darned well it's doing compares that won't pay on random data -- but so\r
+ does the samplesort hybrid). For contrast, Hoare's original random-pivot\r
+ quicksort does about 39% more compares than the limit, and the median-of-3\r
+ variant about 19% more.\r
+\r
+ 3sort, %sort, and !sort: No contest; there's structure in this data, but\r
+ not of the specific kinds samplesort special-cases. Note that structure\r
+ in !sort wasn't put there on purpose -- it was crafted as a worst case for\r
+ a previous quicksort implementation. That timsort nails it came as a\r
+ surprise to me (although it's obvious in retrospect).\r
+\r
+ +sort: samplesort special-cases this data, and does a few less compares\r
+ than timsort. However, timsort runs this case significantly faster on all\r
+ boxes we have timings for, because timsort is in the business of merging\r
+ runs efficiently, while samplesort does much more data movement in this\r
+ (for it) special case.\r
+\r
+ ~sort: samplesort's special cases for large masses of equal elements are\r
+ extremely effective on ~sort's specific data pattern, and timsort just\r
+ isn't going to get close to that, despite that it's clearly getting a\r
+ great deal of benefit out of the duplicates (the # of compares is much less\r
+ than lg(n!)). ~sort has a perfectly uniform distribution of just 4\r
+ distinct values, and as the distribution gets more skewed, samplesort's\r
+ equal-element gimmicks become less effective, while timsort's adaptive\r
+ strategies find more to exploit; in a database supplied by Kevin Altis, a\r
+ sort on its highly skewed "on which stock exchange does this company's\r
+ stock trade?" field ran over twice as fast under timsort.\r
+\r
+ However, despite that timsort does many more comparisons on ~sort, and\r
+ that on several platforms ~sort runs highly significantly slower under\r
+ timsort, on other platforms ~sort runs highly significantly faster under\r
+ timsort. No other kind of data has shown this wild x-platform behavior,\r
+ and we don't have an explanation for it. The only thing I can think of\r
+ that could transform what "should be" highly significant slowdowns into\r
+ highly significant speedups on some boxes are catastrophic cache effects\r
+ in samplesort.\r
+\r
+ But timsort "should be" slower than samplesort on ~sort, so it's hard\r
+ to count that it isn't on some boxes as a strike against it <wink>.\r
+\r
++ Here's the highwater mark for the number of heap-based temp slots (4\r
+ bytes each on this box) needed by each test, again with arguments\r
+ "15 20 1":\r
+\r
+ 2**i *sort \sort /sort 3sort +sort %sort ~sort =sort !sort\r
+ 32768 16384 0 0 6256 0 10821 12288 0 16383\r
+ 65536 32766 0 0 21652 0 31276 24576 0 32767\r
+ 131072 65534 0 0 17258 0 58112 49152 0 65535\r
+ 262144 131072 0 0 35660 0 123561 98304 0 131071\r
+ 524288 262142 0 0 31302 0 212057 196608 0 262143\r
+1048576 524286 0 0 312438 0 484942 393216 0 524287\r
+\r
+ Discussion: The tests that end up doing (close to) perfectly balanced\r
+ merges (*sort, !sort) need all N//2 temp slots (or almost all). ~sort\r
+ also ends up doing balanced merges, but systematically benefits a lot from\r
+ the preliminary pre-merge searches described under "Merge Memory" later.\r
+ %sort approaches having a balanced merge at the end because the random\r
+ selection of elements to replace is expected to produce an out-of-order\r
+ element near the midpoint. \sort, /sort, =sort are the trivial one-run\r
+ cases, needing no merging at all. +sort ends up having one very long run\r
+ and one very short, and so gets all the temp space it needs from the small\r
+ temparray member of the MergeState struct (note that the same would be\r
+ true if the new random elements were prefixed to the sorted list instead,\r
+ but not if they appeared "in the middle"). 3sort approaches N//3 temp\r
+ slots twice, but the run lengths that remain after 3 random exchanges\r
+ clearly has very high variance.\r
+\r
+\r
+A detailed description of timsort follows.\r
+\r
+Runs\r
+----\r
+count_run() returns the # of elements in the next run. A run is either\r
+"ascending", which means non-decreasing:\r
+\r
+ a0 <= a1 <= a2 <= ...\r
+\r
+or "descending", which means strictly decreasing:\r
+\r
+ a0 > a1 > a2 > ...\r
+\r
+Note that a run is always at least 2 long, unless we start at the array's\r
+last element.\r
+\r
+The definition of descending is strict, because the main routine reverses\r
+a descending run in-place, transforming a descending run into an ascending\r
+run. Reversal is done via the obvious fast "swap elements starting at each\r
+end, and converge at the middle" method, and that can violate stability if\r
+the slice contains any equal elements. Using a strict definition of\r
+descending ensures that a descending run contains distinct elements.\r
+\r
+If an array is random, it's very unlikely we'll see long runs. If a natural\r
+run contains less than minrun elements (see next section), the main loop\r
+artificially boosts it to minrun elements, via a stable binary insertion sort\r
+applied to the right number of array elements following the short natural\r
+run. In a random array, *all* runs are likely to be minrun long as a\r
+result. This has two primary good effects:\r
+\r
+1. Random data strongly tends then toward perfectly balanced (both runs have\r
+ the same length) merges, which is the most efficient way to proceed when\r
+ data is random.\r
+\r
+2. Because runs are never very short, the rest of the code doesn't make\r
+ heroic efforts to shave a few cycles off per-merge overheads. For\r
+ example, reasonable use of function calls is made, rather than trying to\r
+ inline everything. Since there are no more than N/minrun runs to begin\r
+ with, a few "extra" function calls per merge is barely measurable.\r
+\r
+\r
+Computing minrun\r
+----------------\r
+If N < 64, minrun is N. IOW, binary insertion sort is used for the whole\r
+array then; it's hard to beat that given the overheads of trying something\r
+fancier (see note BINSORT).\r
+\r
+When N is a power of 2, testing on random data showed that minrun values of\r
+16, 32, 64 and 128 worked about equally well. At 256 the data-movement cost\r
+in binary insertion sort clearly hurt, and at 8 the increase in the number\r
+of function calls clearly hurt. Picking *some* power of 2 is important\r
+here, so that the merges end up perfectly balanced (see next section). We\r
+pick 32 as a good value in the sweet range; picking a value at the low end\r
+allows the adaptive gimmicks more opportunity to exploit shorter natural\r
+runs.\r
+\r
+Because sortperf.py only tries powers of 2, it took a long time to notice\r
+that 32 isn't a good choice for the general case! Consider N=2112:\r
+\r
+>>> divmod(2112, 32)\r
+(66, 0)\r
+>>>\r
+\r
+If the data is randomly ordered, we're very likely to end up with 66 runs\r
+each of length 32. The first 64 of these trigger a sequence of perfectly\r
+balanced merges (see next section), leaving runs of lengths 2048 and 64 to\r
+merge at the end. The adaptive gimmicks can do that with fewer than 2048+64\r
+compares, but it's still more compares than necessary, and-- mergesort's\r
+bugaboo relative to samplesort --a lot more data movement (O(N) copies just\r
+to get 64 elements into place).\r
+\r
+If we take minrun=33 in this case, then we're very likely to end up with 64\r
+runs each of length 33, and then all merges are perfectly balanced. Better!\r
+\r
+What we want to avoid is picking minrun such that in\r
+\r
+ q, r = divmod(N, minrun)\r
+\r
+q is a power of 2 and r>0 (then the last merge only gets r elements into\r
+place, and r < minrun is small compared to N), or q a little larger than a\r
+power of 2 regardless of r (then we've got a case similar to "2112", again\r
+leaving too little work for the last merge to do).\r
+\r
+Instead we pick a minrun in range(32, 65) such that N/minrun is exactly a\r
+power of 2, or if that isn't possible, is close to, but strictly less than,\r
+a power of 2. This is easier to do than it may sound: take the first 6\r
+bits of N, and add 1 if any of the remaining bits are set. In fact, that\r
+rule covers every case in this section, including small N and exact powers\r
+of 2; merge_compute_minrun() is a deceptively simple function.\r
+\r
+\r
+The Merge Pattern\r
+-----------------\r
+In order to exploit regularities in the data, we're merging on natural\r
+run lengths, and they can become wildly unbalanced. That's a Good Thing\r
+for this sort! It means we have to find a way to manage an assortment of\r
+potentially very different run lengths, though.\r
+\r
+Stability constrains permissible merging patterns. For example, if we have\r
+3 consecutive runs of lengths\r
+\r
+ A:10000 B:20000 C:10000\r
+\r
+we dare not merge A with C first, because if A, B and C happen to contain\r
+a common element, it would get out of order wrt its occurrence(s) in B. The\r
+merging must be done as (A+B)+C or A+(B+C) instead.\r
+\r
+So merging is always done on two consecutive runs at a time, and in-place,\r
+although this may require some temp memory (more on that later).\r
+\r
+When a run is identified, its base address and length are pushed on a stack\r
+in the MergeState struct. merge_collapse() is then called to see whether it\r
+should merge it with preceding run(s). We would like to delay merging as\r
+long as possible in order to exploit patterns that may come up later, but we\r
+like even more to do merging as soon as possible to exploit that the run just\r
+found is still high in the memory hierarchy. We also can't delay merging\r
+"too long" because it consumes memory to remember the runs that are still\r
+unmerged, and the stack has a fixed size.\r
+\r
+What turned out to be a good compromise maintains two invariants on the\r
+stack entries, where A, B and C are the lengths of the three righmost not-yet\r
+merged slices:\r
+\r
+1. A > B+C\r
+2. B > C\r
+\r
+Note that, by induction, #2 implies the lengths of pending runs form a\r
+decreasing sequence. #1 implies that, reading the lengths right to left,\r
+the pending-run lengths grow at least as fast as the Fibonacci numbers.\r
+Therefore the stack can never grow larger than about log_base_phi(N) entries,\r
+where phi = (1+sqrt(5))/2 ~= 1.618. Thus a small # of stack slots suffice\r
+for very large arrays.\r
+\r
+If A <= B+C, the smaller of A and C is merged with B (ties favor C, for the\r
+freshness-in-cache reason), and the new run replaces the A,B or B,C entries;\r
+e.g., if the last 3 entries are\r
+\r
+ A:30 B:20 C:10\r
+\r
+then B is merged with C, leaving\r
+\r
+ A:30 BC:30\r
+\r
+on the stack. Or if they were\r
+\r
+ A:500 B:400: C:1000\r
+\r
+then A is merged with B, leaving\r
+\r
+ AB:900 C:1000\r
+\r
+on the stack.\r
+\r
+In both examples, the stack configuration after the merge still violates\r
+invariant #2, and merge_collapse() goes on to continue merging runs until\r
+both invariants are satisfied. As an extreme case, suppose we didn't do the\r
+minrun gimmick, and natural runs were of lengths 128, 64, 32, 16, 8, 4, 2,\r
+and 2. Nothing would get merged until the final 2 was seen, and that would\r
+trigger 7 perfectly balanced merges.\r
+\r
+The thrust of these rules when they trigger merging is to balance the run\r
+lengths as closely as possible, while keeping a low bound on the number of\r
+runs we have to remember. This is maximally effective for random data,\r
+where all runs are likely to be of (artificially forced) length minrun, and\r
+then we get a sequence of perfectly balanced merges (with, perhaps, some\r
+oddballs at the end).\r
+\r
+OTOH, one reason this sort is so good for partly ordered data has to do\r
+with wildly unbalanced run lengths.\r
+\r
+\r
+Merge Memory\r
+------------\r
+Merging adjacent runs of lengths A and B in-place, and in linear time, is\r
+difficult. Theoretical constructions are known that can do it, but they're\r
+too difficult and slow for practical use. But if we have temp memory equal\r
+to min(A, B), it's easy.\r
+\r
+If A is smaller (function merge_lo), copy A to a temp array, leave B alone,\r
+and then we can do the obvious merge algorithm left to right, from the temp\r
+area and B, starting the stores into where A used to live. There's always a\r
+free area in the original area comprising a number of elements equal to the\r
+number not yet merged from the temp array (trivially true at the start;\r
+proceed by induction). The only tricky bit is that if a comparison raises an\r
+exception, we have to remember to copy the remaining elements back in from\r
+the temp area, lest the array end up with duplicate entries from B. But\r
+that's exactly the same thing we need to do if we reach the end of B first,\r
+so the exit code is pleasantly common to both the normal and error cases.\r
+\r
+If B is smaller (function merge_hi, which is merge_lo's "mirror image"),\r
+much the same, except that we need to merge right to left, copying B into a\r
+temp array and starting the stores at the right end of where B used to live.\r
+\r
+A refinement: When we're about to merge adjacent runs A and B, we first do\r
+a form of binary search (more on that later) to see where B[0] should end up\r
+in A. Elements in A preceding that point are already in their final\r
+positions, effectively shrinking the size of A. Likewise we also search to\r
+see where A[-1] should end up in B, and elements of B after that point can\r
+also be ignored. This cuts the amount of temp memory needed by the same\r
+amount.\r
+\r
+These preliminary searches may not pay off, and can be expected *not* to\r
+repay their cost if the data is random. But they can win huge in all of\r
+time, copying, and memory savings when they do pay, so this is one of the\r
+"per-merge overheads" mentioned above that we're happy to endure because\r
+there is at most one very short run. It's generally true in this algorithm\r
+that we're willing to gamble a little to win a lot, even though the net\r
+expectation is negative for random data.\r
+\r
+\r
+Merge Algorithms\r
+----------------\r
+merge_lo() and merge_hi() are where the bulk of the time is spent. merge_lo\r
+deals with runs where A <= B, and merge_hi where A > B. They don't know\r
+whether the data is clustered or uniform, but a lovely thing about merging\r
+is that many kinds of clustering "reveal themselves" by how many times in a\r
+row the winning merge element comes from the same run. We'll only discuss\r
+merge_lo here; merge_hi is exactly analogous.\r
+\r
+Merging begins in the usual, obvious way, comparing the first element of A\r
+to the first of B, and moving B[0] to the merge area if it's less than A[0],\r
+else moving A[0] to the merge area. Call that the "one pair at a time"\r
+mode. The only twist here is keeping track of how many times in a row "the\r
+winner" comes from the same run.\r
+\r
+If that count reaches MIN_GALLOP, we switch to "galloping mode". Here\r
+we *search* B for where A[0] belongs, and move over all the B's before\r
+that point in one chunk to the merge area, then move A[0] to the merge\r
+area. Then we search A for where B[0] belongs, and similarly move a\r
+slice of A in one chunk. Then back to searching B for where A[0] belongs,\r
+etc. We stay in galloping mode until both searches find slices to copy\r
+less than MIN_GALLOP elements long, at which point we go back to one-pair-\r
+at-a-time mode.\r
+\r
+A refinement: The MergeState struct contains the value of min_gallop that\r
+controls when we enter galloping mode, initialized to MIN_GALLOP.\r
+merge_lo() and merge_hi() adjust this higher when galloping isn't paying\r
+off, and lower when it is.\r
+\r
+\r
+Galloping\r
+---------\r
+Still without loss of generality, assume A is the shorter run. In galloping\r
+mode, we first look for A[0] in B. We do this via "galloping", comparing\r
+A[0] in turn to B[0], B[1], B[3], B[7], ..., B[2**j - 1], ..., until finding\r
+the k such that B[2**(k-1) - 1] < A[0] <= B[2**k - 1]. This takes at most\r
+roughly lg(B) comparisons, and, unlike a straight binary search, favors\r
+finding the right spot early in B (more on that later).\r
+\r
+After finding such a k, the region of uncertainty is reduced to 2**(k-1) - 1\r
+consecutive elements, and a straight binary search requires exactly k-1\r
+additional comparisons to nail it (see note REGION OF UNCERTAINTY). Then we\r
+copy all the B's up to that point in one chunk, and then copy A[0]. Note\r
+that no matter where A[0] belongs in B, the combination of galloping + binary\r
+search finds it in no more than about 2*lg(B) comparisons.\r
+\r
+If we did a straight binary search, we could find it in no more than\r
+ceiling(lg(B+1)) comparisons -- but straight binary search takes that many\r
+comparisons no matter where A[0] belongs. Straight binary search thus loses\r
+to galloping unless the run is quite long, and we simply can't guess\r
+whether it is in advance.\r
+\r
+If data is random and runs have the same length, A[0] belongs at B[0] half\r
+the time, at B[1] a quarter of the time, and so on: a consecutive winning\r
+sub-run in B of length k occurs with probability 1/2**(k+1). So long\r
+winning sub-runs are extremely unlikely in random data, and guessing that a\r
+winning sub-run is going to be long is a dangerous game.\r
+\r
+OTOH, if data is lopsided or lumpy or contains many duplicates, long\r
+stretches of winning sub-runs are very likely, and cutting the number of\r
+comparisons needed to find one from O(B) to O(log B) is a huge win.\r
+\r
+Galloping compromises by getting out fast if there isn't a long winning\r
+sub-run, yet finding such very efficiently when they exist.\r
+\r
+I first learned about the galloping strategy in a related context; see:\r
+\r
+ "Adaptive Set Intersections, Unions, and Differences" (2000)\r
+ Erik D. Demaine, Alejandro López-Ortiz, J. Ian Munro\r
+\r
+and its followup(s). An earlier paper called the same strategy\r
+"exponential search":\r
+\r
+ "Optimistic Sorting and Information Theoretic Complexity"\r
+ Peter McIlroy\r
+ SODA (Fourth Annual ACM-SIAM Symposium on Discrete Algorithms), pp\r
+ 467-474, Austin, Texas, 25-27 January 1993.\r
+\r
+and it probably dates back to an earlier paper by Bentley and Yao. The\r
+McIlroy paper in particular has good analysis of a mergesort that's\r
+probably strongly related to this one in its galloping strategy.\r
+\r
+\r
+Galloping with a Broken Leg\r
+---------------------------\r
+So why don't we always gallop? Because it can lose, on two counts:\r
+\r
+1. While we're willing to endure small per-merge overheads, per-comparison\r
+ overheads are a different story. Calling Yet Another Function per\r
+ comparison is expensive, and gallop_left() and gallop_right() are\r
+ too long-winded for sane inlining.\r
+\r
+2. Galloping can-- alas --require more comparisons than linear one-at-time\r
+ search, depending on the data.\r
+\r
+#2 requires details. If A[0] belongs before B[0], galloping requires 1\r
+compare to determine that, same as linear search, except it costs more\r
+to call the gallop function. If A[0] belongs right before B[1], galloping\r
+requires 2 compares, again same as linear search. On the third compare,\r
+galloping checks A[0] against B[3], and if it's <=, requires one more\r
+compare to determine whether A[0] belongs at B[2] or B[3]. That's a total\r
+of 4 compares, but if A[0] does belong at B[2], linear search would have\r
+discovered that in only 3 compares, and that's a huge loss! Really. It's\r
+an increase of 33% in the number of compares needed, and comparisons are\r
+expensive in Python.\r
+\r
+index in B where # compares linear # gallop # binary gallop\r
+A[0] belongs search needs compares compares total\r
+---------------- ----------------- -------- -------- ------\r
+ 0 1 1 0 1\r
+\r
+ 1 2 2 0 2\r
+\r
+ 2 3 3 1 4\r
+ 3 4 3 1 4\r
+\r
+ 4 5 4 2 6\r
+ 5 6 4 2 6\r
+ 6 7 4 2 6\r
+ 7 8 4 2 6\r
+\r
+ 8 9 5 3 8\r
+ 9 10 5 3 8\r
+ 10 11 5 3 8\r
+ 11 12 5 3 8\r
+ ...\r
+\r
+In general, if A[0] belongs at B[i], linear search requires i+1 comparisons\r
+to determine that, and galloping a total of 2*floor(lg(i))+2 comparisons.\r
+The advantage of galloping is unbounded as i grows, but it doesn't win at\r
+all until i=6. Before then, it loses twice (at i=2 and i=4), and ties\r
+at the other values. At and after i=6, galloping always wins.\r
+\r
+We can't guess in advance when it's going to win, though, so we do one pair\r
+at a time until the evidence seems strong that galloping may pay. MIN_GALLOP\r
+is 7, and that's pretty strong evidence. However, if the data is random, it\r
+simply will trigger galloping mode purely by luck every now and again, and\r
+it's quite likely to hit one of the losing cases next. On the other hand,\r
+in cases like ~sort, galloping always pays, and MIN_GALLOP is larger than it\r
+"should be" then. So the MergeState struct keeps a min_gallop variable\r
+that merge_lo and merge_hi adjust: the longer we stay in galloping mode,\r
+the smaller min_gallop gets, making it easier to transition back to\r
+galloping mode (if we ever leave it in the current merge, and at the\r
+start of the next merge). But whenever the gallop loop doesn't pay,\r
+min_gallop is increased by one, making it harder to transition back\r
+to galloping mode (and again both within a merge and across merges). For\r
+random data, this all but eliminates the gallop penalty: min_gallop grows\r
+large enough that we almost never get into galloping mode. And for cases\r
+like ~sort, min_gallop can fall to as low as 1. This seems to work well,\r
+but in all it's a minor improvement over using a fixed MIN_GALLOP value.\r
+\r
+\r
+Galloping Complication\r
+----------------------\r
+The description above was for merge_lo. merge_hi has to merge "from the\r
+other end", and really needs to gallop starting at the last element in a run\r
+instead of the first. Galloping from the first still works, but does more\r
+comparisons than it should (this is significant -- I timed it both ways). For\r
+this reason, the gallop_left() and gallop_right() (see note LEFT OR RIGHT)\r
+functions have a "hint" argument, which is the index at which galloping\r
+should begin. So galloping can actually start at any index, and proceed at\r
+offsets of 1, 3, 7, 15, ... or -1, -3, -7, -15, ... from the starting index.\r
+\r
+In the code as I type it's always called with either 0 or n-1 (where n is\r
+the # of elements in a run). It's tempting to try to do something fancier,\r
+melding galloping with some form of interpolation search; for example, if\r
+we're merging a run of length 1 with a run of length 10000, index 5000 is\r
+probably a better guess at the final result than either 0 or 9999. But\r
+it's unclear how to generalize that intuition usefully, and merging of\r
+wildly unbalanced runs already enjoys excellent performance.\r
+\r
+~sort is a good example of when balanced runs could benefit from a better\r
+hint value: to the extent possible, this would like to use a starting\r
+offset equal to the previous value of acount/bcount. Doing so saves about\r
+10% of the compares in ~sort. However, doing so is also a mixed bag,\r
+hurting other cases.\r
+\r
+\r
+Comparing Average # of Compares on Random Arrays\r
+------------------------------------------------\r
+[NOTE: This was done when the new algorithm used about 0.1% more compares\r
+ on random data than does its current incarnation.]\r
+\r
+Here list.sort() is samplesort, and list.msort() this sort:\r
+\r
+"""\r
+import random\r
+from time import clock as now\r
+\r
+def fill(n):\r
+ from random import random\r
+ return [random() for i in xrange(n)]\r
+\r
+def mycmp(x, y):\r
+ global ncmp\r
+ ncmp += 1\r
+ return cmp(x, y)\r
+\r
+def timeit(values, method):\r
+ global ncmp\r
+ X = values[:]\r
+ bound = getattr(X, method)\r
+ ncmp = 0\r
+ t1 = now()\r
+ bound(mycmp)\r
+ t2 = now()\r
+ return t2-t1, ncmp\r
+\r
+format = "%5s %9.2f %11d"\r
+f2 = "%5s %9.2f %11.2f"\r
+\r
+def drive():\r
+ count = sst = sscmp = mst = mscmp = nelts = 0\r
+ while True:\r
+ n = random.randrange(100000)\r
+ nelts += n\r
+ x = fill(n)\r
+\r
+ t, c = timeit(x, 'sort')\r
+ sst += t\r
+ sscmp += c\r
+\r
+ t, c = timeit(x, 'msort')\r
+ mst += t\r
+ mscmp += c\r
+\r
+ count += 1\r
+ if count % 10:\r
+ continue\r
+\r
+ print "count", count, "nelts", nelts\r
+ print format % ("sort", sst, sscmp)\r
+ print format % ("msort", mst, mscmp)\r
+ print f2 % ("", (sst-mst)*1e2/mst, (sscmp-mscmp)*1e2/mscmp)\r
+\r
+drive()\r
+"""\r
+\r
+I ran this on Windows and kept using the computer lightly while it was\r
+running. time.clock() is wall-clock time on Windows, with better than\r
+microsecond resolution. samplesort started with a 1.52% #-of-comparisons\r
+disadvantage, fell quickly to 1.48%, and then fluctuated within that small\r
+range. Here's the last chunk of output before I killed the job:\r
+\r
+count 2630 nelts 130906543\r
+ sort 6110.80 1937887573\r
+msort 6002.78 1909389381\r
+ 1.80 1.49\r
+\r
+We've done nearly 2 billion comparisons apiece at Python speed there, and\r
+that's enough <wink>.\r
+\r
+For random arrays of size 2 (yes, there are only 2 interesting ones),\r
+samplesort has a 50%(!) comparison disadvantage. This is a consequence of\r
+samplesort special-casing at most one ascending run at the start, then\r
+falling back to the general case if it doesn't find an ascending run\r
+immediately. The consequence is that it ends up using two compares to sort\r
+[2, 1]. Gratifyingly, timsort doesn't do any special-casing, so had to be\r
+taught how to deal with mixtures of ascending and descending runs\r
+efficiently in all cases.\r
+\r
+\r
+NOTES\r
+-----\r
+\r
+BINSORT\r
+A "binary insertion sort" is just like a textbook insertion sort, but instead\r
+of locating the correct position of the next item via linear (one at a time)\r
+search, an equivalent to Python's bisect.bisect_right is used to find the\r
+correct position in logarithmic time. Most texts don't mention this\r
+variation, and those that do usually say it's not worth the bother: insertion\r
+sort remains quadratic (expected and worst cases) either way. Speeding the\r
+search doesn't reduce the quadratic data movement costs.\r
+\r
+But in CPython's case, comparisons are extraordinarily expensive compared to\r
+moving data, and the details matter. Moving objects is just copying\r
+pointers. Comparisons can be arbitrarily expensive (can invoke arbitary\r
+user-supplied Python code), but even in simple cases (like 3 < 4) _all_\r
+decisions are made at runtime: what's the type of the left comparand? the\r
+type of the right? do they need to be coerced to a common type? where's the\r
+code to compare these types? And so on. Even the simplest Python comparison\r
+triggers a large pile of C-level pointer dereferences, conditionals, and\r
+function calls.\r
+\r
+So cutting the number of compares is almost always measurably helpful in\r
+CPython, and the savings swamp the quadratic-time data movement costs for\r
+reasonable minrun values.\r
+\r
+\r
+LEFT OR RIGHT\r
+gallop_left() and gallop_right() are akin to the Python bisect module's\r
+bisect_left() and bisect_right(): they're the same unless the slice they're\r
+searching contains a (at least one) value equal to the value being searched\r
+for. In that case, gallop_left() returns the position immediately before the\r
+leftmost equal value, and gallop_right() the position immediately after the\r
+rightmost equal value. The distinction is needed to preserve stability. In\r
+general, when merging adjacent runs A and B, gallop_left is used to search\r
+thru B for where an element from A belongs, and gallop_right to search thru A\r
+for where an element from B belongs.\r
+\r
+\r
+REGION OF UNCERTAINTY\r
+Two kinds of confusion seem to be common about the claim that after finding\r
+a k such that\r
+\r
+ B[2**(k-1) - 1] < A[0] <= B[2**k - 1]\r
+\r
+then a binary search requires exactly k-1 tries to find A[0]'s proper\r
+location. For concreteness, say k=3, so B[3] < A[0] <= B[7].\r
+\r
+The first confusion takes the form "OK, then the region of uncertainty is at\r
+indices 3, 4, 5, 6 and 7: that's 5 elements, not the claimed 2**(k-1) - 1 =\r
+3"; or the region is viewed as a Python slice and the objection is "but that's\r
+the slice B[3:7], so has 7-3 = 4 elements". Resolution: we've already\r
+compared A[0] against B[3] and against B[7], so A[0]'s correct location is\r
+already known wrt _both_ endpoints. What remains is to find A[0]'s correct\r
+location wrt B[4], B[5] and B[6], which spans 3 elements. Or in general, the\r
+slice (leaving off both endpoints) (2**(k-1)-1)+1 through (2**k-1)-1\r
+inclusive = 2**(k-1) through (2**k-1)-1 inclusive, which has\r
+ (2**k-1)-1 - 2**(k-1) + 1 =\r
+ 2**k-1 - 2**(k-1) =\r
+ 2*2**k-1 - 2**(k-1) =\r
+ (2-1)*2**(k-1) - 1 =\r
+ 2**(k-1) - 1\r
+elements.\r
+\r
+The second confusion: "k-1 = 2 binary searches can find the correct location\r
+among 2**(k-1) = 4 elements, but you're only applying it to 3 elements: we\r
+could make this more efficient by arranging for the region of uncertainty to\r
+span 2**(k-1) elements." Resolution: that confuses "elements" with\r
+"locations". In a slice with N elements, there are N+1 _locations_. In the\r
+example, with the region of uncertainty B[4], B[5], B[6], there are 4\r
+locations: before B[4], between B[4] and B[5], between B[5] and B[6], and\r
+after B[6]. In general, across 2**(k-1)-1 elements, there are 2**(k-1)\r
+locations. That's why k-1 binary searches are necessary and sufficient.\r
--- /dev/null
+All about co_lnotab, the line number table.\r
+\r
+Code objects store a field named co_lnotab. This is an array of unsigned bytes\r
+disguised as a Python string. It is used to map bytecode offsets to source code\r
+line #s for tracebacks and to identify line number boundaries for line tracing.\r
+\r
+The array is conceptually a compressed list of\r
+ (bytecode offset increment, line number increment)\r
+pairs. The details are important and delicate, best illustrated by example:\r
+\r
+ byte code offset source code line number\r
+ 0 1\r
+ 6 2\r
+ 50 7\r
+ 350 307\r
+ 361 308\r
+\r
+Instead of storing these numbers literally, we compress the list by storing only\r
+the increments from one row to the next. Conceptually, the stored list might\r
+look like:\r
+\r
+ 0, 1, 6, 1, 44, 5, 300, 300, 11, 1\r
+\r
+The above doesn't really work, but it's a start. Note that an unsigned byte\r
+can't hold negative values, or values larger than 255, and the above example\r
+contains two such values. So we make two tweaks:\r
+\r
+ (a) there's a deep assumption that byte code offsets and their corresponding\r
+ line #s both increase monotonically, and\r
+ (b) if at least one column jumps by more than 255 from one row to the next,\r
+ more than one pair is written to the table. In case #b, there's no way to know\r
+ from looking at the table later how many were written. That's the delicate\r
+ part. A user of co_lnotab desiring to find the source line number\r
+ corresponding to a bytecode address A should do something like this\r
+\r
+ lineno = addr = 0\r
+ for addr_incr, line_incr in co_lnotab:\r
+ addr += addr_incr\r
+ if addr > A:\r
+ return lineno\r
+ lineno += line_incr\r
+\r
+(In C, this is implemented by PyCode_Addr2Line().) In order for this to work,\r
+when the addr field increments by more than 255, the line # increment in each\r
+pair generated must be 0 until the remaining addr increment is < 256. So, in\r
+the example above, assemble_lnotab in compile.c should not (as was actually done\r
+until 2.2) expand 300, 300 to\r
+ 255, 255, 45, 45,\r
+but to\r
+ 255, 0, 45, 255, 0, 45.\r
+\r
+The above is sufficient to reconstruct line numbers for tracebacks, but not for\r
+line tracing. Tracing is handled by PyCode_CheckLineNumber() in codeobject.c\r
+and maybe_call_line_trace() in ceval.c.\r
+\r
+*** Tracing ***\r
+\r
+To a first approximation, we want to call the tracing function when the line\r
+number of the current instruction changes. Re-computing the current line for\r
+every instruction is a little slow, though, so each time we compute the line\r
+number we save the bytecode indices where it's valid:\r
+\r
+ *instr_lb <= frame->f_lasti < *instr_ub\r
+\r
+is true so long as execution does not change lines. That is, *instr_lb holds\r
+the first bytecode index of the current line, and *instr_ub holds the first\r
+bytecode index of the next line. As long as the above expression is true,\r
+maybe_call_line_trace() does not need to call PyCode_CheckLineNumber(). Note\r
+that the same line may appear multiple times in the lnotab, either because the\r
+bytecode jumped more than 255 indices between line number changes or because\r
+the compiler inserted the same line twice. Even in that case, *instr_ub holds\r
+the first index of the next line.\r
+\r
+However, we don't *always* want to call the line trace function when the above\r
+test fails.\r
+\r
+Consider this code:\r
+\r
+1: def f(a):\r
+2: while a:\r
+3: print 1,\r
+4: break\r
+5: else:\r
+6: print 2,\r
+\r
+which compiles to this:\r
+\r
+ 2 0 SETUP_LOOP 19 (to 22)\r
+ >> 3 LOAD_FAST 0 (a)\r
+ 6 POP_JUMP_IF_FALSE 17\r
+\r
+ 3 9 LOAD_CONST 1 (1)\r
+ 12 PRINT_ITEM \r
+\r
+ 4 13 BREAK_LOOP \r
+ 14 JUMP_ABSOLUTE 3\r
+ >> 17 POP_BLOCK \r
+\r
+ 6 18 LOAD_CONST 2 (2)\r
+ 21 PRINT_ITEM \r
+ >> 22 LOAD_CONST 0 (None)\r
+ 25 RETURN_VALUE \r
+\r
+If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 17\r
+and the co_lnotab will claim that execution has moved to line 4, which is wrong.\r
+In this case, we could instead associate the POP_BLOCK with line 5, but that\r
+would break jumps around loops without else clauses.\r
+\r
+We fix this by only calling the line trace function for a forward jump if the\r
+co_lnotab indicates we have jumped to the *start* of a line, i.e. if the current\r
+instruction offset matches the offset given for the start of a line by the\r
+co_lnotab. For backward jumps, however, we always call the line trace function,\r
+which lets a debugger stop on every evaluation of a loop guard (which usually\r
+won't be the first opcode in a line).\r
+\r
+Why do we set f_lineno when tracing, and only just before calling the trace\r
+function? Well, consider the code above when 'a' is true. If stepping through\r
+this with 'n' in pdb, you would stop at line 1 with a "call" type event, then\r
+line events on lines 2, 3, and 4, then a "return" type event -- but because the\r
+code for the return actually falls in the range of the "line 6" opcodes, you\r
+would be shown line 6 during this event. This is a change from the behaviour in\r
+2.2 and before, and I've found it confusing in practice. By setting and using\r
+f_lineno when tracing, one can report a line number different from that\r
+suggested by f_lasti on this one occasion where it's desirable.\r
--- /dev/null
+\r
+/* Memoryview object implementation */\r
+\r
+#include "Python.h"\r
+\r
+static Py_ssize_t\r
+get_shape0(Py_buffer *buf)\r
+{\r
+ if (buf->shape != NULL)\r
+ return buf->shape[0];\r
+ if (buf->ndim == 0)\r
+ return 1;\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "exported buffer does not have any shape information associated "\r
+ "to it");\r
+ return -1;\r
+}\r
+\r
+static void\r
+dup_buffer(Py_buffer *dest, Py_buffer *src)\r
+{\r
+ *dest = *src;\r
+ if (src->ndim == 1 && src->shape != NULL) {\r
+ dest->shape = &(dest->smalltable[0]);\r
+ dest->shape[0] = get_shape0(src);\r
+ }\r
+ if (src->ndim == 1 && src->strides != NULL) {\r
+ dest->strides = &(dest->smalltable[1]);\r
+ dest->strides[0] = src->strides[0];\r
+ }\r
+}\r
+\r
+static int\r
+memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)\r
+{\r
+ int res = 0;\r
+ if (self->view.obj != NULL)\r
+ res = PyObject_GetBuffer(self->view.obj, view, flags);\r
+ if (view)\r
+ dup_buffer(view, &self->view);\r
+ return res;\r
+}\r
+\r
+static void\r
+memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)\r
+{\r
+ PyBuffer_Release(view);\r
+}\r
+\r
+PyDoc_STRVAR(memory_doc,\r
+"memoryview(object)\n\\r
+\n\\r
+Create a new memoryview object which references the given object.");\r
+\r
+PyObject *\r
+PyMemoryView_FromBuffer(Py_buffer *info)\r
+{\r
+ PyMemoryViewObject *mview;\r
+\r
+ mview = (PyMemoryViewObject *)\r
+ PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type);\r
+ if (mview == NULL)\r
+ return NULL;\r
+ mview->base = NULL;\r
+ dup_buffer(&mview->view, info);\r
+ /* NOTE: mview->view.obj should already have been incref'ed as\r
+ part of PyBuffer_FillInfo(). */\r
+ _PyObject_GC_TRACK(mview);\r
+ return (PyObject *)mview;\r
+}\r
+\r
+PyObject *\r
+PyMemoryView_FromObject(PyObject *base)\r
+{\r
+ PyMemoryViewObject *mview;\r
+ Py_buffer view;\r
+\r
+ if (!PyObject_CheckBuffer(base)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "cannot make memory view because object does "\r
+ "not have the buffer interface");\r
+ return NULL;\r
+ }\r
+\r
+ if (PyObject_GetBuffer(base, &view, PyBUF_FULL_RO) < 0)\r
+ return NULL;\r
+\r
+ mview = (PyMemoryViewObject *)PyMemoryView_FromBuffer(&view);\r
+ if (mview == NULL) {\r
+ PyBuffer_Release(&view);\r
+ return NULL;\r
+ }\r
+\r
+ mview->base = base;\r
+ Py_INCREF(base);\r
+ return (PyObject *)mview;\r
+}\r
+\r
+static PyObject *\r
+memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *obj;\r
+ static char *kwlist[] = {"object", 0};\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,\r
+ &obj)) {\r
+ return NULL;\r
+ }\r
+\r
+ return PyMemoryView_FromObject(obj);\r
+}\r
+\r
+\r
+static void\r
+_strided_copy_nd(char *dest, char *src, int nd, Py_ssize_t *shape,\r
+ Py_ssize_t *strides, Py_ssize_t itemsize, char fort)\r
+{\r
+ int k;\r
+ Py_ssize_t outstride;\r
+\r
+ if (nd==0) {\r
+ memcpy(dest, src, itemsize);\r
+ }\r
+ else if (nd == 1) {\r
+ for (k = 0; k<shape[0]; k++) {\r
+ memcpy(dest, src, itemsize);\r
+ dest += itemsize;\r
+ src += strides[0];\r
+ }\r
+ }\r
+ else {\r
+ if (fort == 'F') {\r
+ /* Copy first dimension first,\r
+ second dimension second, etc...\r
+ Set up the recursive loop backwards so that final\r
+ dimension is actually copied last.\r
+ */\r
+ outstride = itemsize;\r
+ for (k=1; k<nd-1;k++) {\r
+ outstride *= shape[k];\r
+ }\r
+ for (k=0; k<shape[nd-1]; k++) {\r
+ _strided_copy_nd(dest, src, nd-1, shape,\r
+ strides, itemsize, fort);\r
+ dest += outstride;\r
+ src += strides[nd-1];\r
+ }\r
+ }\r
+\r
+ else {\r
+ /* Copy last dimension first,\r
+ second-to-last dimension second, etc.\r
+ Set up the recursion so that the\r
+ first dimension is copied last\r
+ */\r
+ outstride = itemsize;\r
+ for (k=1; k < nd; k++) {\r
+ outstride *= shape[k];\r
+ }\r
+ for (k=0; k<shape[0]; k++) {\r
+ _strided_copy_nd(dest, src, nd-1, shape+1,\r
+ strides+1, itemsize,\r
+ fort);\r
+ dest += outstride;\r
+ src += strides[0];\r
+ }\r
+ }\r
+ }\r
+ return;\r
+}\r
+\r
+static int\r
+_indirect_copy_nd(char *dest, Py_buffer *view, char fort)\r
+{\r
+ Py_ssize_t *indices;\r
+ int k;\r
+ Py_ssize_t elements;\r
+ char *ptr;\r
+ void (*func)(int, Py_ssize_t *, const Py_ssize_t *);\r
+\r
+ if (view->ndim > PY_SSIZE_T_MAX / sizeof(Py_ssize_t)) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+\r
+ indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view->ndim);\r
+ if (indices == NULL) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ for (k=0; k<view->ndim;k++) {\r
+ indices[k] = 0;\r
+ }\r
+\r
+ elements = 1;\r
+ for (k=0; k<view->ndim; k++) {\r
+ elements *= view->shape[k];\r
+ }\r
+ if (fort == 'F') {\r
+ func = _Py_add_one_to_index_F;\r
+ }\r
+ else {\r
+ func = _Py_add_one_to_index_C;\r
+ }\r
+ while (elements--) {\r
+ func(view->ndim, indices, view->shape);\r
+ ptr = PyBuffer_GetPointer(view, indices);\r
+ memcpy(dest, ptr, view->itemsize);\r
+ dest += view->itemsize;\r
+ }\r
+\r
+ PyMem_Free(indices);\r
+ return 0;\r
+}\r
+\r
+/*\r
+ Get a the data from an object as a contiguous chunk of memory (in\r
+ either 'C' or 'F'ortran order) even if it means copying it into a\r
+ separate memory area.\r
+\r
+ Returns a new reference to a Memory view object. If no copy is needed,\r
+ the memory view object points to the original memory and holds a\r
+ lock on the original. If a copy is needed, then the memory view object\r
+ points to a brand-new Bytes object (and holds a memory lock on it).\r
+\r
+ buffertype\r
+\r
+ PyBUF_READ buffer only needs to be read-only\r
+ PyBUF_WRITE buffer needs to be writable (give error if not contiguous)\r
+ PyBUF_SHADOW buffer needs to be writable so shadow it with\r
+ a contiguous buffer if it is not. The view will point to\r
+ the shadow buffer which can be written to and then\r
+ will be copied back into the other buffer when the memory\r
+ view is de-allocated. While the shadow buffer is\r
+ being used, it will have an exclusive write lock on\r
+ the original buffer.\r
+ */\r
+\r
+PyObject *\r
+PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)\r
+{\r
+ PyMemoryViewObject *mem;\r
+ PyObject *bytes;\r
+ Py_buffer *view;\r
+ int flags;\r
+ char *dest;\r
+\r
+ if (!PyObject_CheckBuffer(obj)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "object does not have the buffer interface");\r
+ return NULL;\r
+ }\r
+\r
+ mem = PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type);\r
+ if (mem == NULL)\r
+ return NULL;\r
+\r
+ view = &mem->view;\r
+ flags = PyBUF_FULL_RO;\r
+ switch(buffertype) {\r
+ case PyBUF_WRITE:\r
+ flags = PyBUF_FULL;\r
+ break;\r
+ }\r
+\r
+ if (PyObject_GetBuffer(obj, view, flags) != 0) {\r
+ Py_DECREF(mem);\r
+ return NULL;\r
+ }\r
+\r
+ if (PyBuffer_IsContiguous(view, fort)) {\r
+ /* no copy needed */\r
+ Py_INCREF(obj);\r
+ mem->base = obj;\r
+ _PyObject_GC_TRACK(mem);\r
+ return (PyObject *)mem;\r
+ }\r
+ /* otherwise a copy is needed */\r
+ if (buffertype == PyBUF_WRITE) {\r
+ Py_DECREF(mem);\r
+ PyErr_SetString(PyExc_BufferError,\r
+ "writable contiguous buffer requested "\r
+ "for a non-contiguousobject.");\r
+ return NULL;\r
+ }\r
+ bytes = PyBytes_FromStringAndSize(NULL, view->len);\r
+ if (bytes == NULL) {\r
+ Py_DECREF(mem);\r
+ return NULL;\r
+ }\r
+ dest = PyBytes_AS_STRING(bytes);\r
+ /* different copying strategy depending on whether\r
+ or not any pointer de-referencing is needed\r
+ */\r
+ /* strided or in-direct copy */\r
+ if (view->suboffsets==NULL) {\r
+ _strided_copy_nd(dest, view->buf, view->ndim, view->shape,\r
+ view->strides, view->itemsize, fort);\r
+ }\r
+ else {\r
+ if (_indirect_copy_nd(dest, view, fort) < 0) {\r
+ Py_DECREF(bytes);\r
+ Py_DECREF(mem);\r
+ return NULL;\r
+ }\r
+ }\r
+ if (buffertype == PyBUF_SHADOW) {\r
+ /* return a shadowed memory-view object */\r
+ view->buf = dest;\r
+ mem->base = PyTuple_Pack(2, obj, bytes);\r
+ Py_DECREF(bytes);\r
+ if (mem->base == NULL) {\r
+ Py_DECREF(mem);\r
+ return NULL;\r
+ }\r
+ }\r
+ else {\r
+ PyBuffer_Release(view); /* XXX ? */\r
+ /* steal the reference */\r
+ mem->base = bytes;\r
+ }\r
+ _PyObject_GC_TRACK(mem);\r
+ return (PyObject *)mem;\r
+}\r
+\r
+\r
+static PyObject *\r
+memory_format_get(PyMemoryViewObject *self)\r
+{\r
+ return PyString_FromString(self->view.format);\r
+}\r
+\r
+static PyObject *\r
+memory_itemsize_get(PyMemoryViewObject *self)\r
+{\r
+ return PyLong_FromSsize_t(self->view.itemsize);\r
+}\r
+\r
+static PyObject *\r
+_IntTupleFromSsizet(int len, Py_ssize_t *vals)\r
+{\r
+ int i;\r
+ PyObject *o;\r
+ PyObject *intTuple;\r
+\r
+ if (vals == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ intTuple = PyTuple_New(len);\r
+ if (!intTuple) return NULL;\r
+ for(i=0; i<len; i++) {\r
+ o = PyLong_FromSsize_t(vals[i]);\r
+ if (!o) {\r
+ Py_DECREF(intTuple);\r
+ return NULL;\r
+ }\r
+ PyTuple_SET_ITEM(intTuple, i, o);\r
+ }\r
+ return intTuple;\r
+}\r
+\r
+static PyObject *\r
+memory_shape_get(PyMemoryViewObject *self)\r
+{\r
+ return _IntTupleFromSsizet(self->view.ndim, self->view.shape);\r
+}\r
+\r
+static PyObject *\r
+memory_strides_get(PyMemoryViewObject *self)\r
+{\r
+ return _IntTupleFromSsizet(self->view.ndim, self->view.strides);\r
+}\r
+\r
+static PyObject *\r
+memory_suboffsets_get(PyMemoryViewObject *self)\r
+{\r
+ return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);\r
+}\r
+\r
+static PyObject *\r
+memory_readonly_get(PyMemoryViewObject *self)\r
+{\r
+ return PyBool_FromLong(self->view.readonly);\r
+}\r
+\r
+static PyObject *\r
+memory_ndim_get(PyMemoryViewObject *self)\r
+{\r
+ return PyLong_FromLong(self->view.ndim);\r
+}\r
+\r
+static PyGetSetDef memory_getsetlist[] ={\r
+ {"format", (getter)memory_format_get, NULL, NULL},\r
+ {"itemsize", (getter)memory_itemsize_get, NULL, NULL},\r
+ {"shape", (getter)memory_shape_get, NULL, NULL},\r
+ {"strides", (getter)memory_strides_get, NULL, NULL},\r
+ {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL},\r
+ {"readonly", (getter)memory_readonly_get, NULL, NULL},\r
+ {"ndim", (getter)memory_ndim_get, NULL, NULL},\r
+ {NULL, NULL, NULL, NULL},\r
+};\r
+\r
+\r
+static PyObject *\r
+memory_tobytes(PyMemoryViewObject *self, PyObject *noargs)\r
+{\r
+ Py_buffer view;\r
+ PyObject *res;\r
+\r
+ if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_SIMPLE) < 0)\r
+ return NULL;\r
+\r
+ res = PyBytes_FromStringAndSize(NULL, view.len);\r
+ PyBuffer_ToContiguous(PyBytes_AS_STRING(res), &view, view.len, 'C');\r
+ PyBuffer_Release(&view);\r
+ return res;\r
+}\r
+\r
+/* TODO: rewrite this function using the struct module to unpack\r
+ each buffer item */\r
+\r
+static PyObject *\r
+memory_tolist(PyMemoryViewObject *mem, PyObject *noargs)\r
+{\r
+ Py_buffer *view = &(mem->view);\r
+ Py_ssize_t i;\r
+ PyObject *res, *item;\r
+ char *buf;\r
+\r
+ if (strcmp(view->format, "B") || view->itemsize != 1) {\r
+ PyErr_SetString(PyExc_NotImplementedError, \r
+ "tolist() only supports byte views");\r
+ return NULL;\r
+ }\r
+ if (view->ndim != 1) {\r
+ PyErr_SetString(PyExc_NotImplementedError, \r
+ "tolist() only supports one-dimensional objects");\r
+ return NULL;\r
+ }\r
+ res = PyList_New(view->len);\r
+ if (res == NULL)\r
+ return NULL;\r
+ buf = view->buf;\r
+ for (i = 0; i < view->len; i++) {\r
+ item = PyInt_FromLong((unsigned char) *buf);\r
+ if (item == NULL) {\r
+ Py_DECREF(res);\r
+ return NULL;\r
+ }\r
+ PyList_SET_ITEM(res, i, item);\r
+ buf++;\r
+ }\r
+ return res;\r
+}\r
+\r
+static PyMethodDef memory_methods[] = {\r
+ {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL},\r
+ {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+\r
+static void\r
+memory_dealloc(PyMemoryViewObject *self)\r
+{\r
+ _PyObject_GC_UNTRACK(self);\r
+ if (self->view.obj != NULL) {\r
+ if (self->base && PyTuple_Check(self->base)) {\r
+ /* Special case when first element is generic object\r
+ with buffer interface and the second element is a\r
+ contiguous "shadow" that must be copied back into\r
+ the data areay of the first tuple element before\r
+ releasing the buffer on the first element.\r
+ */\r
+\r
+ PyObject_CopyData(PyTuple_GET_ITEM(self->base,0),\r
+ PyTuple_GET_ITEM(self->base,1));\r
+\r
+ /* The view member should have readonly == -1 in\r
+ this instance indicating that the memory can\r
+ be "locked" and was locked and will be unlocked\r
+ again after this call.\r
+ */\r
+ PyBuffer_Release(&(self->view));\r
+ }\r
+ else {\r
+ PyBuffer_Release(&(self->view));\r
+ }\r
+ Py_CLEAR(self->base);\r
+ }\r
+ PyObject_GC_Del(self);\r
+}\r
+\r
+static PyObject *\r
+memory_repr(PyMemoryViewObject *self)\r
+{\r
+ return PyString_FromFormat("<memory at %p>", self);\r
+}\r
+\r
+/* Sequence methods */\r
+static Py_ssize_t\r
+memory_length(PyMemoryViewObject *self)\r
+{\r
+ return get_shape0(&self->view);\r
+}\r
+\r
+/* Alternate version of memory_subcript that only accepts indices.\r
+ Used by PySeqIter_New().\r
+*/\r
+static PyObject *\r
+memory_item(PyMemoryViewObject *self, Py_ssize_t result)\r
+{\r
+ Py_buffer *view = &(self->view);\r
+\r
+ if (view->ndim == 0) {\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "invalid indexing of 0-dim memory");\r
+ return NULL;\r
+ }\r
+ if (view->ndim == 1) {\r
+ /* Return a bytes object */\r
+ char *ptr;\r
+ ptr = (char *)view->buf;\r
+ if (result < 0) {\r
+ result += get_shape0(view);\r
+ }\r
+ if ((result < 0) || (result >= get_shape0(view))) {\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "index out of bounds");\r
+ return NULL;\r
+ }\r
+ if (view->strides == NULL)\r
+ ptr += view->itemsize * result;\r
+ else\r
+ ptr += view->strides[0] * result;\r
+ if (view->suboffsets != NULL &&\r
+ view->suboffsets[0] >= 0) {\r
+ ptr = *((char **)ptr) + view->suboffsets[0];\r
+ }\r
+ return PyBytes_FromStringAndSize(ptr, view->itemsize);\r
+ } else {\r
+ /* Return a new memory-view object */\r
+ Py_buffer newview;\r
+ memset(&newview, 0, sizeof(newview));\r
+ /* XXX: This needs to be fixed so it actually returns a sub-view */\r
+ return PyMemoryView_FromBuffer(&newview);\r
+ }\r
+}\r
+\r
+/*\r
+ mem[obj] returns a bytes object holding the data for one element if\r
+ obj fully indexes the memory view or another memory-view object\r
+ if it does not.\r
+\r
+ 0-d memory-view objects can be referenced using ... or () but\r
+ not with anything else.\r
+ */\r
+static PyObject *\r
+memory_subscript(PyMemoryViewObject *self, PyObject *key)\r
+{\r
+ Py_buffer *view;\r
+ view = &(self->view);\r
+ \r
+ if (view->ndim == 0) {\r
+ if (key == Py_Ellipsis ||\r
+ (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "invalid indexing of 0-dim memory");\r
+ return NULL;\r
+ }\r
+ }\r
+ if (PyIndex_Check(key)) {\r
+ Py_ssize_t result;\r
+ result = PyNumber_AsSsize_t(key, NULL);\r
+ if (result == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ return memory_item(self, result);\r
+ }\r
+ else if (PySlice_Check(key)) {\r
+ Py_ssize_t start, stop, step, slicelength;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject*)key, get_shape0(view),\r
+ &start, &stop, &step, &slicelength) < 0) {\r
+ return NULL;\r
+ }\r
+ \r
+ if (step == 1 && view->ndim == 1) {\r
+ Py_buffer newview;\r
+ void *newbuf = (char *) view->buf\r
+ + start * view->itemsize;\r
+ int newflags = view->readonly\r
+ ? PyBUF_CONTIG_RO : PyBUF_CONTIG;\r
+ \r
+ /* XXX There should be an API to create a subbuffer */\r
+ if (view->obj != NULL) {\r
+ if (PyObject_GetBuffer(view->obj, &newview, newflags) == -1)\r
+ return NULL;\r
+ }\r
+ else {\r
+ newview = *view;\r
+ }\r
+ newview.buf = newbuf;\r
+ newview.len = slicelength * newview.itemsize;\r
+ newview.format = view->format;\r
+ newview.shape = &(newview.smalltable[0]);\r
+ newview.shape[0] = slicelength;\r
+ newview.strides = &(newview.itemsize);\r
+ return PyMemoryView_FromBuffer(&newview);\r
+ }\r
+ PyErr_SetNone(PyExc_NotImplementedError);\r
+ return NULL;\r
+ }\r
+ PyErr_Format(PyExc_TypeError,\r
+ "cannot index memory using \"%.200s\"", \r
+ key->ob_type->tp_name);\r
+ return NULL;\r
+}\r
+\r
+\r
+/* Need to support assigning memory if we can */\r
+static int\r
+memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)\r
+{\r
+ Py_ssize_t start, len, bytelen;\r
+ Py_buffer srcview;\r
+ Py_buffer *view = &(self->view);\r
+ char *srcbuf, *destbuf;\r
+\r
+ if (view->readonly) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "cannot modify read-only memory");\r
+ return -1;\r
+ }\r
+ if (value == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "cannot delete memory");\r
+ return -1;\r
+ }\r
+ if (view->ndim != 1) {\r
+ PyErr_SetNone(PyExc_NotImplementedError);\r
+ return -1;\r
+ }\r
+ if (PyIndex_Check(key)) {\r
+ start = PyNumber_AsSsize_t(key, NULL);\r
+ if (start == -1 && PyErr_Occurred())\r
+ return -1;\r
+ if (start < 0) {\r
+ start += get_shape0(view);\r
+ }\r
+ if ((start < 0) || (start >= get_shape0(view))) {\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "index out of bounds");\r
+ return -1;\r
+ }\r
+ len = 1;\r
+ }\r
+ else if (PySlice_Check(key)) {\r
+ Py_ssize_t stop, step;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject*)key, get_shape0(view),\r
+ &start, &stop, &step, &len) < 0) {\r
+ return -1;\r
+ }\r
+ if (step != 1) {\r
+ PyErr_SetNone(PyExc_NotImplementedError);\r
+ return -1;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "cannot index memory using \"%.200s\"", \r
+ key->ob_type->tp_name);\r
+ return -1;\r
+ }\r
+ if (PyObject_GetBuffer(value, &srcview, PyBUF_CONTIG_RO) == -1) {\r
+ return -1;\r
+ }\r
+ /* XXX should we allow assignment of different item sizes\r
+ as long as the byte length is the same?\r
+ (e.g. assign 2 shorts to a 4-byte slice) */\r
+ if (srcview.itemsize != view->itemsize) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "mismatching item sizes for \"%.200s\" and \"%.200s\"", \r
+ view->obj->ob_type->tp_name, srcview.obj->ob_type->tp_name);\r
+ goto _error;\r
+ }\r
+ bytelen = len * view->itemsize;\r
+ if (bytelen != srcview.len) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "cannot modify size of memoryview object");\r
+ goto _error;\r
+ }\r
+ /* Do the actual copy */\r
+ destbuf = (char *) view->buf + start * view->itemsize;\r
+ srcbuf = (char *) srcview.buf;\r
+ if (destbuf + bytelen < srcbuf || srcbuf + bytelen < destbuf)\r
+ /* No overlapping */\r
+ memcpy(destbuf, srcbuf, bytelen);\r
+ else\r
+ memmove(destbuf, srcbuf, bytelen);\r
+\r
+ PyBuffer_Release(&srcview);\r
+ return 0;\r
+\r
+_error:\r
+ PyBuffer_Release(&srcview);\r
+ return -1;\r
+}\r
+\r
+static PyObject *\r
+memory_richcompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ Py_buffer vv, ww;\r
+ int equal = 0;\r
+ PyObject *res;\r
+\r
+ vv.obj = NULL;\r
+ ww.obj = NULL;\r
+ if (op != Py_EQ && op != Py_NE)\r
+ goto _notimpl;\r
+ if (PyObject_GetBuffer(v, &vv, PyBUF_CONTIG_RO) == -1) {\r
+ PyErr_Clear();\r
+ goto _notimpl;\r
+ }\r
+ if (PyObject_GetBuffer(w, &ww, PyBUF_CONTIG_RO) == -1) {\r
+ PyErr_Clear();\r
+ goto _notimpl;\r
+ }\r
+\r
+ if (vv.itemsize != ww.itemsize || vv.len != ww.len)\r
+ goto _end;\r
+\r
+ equal = !memcmp(vv.buf, ww.buf, vv.len);\r
+\r
+_end:\r
+ PyBuffer_Release(&vv);\r
+ PyBuffer_Release(&ww);\r
+ if ((equal && op == Py_EQ) || (!equal && op == Py_NE))\r
+ res = Py_True;\r
+ else\r
+ res = Py_False;\r
+ Py_INCREF(res);\r
+ return res;\r
+\r
+_notimpl:\r
+ PyBuffer_Release(&vv);\r
+ PyBuffer_Release(&ww);\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+}\r
+\r
+\r
+static int\r
+memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)\r
+{\r
+ if (self->base != NULL)\r
+ Py_VISIT(self->base);\r
+ if (self->view.obj != NULL)\r
+ Py_VISIT(self->view.obj);\r
+ return 0;\r
+}\r
+\r
+static int\r
+memory_clear(PyMemoryViewObject *self)\r
+{\r
+ Py_CLEAR(self->base);\r
+ PyBuffer_Release(&self->view);\r
+ return 0;\r
+}\r
+\r
+\r
+/* As mapping */\r
+static PyMappingMethods memory_as_mapping = {\r
+ (lenfunc)memory_length, /* mp_length */\r
+ (binaryfunc)memory_subscript, /* mp_subscript */\r
+ (objobjargproc)memory_ass_sub, /* mp_ass_subscript */\r
+};\r
+\r
+static PySequenceMethods memory_as_sequence = {\r
+ 0, /* sq_length */\r
+ 0, /* sq_concat */\r
+ 0, /* sq_repeat */\r
+ (ssizeargfunc)memory_item, /* sq_item */\r
+};\r
+\r
+/* Buffer methods */\r
+static PyBufferProcs memory_as_buffer = {\r
+ 0, /* bf_getreadbuffer */\r
+ 0, /* bf_getwritebuffer */\r
+ 0, /* bf_getsegcount */\r
+ 0, /* bf_getcharbuffer */\r
+ (getbufferproc)memory_getbuf, /* bf_getbuffer */\r
+ (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */\r
+};\r
+\r
+\r
+PyTypeObject PyMemoryView_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "memoryview",\r
+ sizeof(PyMemoryViewObject),\r
+ 0,\r
+ (destructor)memory_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)memory_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &memory_as_sequence, /* tp_as_sequence */\r
+ &memory_as_mapping, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ &memory_as_buffer, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */\r
+ memory_doc, /* tp_doc */\r
+ (traverseproc)memory_traverse, /* tp_traverse */\r
+ (inquiry)memory_clear, /* tp_clear */\r
+ memory_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ memory_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ memory_getsetlist, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ memory_new, /* tp_new */\r
+};\r
--- /dev/null
+\r
+/* Method object implementation */\r
+\r
+#include "Python.h"\r
+#include "structmember.h"\r
+\r
+/* Free list for method objects to safe malloc/free overhead\r
+ * The m_self element is used to chain the objects.\r
+ */\r
+static PyCFunctionObject *free_list = NULL;\r
+static int numfree = 0;\r
+#ifndef PyCFunction_MAXFREELIST\r
+#define PyCFunction_MAXFREELIST 256\r
+#endif\r
+\r
+PyObject *\r
+PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)\r
+{\r
+ PyCFunctionObject *op;\r
+ op = free_list;\r
+ if (op != NULL) {\r
+ free_list = (PyCFunctionObject *)(op->m_self);\r
+ PyObject_INIT(op, &PyCFunction_Type);\r
+ numfree--;\r
+ }\r
+ else {\r
+ op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);\r
+ if (op == NULL)\r
+ return NULL;\r
+ }\r
+ op->m_ml = ml;\r
+ Py_XINCREF(self);\r
+ op->m_self = self;\r
+ Py_XINCREF(module);\r
+ op->m_module = module;\r
+ _PyObject_GC_TRACK(op);\r
+ return (PyObject *)op;\r
+}\r
+\r
+PyCFunction\r
+PyCFunction_GetFunction(PyObject *op)\r
+{\r
+ if (!PyCFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;\r
+}\r
+\r
+PyObject *\r
+PyCFunction_GetSelf(PyObject *op)\r
+{\r
+ if (!PyCFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return ((PyCFunctionObject *)op) -> m_self;\r
+}\r
+\r
+int\r
+PyCFunction_GetFlags(PyObject *op)\r
+{\r
+ if (!PyCFunction_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;\r
+}\r
+\r
+PyObject *\r
+PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)\r
+{\r
+ PyCFunctionObject* f = (PyCFunctionObject*)func;\r
+ PyCFunction meth = PyCFunction_GET_FUNCTION(func);\r
+ PyObject *self = PyCFunction_GET_SELF(func);\r
+ Py_ssize_t size;\r
+\r
+ switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {\r
+ case METH_VARARGS:\r
+ if (kw == NULL || PyDict_Size(kw) == 0)\r
+ return (*meth)(self, arg);\r
+ break;\r
+ case METH_VARARGS | METH_KEYWORDS:\r
+ case METH_OLDARGS | METH_KEYWORDS:\r
+ return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);\r
+ case METH_NOARGS:\r
+ if (kw == NULL || PyDict_Size(kw) == 0) {\r
+ size = PyTuple_GET_SIZE(arg);\r
+ if (size == 0)\r
+ return (*meth)(self, NULL);\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%.200s() takes no arguments (%zd given)",\r
+ f->m_ml->ml_name, size);\r
+ return NULL;\r
+ }\r
+ break;\r
+ case METH_O:\r
+ if (kw == NULL || PyDict_Size(kw) == 0) {\r
+ size = PyTuple_GET_SIZE(arg);\r
+ if (size == 1)\r
+ return (*meth)(self, PyTuple_GET_ITEM(arg, 0));\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%.200s() takes exactly one argument (%zd given)",\r
+ f->m_ml->ml_name, size);\r
+ return NULL;\r
+ }\r
+ break;\r
+ case METH_OLDARGS:\r
+ /* the really old style */\r
+ if (kw == NULL || PyDict_Size(kw) == 0) {\r
+ size = PyTuple_GET_SIZE(arg);\r
+ if (size == 1)\r
+ arg = PyTuple_GET_ITEM(arg, 0);\r
+ else if (size == 0)\r
+ arg = NULL;\r
+ return (*meth)(self, arg);\r
+ }\r
+ break;\r
+ default:\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",\r
+ f->m_ml->ml_name);\r
+ return NULL;\r
+}\r
+\r
+/* Methods (the standard built-in methods, that is) */\r
+\r
+static void\r
+meth_dealloc(PyCFunctionObject *m)\r
+{\r
+ _PyObject_GC_UNTRACK(m);\r
+ Py_XDECREF(m->m_self);\r
+ Py_XDECREF(m->m_module);\r
+ if (numfree < PyCFunction_MAXFREELIST) {\r
+ m->m_self = (PyObject *)free_list;\r
+ free_list = m;\r
+ numfree++;\r
+ }\r
+ else {\r
+ PyObject_GC_Del(m);\r
+ }\r
+}\r
+\r
+static PyObject *\r
+meth_get__doc__(PyCFunctionObject *m, void *closure)\r
+{\r
+ const char *doc = m->m_ml->ml_doc;\r
+\r
+ if (doc != NULL)\r
+ return PyString_FromString(doc);\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+meth_get__name__(PyCFunctionObject *m, void *closure)\r
+{\r
+ return PyString_FromString(m->m_ml->ml_name);\r
+}\r
+\r
+static int\r
+meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(m->m_self);\r
+ Py_VISIT(m->m_module);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+meth_get__self__(PyCFunctionObject *m, void *closure)\r
+{\r
+ PyObject *self;\r
+ if (PyEval_GetRestricted()) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "method.__self__ not accessible in restricted mode");\r
+ return NULL;\r
+ }\r
+ self = m->m_self;\r
+ if (self == NULL)\r
+ self = Py_None;\r
+ Py_INCREF(self);\r
+ return self;\r
+}\r
+\r
+static PyGetSetDef meth_getsets [] = {\r
+ {"__doc__", (getter)meth_get__doc__, NULL, NULL},\r
+ {"__name__", (getter)meth_get__name__, NULL, NULL},\r
+ {"__self__", (getter)meth_get__self__, NULL, NULL},\r
+ {0}\r
+};\r
+\r
+#define OFF(x) offsetof(PyCFunctionObject, x)\r
+\r
+static PyMemberDef meth_members[] = {\r
+ {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},\r
+ {NULL}\r
+};\r
+\r
+static PyObject *\r
+meth_repr(PyCFunctionObject *m)\r
+{\r
+ if (m->m_self == NULL)\r
+ return PyString_FromFormat("<built-in function %s>",\r
+ m->m_ml->ml_name);\r
+ return PyString_FromFormat("<built-in method %s of %s object at %p>",\r
+ m->m_ml->ml_name,\r
+ m->m_self->ob_type->tp_name,\r
+ m->m_self);\r
+}\r
+\r
+static int\r
+meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)\r
+{\r
+ if (a->m_self != b->m_self)\r
+ return (a->m_self < b->m_self) ? -1 : 1;\r
+ if (a->m_ml->ml_meth == b->m_ml->ml_meth)\r
+ return 0;\r
+ if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)\r
+ return -1;\r
+ else\r
+ return 1;\r
+}\r
+\r
+static PyObject *\r
+meth_richcompare(PyObject *self, PyObject *other, int op)\r
+{\r
+ PyCFunctionObject *a, *b;\r
+ PyObject *res;\r
+ int eq;\r
+\r
+ if (op != Py_EQ && op != Py_NE) {\r
+ /* Py3K warning if comparison isn't == or !=. */\r
+ if (PyErr_WarnPy3k("builtin_function_or_method order "\r
+ "comparisons not supported in 3.x", 1) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ else if (!PyCFunction_Check(self) || !PyCFunction_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ a = (PyCFunctionObject *)self;\r
+ b = (PyCFunctionObject *)other;\r
+ eq = a->m_self == b->m_self;\r
+ if (eq)\r
+ eq = a->m_ml->ml_meth == b->m_ml->ml_meth;\r
+ if (op == Py_EQ)\r
+ res = eq ? Py_True : Py_False;\r
+ else\r
+ res = eq ? Py_False : Py_True;\r
+ Py_INCREF(res);\r
+ return res;\r
+}\r
+\r
+static long\r
+meth_hash(PyCFunctionObject *a)\r
+{\r
+ long x,y;\r
+ if (a->m_self == NULL)\r
+ x = 0;\r
+ else {\r
+ x = PyObject_Hash(a->m_self);\r
+ if (x == -1)\r
+ return -1;\r
+ }\r
+ y = _Py_HashPointer((void*)(a->m_ml->ml_meth));\r
+ if (y == -1)\r
+ return -1;\r
+ x ^= y;\r
+ if (x == -1)\r
+ x = -2;\r
+ return x;\r
+}\r
+\r
+\r
+PyTypeObject PyCFunction_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "builtin_function_or_method",\r
+ sizeof(PyCFunctionObject),\r
+ 0,\r
+ (destructor)meth_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)meth_compare, /* tp_compare */\r
+ (reprfunc)meth_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)meth_hash, /* tp_hash */\r
+ PyCFunction_Call, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)meth_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ meth_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ meth_members, /* tp_members */\r
+ meth_getsets, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+};\r
+\r
+/* List all methods in a chain -- helper for findmethodinchain */\r
+\r
+static PyObject *\r
+listmethodchain(PyMethodChain *chain)\r
+{\r
+ PyMethodChain *c;\r
+ PyMethodDef *ml;\r
+ int i, n;\r
+ PyObject *v;\r
+\r
+ n = 0;\r
+ for (c = chain; c != NULL; c = c->link) {\r
+ for (ml = c->methods; ml->ml_name != NULL; ml++)\r
+ n++;\r
+ }\r
+ v = PyList_New(n);\r
+ if (v == NULL)\r
+ return NULL;\r
+ i = 0;\r
+ for (c = chain; c != NULL; c = c->link) {\r
+ for (ml = c->methods; ml->ml_name != NULL; ml++) {\r
+ PyList_SetItem(v, i, PyString_FromString(ml->ml_name));\r
+ i++;\r
+ }\r
+ }\r
+ if (PyErr_Occurred()) {\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ PyList_Sort(v);\r
+ return v;\r
+}\r
+\r
+/* Find a method in a method chain */\r
+\r
+PyObject *\r
+Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)\r
+{\r
+ if (name[0] == '_' && name[1] == '_') {\r
+ if (strcmp(name, "__methods__") == 0) {\r
+ if (PyErr_WarnPy3k("__methods__ not supported in 3.x",\r
+ 1) < 0)\r
+ return NULL;\r
+ return listmethodchain(chain);\r
+ }\r
+ if (strcmp(name, "__doc__") == 0) {\r
+ const char *doc = self->ob_type->tp_doc;\r
+ if (doc != NULL)\r
+ return PyString_FromString(doc);\r
+ }\r
+ }\r
+ while (chain != NULL) {\r
+ PyMethodDef *ml = chain->methods;\r
+ for (; ml->ml_name != NULL; ml++) {\r
+ if (name[0] == ml->ml_name[0] &&\r
+ strcmp(name+1, ml->ml_name+1) == 0)\r
+ /* XXX */\r
+ return PyCFunction_New(ml, self);\r
+ }\r
+ chain = chain->link;\r
+ }\r
+ PyErr_SetString(PyExc_AttributeError, name);\r
+ return NULL;\r
+}\r
+\r
+/* Find a method in a single method list */\r
+\r
+PyObject *\r
+Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)\r
+{\r
+ PyMethodChain chain;\r
+ chain.methods = methods;\r
+ chain.link = NULL;\r
+ return Py_FindMethodInChain(&chain, self, name);\r
+}\r
+\r
+/* Clear out the free list */\r
+\r
+int\r
+PyCFunction_ClearFreeList(void)\r
+{\r
+ int freelist_size = numfree;\r
+\r
+ while (free_list) {\r
+ PyCFunctionObject *v = free_list;\r
+ free_list = (PyCFunctionObject *)(v->m_self);\r
+ PyObject_GC_Del(v);\r
+ numfree--;\r
+ }\r
+ assert(numfree == 0);\r
+ return freelist_size;\r
+}\r
+\r
+void\r
+PyCFunction_Fini(void)\r
+{\r
+ (void)PyCFunction_ClearFreeList();\r
+}\r
+\r
+/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),\r
+ but it's part of the API so we need to keep a function around that\r
+ existing C extensions can call.\r
+*/\r
+\r
+#undef PyCFunction_New\r
+PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);\r
+\r
+PyObject *\r
+PyCFunction_New(PyMethodDef *ml, PyObject *self)\r
+{\r
+ return PyCFunction_NewEx(ml, self, NULL);\r
+}\r
--- /dev/null
+\r
+/* Module object implementation */\r
+\r
+#include "Python.h"\r
+#include "structmember.h"\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyObject *md_dict;\r
+} PyModuleObject;\r
+\r
+static PyMemberDef module_members[] = {\r
+ {"__dict__", T_OBJECT, offsetof(PyModuleObject, md_dict), READONLY},\r
+ {0}\r
+};\r
+\r
+PyObject *\r
+PyModule_New(const char *name)\r
+{\r
+ PyModuleObject *m;\r
+ PyObject *nameobj;\r
+ m = PyObject_GC_New(PyModuleObject, &PyModule_Type);\r
+ if (m == NULL)\r
+ return NULL;\r
+ nameobj = PyString_FromString(name);\r
+ m->md_dict = PyDict_New();\r
+ if (m->md_dict == NULL || nameobj == NULL)\r
+ goto fail;\r
+ if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0)\r
+ goto fail;\r
+ if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) != 0)\r
+ goto fail;\r
+ if (PyDict_SetItemString(m->md_dict, "__package__", Py_None) != 0)\r
+ goto fail;\r
+ Py_DECREF(nameobj);\r
+ PyObject_GC_Track(m);\r
+ return (PyObject *)m;\r
+\r
+ fail:\r
+ Py_XDECREF(nameobj);\r
+ Py_DECREF(m);\r
+ return NULL;\r
+}\r
+\r
+PyObject *\r
+PyModule_GetDict(PyObject *m)\r
+{\r
+ PyObject *d;\r
+ if (!PyModule_Check(m)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ d = ((PyModuleObject *)m) -> md_dict;\r
+ if (d == NULL)\r
+ ((PyModuleObject *)m) -> md_dict = d = PyDict_New();\r
+ return d;\r
+}\r
+\r
+char *\r
+PyModule_GetName(PyObject *m)\r
+{\r
+ PyObject *d;\r
+ PyObject *nameobj;\r
+ if (!PyModule_Check(m)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ d = ((PyModuleObject *)m)->md_dict;\r
+ if (d == NULL ||\r
+ (nameobj = PyDict_GetItemString(d, "__name__")) == NULL ||\r
+ !PyString_Check(nameobj))\r
+ {\r
+ PyErr_SetString(PyExc_SystemError, "nameless module");\r
+ return NULL;\r
+ }\r
+ return PyString_AsString(nameobj);\r
+}\r
+\r
+char *\r
+PyModule_GetFilename(PyObject *m)\r
+{\r
+ PyObject *d;\r
+ PyObject *fileobj;\r
+ if (!PyModule_Check(m)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ d = ((PyModuleObject *)m)->md_dict;\r
+ if (d == NULL ||\r
+ (fileobj = PyDict_GetItemString(d, "__file__")) == NULL ||\r
+ !PyString_Check(fileobj))\r
+ {\r
+ PyErr_SetString(PyExc_SystemError, "module filename missing");\r
+ return NULL;\r
+ }\r
+ return PyString_AsString(fileobj);\r
+}\r
+\r
+void\r
+_PyModule_Clear(PyObject *m)\r
+{\r
+ /* To make the execution order of destructors for global\r
+ objects a bit more predictable, we first zap all objects\r
+ whose name starts with a single underscore, before we clear\r
+ the entire dictionary. We zap them by replacing them with\r
+ None, rather than deleting them from the dictionary, to\r
+ avoid rehashing the dictionary (to some extent). */\r
+\r
+ Py_ssize_t pos;\r
+ PyObject *key, *value;\r
+ PyObject *d;\r
+\r
+ d = ((PyModuleObject *)m)->md_dict;\r
+ if (d == NULL)\r
+ return;\r
+\r
+ /* First, clear only names starting with a single underscore */\r
+ pos = 0;\r
+ while (PyDict_Next(d, &pos, &key, &value)) {\r
+ if (value != Py_None && PyString_Check(key)) {\r
+ char *s = PyString_AsString(key);\r
+ if (s[0] == '_' && s[1] != '_') {\r
+ if (Py_VerboseFlag > 1)\r
+ PySys_WriteStderr("# clear[1] %s\n", s);\r
+ if (PyDict_SetItem(d, key, Py_None) != 0)\r
+ PyErr_Clear();\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Next, clear all names except for __builtins__ */\r
+ pos = 0;\r
+ while (PyDict_Next(d, &pos, &key, &value)) {\r
+ if (value != Py_None && PyString_Check(key)) {\r
+ char *s = PyString_AsString(key);\r
+ if (s[0] != '_' || strcmp(s, "__builtins__") != 0) {\r
+ if (Py_VerboseFlag > 1)\r
+ PySys_WriteStderr("# clear[2] %s\n", s);\r
+ if (PyDict_SetItem(d, key, Py_None) != 0)\r
+ PyErr_Clear();\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Note: we leave __builtins__ in place, so that destructors\r
+ of non-global objects defined in this module can still use\r
+ builtins, in particularly 'None'. */\r
+\r
+}\r
+\r
+/* Methods */\r
+\r
+static int\r
+module_init(PyModuleObject *m, PyObject *args, PyObject *kwds)\r
+{\r
+ static char *kwlist[] = {"name", "doc", NULL};\r
+ PyObject *dict, *name = Py_None, *doc = Py_None;\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|O:module.__init__",\r
+ kwlist, &name, &doc))\r
+ return -1;\r
+ dict = m->md_dict;\r
+ if (dict == NULL) {\r
+ dict = PyDict_New();\r
+ if (dict == NULL)\r
+ return -1;\r
+ m->md_dict = dict;\r
+ }\r
+ if (PyDict_SetItemString(dict, "__name__", name) < 0)\r
+ return -1;\r
+ if (PyDict_SetItemString(dict, "__doc__", doc) < 0)\r
+ return -1;\r
+ return 0;\r
+}\r
+\r
+static void\r
+module_dealloc(PyModuleObject *m)\r
+{\r
+ PyObject_GC_UnTrack(m);\r
+ if (m->md_dict != NULL) {\r
+ _PyModule_Clear((PyObject *)m);\r
+ Py_DECREF(m->md_dict);\r
+ }\r
+ Py_TYPE(m)->tp_free((PyObject *)m);\r
+}\r
+\r
+static PyObject *\r
+module_repr(PyModuleObject *m)\r
+{\r
+ char *name;\r
+ char *filename;\r
+\r
+ name = PyModule_GetName((PyObject *)m);\r
+ if (name == NULL) {\r
+ PyErr_Clear();\r
+ name = "?";\r
+ }\r
+ filename = PyModule_GetFilename((PyObject *)m);\r
+ if (filename == NULL) {\r
+ PyErr_Clear();\r
+ return PyString_FromFormat("<module '%s' (built-in)>", name);\r
+ }\r
+ return PyString_FromFormat("<module '%s' from '%s'>", name, filename);\r
+}\r
+\r
+/* We only need a traverse function, no clear function: If the module\r
+ is in a cycle, md_dict will be cleared as well, which will break\r
+ the cycle. */\r
+static int\r
+module_traverse(PyModuleObject *m, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(m->md_dict);\r
+ return 0;\r
+}\r
+\r
+PyDoc_STRVAR(module_doc,\r
+"module(name[, doc])\n\\r
+\n\\r
+Create a module object.\n\\r
+The name must be a string; the optional doc argument can have any type.");\r
+\r
+PyTypeObject PyModule_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "module", /* tp_name */\r
+ sizeof(PyModuleObject), /* tp_size */\r
+ 0, /* tp_itemsize */\r
+ (destructor)module_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)module_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ PyObject_GenericSetAttr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ module_doc, /* tp_doc */\r
+ (traverseproc)module_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ module_members, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ offsetof(PyModuleObject, md_dict), /* tp_dictoffset */\r
+ (initproc)module_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ PyType_GenericNew, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
--- /dev/null
+\r
+/* Generic object operations; and implementation of None (NoObject) */\r
+\r
+#include "Python.h"\r
+#include "frameobject.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#ifdef Py_REF_DEBUG\r
+Py_ssize_t _Py_RefTotal;\r
+\r
+Py_ssize_t\r
+_Py_GetRefTotal(void)\r
+{\r
+ PyObject *o;\r
+ Py_ssize_t total = _Py_RefTotal;\r
+ /* ignore the references to the dummy object of the dicts and sets\r
+ because they are not reliable and not useful (now that the\r
+ hash table code is well-tested) */\r
+ o = _PyDict_Dummy();\r
+ if (o != NULL)\r
+ total -= o->ob_refcnt;\r
+ o = _PySet_Dummy();\r
+ if (o != NULL)\r
+ total -= o->ob_refcnt;\r
+ return total;\r
+}\r
+#endif /* Py_REF_DEBUG */\r
+\r
+int Py_DivisionWarningFlag;\r
+int Py_Py3kWarningFlag;\r
+\r
+/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.\r
+ These are used by the individual routines for object creation.\r
+ Do not call them otherwise, they do not initialize the object! */\r
+\r
+#ifdef Py_TRACE_REFS\r
+/* Head of circular doubly-linked list of all objects. These are linked\r
+ * together via the _ob_prev and _ob_next members of a PyObject, which\r
+ * exist only in a Py_TRACE_REFS build.\r
+ */\r
+static PyObject refchain = {&refchain, &refchain};\r
+\r
+/* Insert op at the front of the list of all objects. If force is true,\r
+ * op is added even if _ob_prev and _ob_next are non-NULL already. If\r
+ * force is false amd _ob_prev or _ob_next are non-NULL, do nothing.\r
+ * force should be true if and only if op points to freshly allocated,\r
+ * uninitialized memory, or you've unlinked op from the list and are\r
+ * relinking it into the front.\r
+ * Note that objects are normally added to the list via _Py_NewReference,\r
+ * which is called by PyObject_Init. Not all objects are initialized that\r
+ * way, though; exceptions include statically allocated type objects, and\r
+ * statically allocated singletons (like Py_True and Py_None).\r
+ */\r
+void\r
+_Py_AddToAllObjects(PyObject *op, int force)\r
+{\r
+#ifdef Py_DEBUG\r
+ if (!force) {\r
+ /* If it's initialized memory, op must be in or out of\r
+ * the list unambiguously.\r
+ */\r
+ assert((op->_ob_prev == NULL) == (op->_ob_next == NULL));\r
+ }\r
+#endif\r
+ if (force || op->_ob_prev == NULL) {\r
+ op->_ob_next = refchain._ob_next;\r
+ op->_ob_prev = &refchain;\r
+ refchain._ob_next->_ob_prev = op;\r
+ refchain._ob_next = op;\r
+ }\r
+}\r
+#endif /* Py_TRACE_REFS */\r
+\r
+#ifdef COUNT_ALLOCS\r
+static PyTypeObject *type_list;\r
+/* All types are added to type_list, at least when\r
+ they get one object created. That makes them\r
+ immortal, which unfortunately contributes to\r
+ garbage itself. If unlist_types_without_objects\r
+ is set, they will be removed from the type_list\r
+ once the last object is deallocated. */\r
+static int unlist_types_without_objects;\r
+extern Py_ssize_t tuple_zero_allocs, fast_tuple_allocs;\r
+extern Py_ssize_t quick_int_allocs, quick_neg_int_allocs;\r
+extern Py_ssize_t null_strings, one_strings;\r
+void\r
+dump_counts(FILE* f)\r
+{\r
+ PyTypeObject *tp;\r
+\r
+ for (tp = type_list; tp; tp = tp->tp_next)\r
+ fprintf(f, "%s alloc'd: %" PY_FORMAT_SIZE_T "d, "\r
+ "freed: %" PY_FORMAT_SIZE_T "d, "\r
+ "max in use: %" PY_FORMAT_SIZE_T "d\n",\r
+ tp->tp_name, tp->tp_allocs, tp->tp_frees,\r
+ tp->tp_maxalloc);\r
+ fprintf(f, "fast tuple allocs: %" PY_FORMAT_SIZE_T "d, "\r
+ "empty: %" PY_FORMAT_SIZE_T "d\n",\r
+ fast_tuple_allocs, tuple_zero_allocs);\r
+ fprintf(f, "fast int allocs: pos: %" PY_FORMAT_SIZE_T "d, "\r
+ "neg: %" PY_FORMAT_SIZE_T "d\n",\r
+ quick_int_allocs, quick_neg_int_allocs);\r
+ fprintf(f, "null strings: %" PY_FORMAT_SIZE_T "d, "\r
+ "1-strings: %" PY_FORMAT_SIZE_T "d\n",\r
+ null_strings, one_strings);\r
+}\r
+\r
+PyObject *\r
+get_counts(void)\r
+{\r
+ PyTypeObject *tp;\r
+ PyObject *result;\r
+ PyObject *v;\r
+\r
+ result = PyList_New(0);\r
+ if (result == NULL)\r
+ return NULL;\r
+ for (tp = type_list; tp; tp = tp->tp_next) {\r
+ v = Py_BuildValue("(snnn)", tp->tp_name, tp->tp_allocs,\r
+ tp->tp_frees, tp->tp_maxalloc);\r
+ if (v == NULL) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ if (PyList_Append(result, v) < 0) {\r
+ Py_DECREF(v);\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ Py_DECREF(v);\r
+ }\r
+ return result;\r
+}\r
+\r
+void\r
+inc_count(PyTypeObject *tp)\r
+{\r
+ if (tp->tp_next == NULL && tp->tp_prev == NULL) {\r
+ /* first time; insert in linked list */\r
+ if (tp->tp_next != NULL) /* sanity check */\r
+ Py_FatalError("XXX inc_count sanity check");\r
+ if (type_list)\r
+ type_list->tp_prev = tp;\r
+ tp->tp_next = type_list;\r
+ /* Note that as of Python 2.2, heap-allocated type objects\r
+ * can go away, but this code requires that they stay alive\r
+ * until program exit. That's why we're careful with\r
+ * refcounts here. type_list gets a new reference to tp,\r
+ * while ownership of the reference type_list used to hold\r
+ * (if any) was transferred to tp->tp_next in the line above.\r
+ * tp is thus effectively immortal after this.\r
+ */\r
+ Py_INCREF(tp);\r
+ type_list = tp;\r
+#ifdef Py_TRACE_REFS\r
+ /* Also insert in the doubly-linked list of all objects,\r
+ * if not already there.\r
+ */\r
+ _Py_AddToAllObjects((PyObject *)tp, 0);\r
+#endif\r
+ }\r
+ tp->tp_allocs++;\r
+ if (tp->tp_allocs - tp->tp_frees > tp->tp_maxalloc)\r
+ tp->tp_maxalloc = tp->tp_allocs - tp->tp_frees;\r
+}\r
+\r
+void dec_count(PyTypeObject *tp)\r
+{\r
+ tp->tp_frees++;\r
+ if (unlist_types_without_objects &&\r
+ tp->tp_allocs == tp->tp_frees) {\r
+ /* unlink the type from type_list */\r
+ if (tp->tp_prev)\r
+ tp->tp_prev->tp_next = tp->tp_next;\r
+ else\r
+ type_list = tp->tp_next;\r
+ if (tp->tp_next)\r
+ tp->tp_next->tp_prev = tp->tp_prev;\r
+ tp->tp_next = tp->tp_prev = NULL;\r
+ Py_DECREF(tp);\r
+ }\r
+}\r
+\r
+#endif\r
+\r
+#ifdef Py_REF_DEBUG\r
+/* Log a fatal error; doesn't return. */\r
+void\r
+_Py_NegativeRefcount(const char *fname, int lineno, PyObject *op)\r
+{\r
+ char buf[300];\r
+\r
+ PyOS_snprintf(buf, sizeof(buf),\r
+ "%s:%i object at %p has negative ref count "\r
+ "%" PY_FORMAT_SIZE_T "d",\r
+ fname, lineno, op, op->ob_refcnt);\r
+ Py_FatalError(buf);\r
+}\r
+\r
+#endif /* Py_REF_DEBUG */\r
+\r
+void\r
+Py_IncRef(PyObject *o)\r
+{\r
+ Py_XINCREF(o);\r
+}\r
+\r
+void\r
+Py_DecRef(PyObject *o)\r
+{\r
+ Py_XDECREF(o);\r
+}\r
+\r
+PyObject *\r
+PyObject_Init(PyObject *op, PyTypeObject *tp)\r
+{\r
+ if (op == NULL)\r
+ return PyErr_NoMemory();\r
+ /* Any changes should be reflected in PyObject_INIT (objimpl.h) */\r
+ Py_TYPE(op) = tp;\r
+ _Py_NewReference(op);\r
+ return op;\r
+}\r
+\r
+PyVarObject *\r
+PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)\r
+{\r
+ if (op == NULL)\r
+ return (PyVarObject *) PyErr_NoMemory();\r
+ /* Any changes should be reflected in PyObject_INIT_VAR */\r
+ op->ob_size = size;\r
+ Py_TYPE(op) = tp;\r
+ _Py_NewReference((PyObject *)op);\r
+ return op;\r
+}\r
+\r
+PyObject *\r
+_PyObject_New(PyTypeObject *tp)\r
+{\r
+ PyObject *op;\r
+ op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));\r
+ if (op == NULL)\r
+ return PyErr_NoMemory();\r
+ return PyObject_INIT(op, tp);\r
+}\r
+\r
+PyVarObject *\r
+_PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems)\r
+{\r
+ PyVarObject *op;\r
+ const size_t size = _PyObject_VAR_SIZE(tp, nitems);\r
+ op = (PyVarObject *) PyObject_MALLOC(size);\r
+ if (op == NULL)\r
+ return (PyVarObject *)PyErr_NoMemory();\r
+ return PyObject_INIT_VAR(op, tp, nitems);\r
+}\r
+\r
+/* for binary compatibility with 2.2 */\r
+#undef _PyObject_Del\r
+void\r
+_PyObject_Del(PyObject *op)\r
+{\r
+ PyObject_FREE(op);\r
+}\r
+\r
+/* Implementation of PyObject_Print with recursion checking */\r
+static int\r
+internal_print(PyObject *op, FILE *fp, int flags, int nesting)\r
+{\r
+ int ret = 0;\r
+ if (nesting > 10) {\r
+ PyErr_SetString(PyExc_RuntimeError, "print recursion");\r
+ return -1;\r
+ }\r
+ if (PyErr_CheckSignals())\r
+ return -1;\r
+#ifdef USE_STACKCHECK\r
+ if (PyOS_CheckStack()) {\r
+ PyErr_SetString(PyExc_MemoryError, "stack overflow");\r
+ return -1;\r
+ }\r
+#endif\r
+ clearerr(fp); /* Clear any previous error condition */\r
+ if (op == NULL) {\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "<nil>");\r
+ Py_END_ALLOW_THREADS\r
+ }\r
+ else {\r
+ if (op->ob_refcnt <= 0)\r
+ /* XXX(twouters) cast refcount to long until %zd is\r
+ universally available */\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "<refcnt %ld at %p>",\r
+ (long)op->ob_refcnt, op);\r
+ Py_END_ALLOW_THREADS\r
+ else if (Py_TYPE(op)->tp_print == NULL) {\r
+ PyObject *s;\r
+ if (flags & Py_PRINT_RAW)\r
+ s = PyObject_Str(op);\r
+ else\r
+ s = PyObject_Repr(op);\r
+ if (s == NULL)\r
+ ret = -1;\r
+ else {\r
+ ret = internal_print(s, fp, Py_PRINT_RAW,\r
+ nesting+1);\r
+ }\r
+ Py_XDECREF(s);\r
+ }\r
+ else\r
+ ret = (*Py_TYPE(op)->tp_print)(op, fp, flags);\r
+ }\r
+ if (ret == 0) {\r
+ if (ferror(fp)) {\r
+ PyErr_SetFromErrno(PyExc_IOError);\r
+ clearerr(fp);\r
+ ret = -1;\r
+ }\r
+ }\r
+ return ret;\r
+}\r
+\r
+int\r
+PyObject_Print(PyObject *op, FILE *fp, int flags)\r
+{\r
+ return internal_print(op, fp, flags, 0);\r
+}\r
+\r
+\r
+/* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */\r
+void _PyObject_Dump(PyObject* op)\r
+{\r
+ if (op == NULL)\r
+ fprintf(stderr, "NULL\n");\r
+ else {\r
+#ifdef WITH_THREAD\r
+ PyGILState_STATE gil;\r
+#endif\r
+ fprintf(stderr, "object : ");\r
+#ifdef WITH_THREAD\r
+ gil = PyGILState_Ensure();\r
+#endif\r
+ (void)PyObject_Print(op, stderr, 0);\r
+#ifdef WITH_THREAD\r
+ PyGILState_Release(gil);\r
+#endif\r
+ /* XXX(twouters) cast refcount to long until %zd is\r
+ universally available */\r
+ fprintf(stderr, "\n"\r
+ "type : %s\n"\r
+ "refcount: %ld\n"\r
+ "address : %p\n",\r
+ Py_TYPE(op)==NULL ? "NULL" : Py_TYPE(op)->tp_name,\r
+ (long)op->ob_refcnt,\r
+ op);\r
+ }\r
+}\r
+\r
+PyObject *\r
+PyObject_Repr(PyObject *v)\r
+{\r
+ if (PyErr_CheckSignals())\r
+ return NULL;\r
+#ifdef USE_STACKCHECK\r
+ if (PyOS_CheckStack()) {\r
+ PyErr_SetString(PyExc_MemoryError, "stack overflow");\r
+ return NULL;\r
+ }\r
+#endif\r
+ if (v == NULL)\r
+ return PyString_FromString("<NULL>");\r
+ else if (Py_TYPE(v)->tp_repr == NULL)\r
+ return PyString_FromFormat("<%s object at %p>",\r
+ Py_TYPE(v)->tp_name, v);\r
+ else {\r
+ PyObject *res;\r
+ res = (*Py_TYPE(v)->tp_repr)(v);\r
+ if (res == NULL)\r
+ return NULL;\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(res)) {\r
+ PyObject* str;\r
+ str = PyUnicode_AsEncodedString(res, NULL, NULL);\r
+ Py_DECREF(res);\r
+ if (str)\r
+ res = str;\r
+ else\r
+ return NULL;\r
+ }\r
+#endif\r
+ if (!PyString_Check(res)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__repr__ returned non-string (type %.200s)",\r
+ Py_TYPE(res)->tp_name);\r
+ Py_DECREF(res);\r
+ return NULL;\r
+ }\r
+ return res;\r
+ }\r
+}\r
+\r
+PyObject *\r
+_PyObject_Str(PyObject *v)\r
+{\r
+ PyObject *res;\r
+ int type_ok;\r
+ if (v == NULL)\r
+ return PyString_FromString("<NULL>");\r
+ if (PyString_CheckExact(v)) {\r
+ Py_INCREF(v);\r
+ return v;\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_CheckExact(v)) {\r
+ Py_INCREF(v);\r
+ return v;\r
+ }\r
+#endif\r
+ if (Py_TYPE(v)->tp_str == NULL)\r
+ return PyObject_Repr(v);\r
+\r
+ /* It is possible for a type to have a tp_str representation that loops\r
+ infinitely. */\r
+ if (Py_EnterRecursiveCall(" while getting the str of an object"))\r
+ return NULL;\r
+ res = (*Py_TYPE(v)->tp_str)(v);\r
+ Py_LeaveRecursiveCall();\r
+ if (res == NULL)\r
+ return NULL;\r
+ type_ok = PyString_Check(res);\r
+#ifdef Py_USING_UNICODE\r
+ type_ok = type_ok || PyUnicode_Check(res);\r
+#endif\r
+ if (!type_ok) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__str__ returned non-string (type %.200s)",\r
+ Py_TYPE(res)->tp_name);\r
+ Py_DECREF(res);\r
+ return NULL;\r
+ }\r
+ return res;\r
+}\r
+\r
+PyObject *\r
+PyObject_Str(PyObject *v)\r
+{\r
+ PyObject *res = _PyObject_Str(v);\r
+ if (res == NULL)\r
+ return NULL;\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(res)) {\r
+ PyObject* str;\r
+ str = PyUnicode_AsEncodedString(res, NULL, NULL);\r
+ Py_DECREF(res);\r
+ if (str)\r
+ res = str;\r
+ else\r
+ return NULL;\r
+ }\r
+#endif\r
+ assert(PyString_Check(res));\r
+ return res;\r
+}\r
+\r
+#ifdef Py_USING_UNICODE\r
+PyObject *\r
+PyObject_Unicode(PyObject *v)\r
+{\r
+ PyObject *res;\r
+ PyObject *func;\r
+ PyObject *str;\r
+ int unicode_method_found = 0;\r
+ static PyObject *unicodestr = NULL;\r
+\r
+ if (v == NULL) {\r
+ res = PyString_FromString("<NULL>");\r
+ if (res == NULL)\r
+ return NULL;\r
+ str = PyUnicode_FromEncodedObject(res, NULL, "strict");\r
+ Py_DECREF(res);\r
+ return str;\r
+ } else if (PyUnicode_CheckExact(v)) {\r
+ Py_INCREF(v);\r
+ return v;\r
+ }\r
+\r
+ if (PyInstance_Check(v)) {\r
+ /* We're an instance of a classic class */\r
+ /* Try __unicode__ from the instance -- alas we have no type */\r
+ if (!unicodestr) {\r
+ unicodestr = PyString_InternFromString("__unicode__");\r
+ if (!unicodestr)\r
+ return NULL;\r
+ }\r
+ func = PyObject_GetAttr(v, unicodestr);\r
+ if (func != NULL) {\r
+ unicode_method_found = 1;\r
+ res = PyObject_CallFunctionObjArgs(func, NULL);\r
+ Py_DECREF(func);\r
+ }\r
+ else {\r
+ PyErr_Clear();\r
+ }\r
+ }\r
+ else {\r
+ /* Not a classic class instance, try __unicode__. */\r
+ func = _PyObject_LookupSpecial(v, "__unicode__", &unicodestr);\r
+ if (func != NULL) {\r
+ unicode_method_found = 1;\r
+ res = PyObject_CallFunctionObjArgs(func, NULL);\r
+ Py_DECREF(func);\r
+ }\r
+ else if (PyErr_Occurred())\r
+ return NULL;\r
+ }\r
+\r
+ /* Didn't find __unicode__ */\r
+ if (!unicode_method_found) {\r
+ if (PyUnicode_Check(v)) {\r
+ /* For a Unicode subtype that's didn't overwrite __unicode__,\r
+ return a true Unicode object with the same data. */\r
+ return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(v),\r
+ PyUnicode_GET_SIZE(v));\r
+ }\r
+ if (PyString_CheckExact(v)) {\r
+ Py_INCREF(v);\r
+ res = v;\r
+ }\r
+ else {\r
+ if (Py_TYPE(v)->tp_str != NULL)\r
+ res = (*Py_TYPE(v)->tp_str)(v);\r
+ else\r
+ res = PyObject_Repr(v);\r
+ }\r
+ }\r
+\r
+ if (res == NULL)\r
+ return NULL;\r
+ if (!PyUnicode_Check(res)) {\r
+ str = PyUnicode_FromEncodedObject(res, NULL, "strict");\r
+ Py_DECREF(res);\r
+ res = str;\r
+ }\r
+ return res;\r
+}\r
+#endif\r
+\r
+\r
+/* Helper to warn about deprecated tp_compare return values. Return:\r
+ -2 for an exception;\r
+ -1 if v < w;\r
+ 0 if v == w;\r
+ 1 if v > w.\r
+ (This function cannot return 2.)\r
+*/\r
+static int\r
+adjust_tp_compare(int c)\r
+{\r
+ if (PyErr_Occurred()) {\r
+ if (c != -1 && c != -2) {\r
+ PyObject *t, *v, *tb;\r
+ PyErr_Fetch(&t, &v, &tb);\r
+ if (PyErr_Warn(PyExc_RuntimeWarning,\r
+ "tp_compare didn't return -1 or -2 "\r
+ "for exception") < 0) {\r
+ Py_XDECREF(t);\r
+ Py_XDECREF(v);\r
+ Py_XDECREF(tb);\r
+ }\r
+ else\r
+ PyErr_Restore(t, v, tb);\r
+ }\r
+ return -2;\r
+ }\r
+ else if (c < -1 || c > 1) {\r
+ if (PyErr_Warn(PyExc_RuntimeWarning,\r
+ "tp_compare didn't return -1, 0 or 1") < 0)\r
+ return -2;\r
+ else\r
+ return c < -1 ? -1 : 1;\r
+ }\r
+ else {\r
+ assert(c >= -1 && c <= 1);\r
+ return c;\r
+ }\r
+}\r
+\r
+\r
+/* Macro to get the tp_richcompare field of a type if defined */\r
+#define RICHCOMPARE(t) (PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE) \\r
+ ? (t)->tp_richcompare : NULL)\r
+\r
+/* Map rich comparison operators to their swapped version, e.g. LT --> GT */\r
+int _Py_SwappedOp[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};\r
+\r
+/* Try a genuine rich comparison, returning an object. Return:\r
+ NULL for exception;\r
+ NotImplemented if this particular rich comparison is not implemented or\r
+ undefined;\r
+ some object not equal to NotImplemented if it is implemented\r
+ (this latter object may not be a Boolean).\r
+*/\r
+static PyObject *\r
+try_rich_compare(PyObject *v, PyObject *w, int op)\r
+{\r
+ richcmpfunc f;\r
+ PyObject *res;\r
+\r
+ if (v->ob_type != w->ob_type &&\r
+ PyType_IsSubtype(w->ob_type, v->ob_type) &&\r
+ (f = RICHCOMPARE(w->ob_type)) != NULL) {\r
+ res = (*f)(w, v, _Py_SwappedOp[op]);\r
+ if (res != Py_NotImplemented)\r
+ return res;\r
+ Py_DECREF(res);\r
+ }\r
+ if ((f = RICHCOMPARE(v->ob_type)) != NULL) {\r
+ res = (*f)(v, w, op);\r
+ if (res != Py_NotImplemented)\r
+ return res;\r
+ Py_DECREF(res);\r
+ }\r
+ if ((f = RICHCOMPARE(w->ob_type)) != NULL) {\r
+ return (*f)(w, v, _Py_SwappedOp[op]);\r
+ }\r
+ res = Py_NotImplemented;\r
+ Py_INCREF(res);\r
+ return res;\r
+}\r
+\r
+/* Try a genuine rich comparison, returning an int. Return:\r
+ -1 for exception (including the case where try_rich_compare() returns an\r
+ object that's not a Boolean);\r
+ 0 if the outcome is false;\r
+ 1 if the outcome is true;\r
+ 2 if this particular rich comparison is not implemented or undefined.\r
+*/\r
+static int\r
+try_rich_compare_bool(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyObject *res;\r
+ int ok;\r
+\r
+ if (RICHCOMPARE(v->ob_type) == NULL && RICHCOMPARE(w->ob_type) == NULL)\r
+ return 2; /* Shortcut, avoid INCREF+DECREF */\r
+ res = try_rich_compare(v, w, op);\r
+ if (res == NULL)\r
+ return -1;\r
+ if (res == Py_NotImplemented) {\r
+ Py_DECREF(res);\r
+ return 2;\r
+ }\r
+ ok = PyObject_IsTrue(res);\r
+ Py_DECREF(res);\r
+ return ok;\r
+}\r
+\r
+/* Try rich comparisons to determine a 3-way comparison. Return:\r
+ -2 for an exception;\r
+ -1 if v < w;\r
+ 0 if v == w;\r
+ 1 if v > w;\r
+ 2 if this particular rich comparison is not implemented or undefined.\r
+*/\r
+static int\r
+try_rich_to_3way_compare(PyObject *v, PyObject *w)\r
+{\r
+ static struct { int op; int outcome; } tries[3] = {\r
+ /* Try this operator, and if it is true, use this outcome: */\r
+ {Py_EQ, 0},\r
+ {Py_LT, -1},\r
+ {Py_GT, 1},\r
+ };\r
+ int i;\r
+\r
+ if (RICHCOMPARE(v->ob_type) == NULL && RICHCOMPARE(w->ob_type) == NULL)\r
+ return 2; /* Shortcut */\r
+\r
+ for (i = 0; i < 3; i++) {\r
+ switch (try_rich_compare_bool(v, w, tries[i].op)) {\r
+ case -1:\r
+ return -2;\r
+ case 1:\r
+ return tries[i].outcome;\r
+ }\r
+ }\r
+\r
+ return 2;\r
+}\r
+\r
+/* Try a 3-way comparison, returning an int. Return:\r
+ -2 for an exception;\r
+ -1 if v < w;\r
+ 0 if v == w;\r
+ 1 if v > w;\r
+ 2 if this particular 3-way comparison is not implemented or undefined.\r
+*/\r
+static int\r
+try_3way_compare(PyObject *v, PyObject *w)\r
+{\r
+ int c;\r
+ cmpfunc f;\r
+\r
+ /* Comparisons involving instances are given to instance_compare,\r
+ which has the same return conventions as this function. */\r
+\r
+ f = v->ob_type->tp_compare;\r
+ if (PyInstance_Check(v))\r
+ return (*f)(v, w);\r
+ if (PyInstance_Check(w))\r
+ return (*w->ob_type->tp_compare)(v, w);\r
+\r
+ /* If both have the same (non-NULL) tp_compare, use it. */\r
+ if (f != NULL && f == w->ob_type->tp_compare) {\r
+ c = (*f)(v, w);\r
+ return adjust_tp_compare(c);\r
+ }\r
+\r
+ /* If either tp_compare is _PyObject_SlotCompare, that's safe. */\r
+ if (f == _PyObject_SlotCompare ||\r
+ w->ob_type->tp_compare == _PyObject_SlotCompare)\r
+ return _PyObject_SlotCompare(v, w);\r
+\r
+ /* If we're here, v and w,\r
+ a) are not instances;\r
+ b) have different types or a type without tp_compare; and\r
+ c) don't have a user-defined tp_compare.\r
+ tp_compare implementations in C assume that both arguments\r
+ have their type, so we give up if the coercion fails or if\r
+ it yields types which are still incompatible (which can\r
+ happen with a user-defined nb_coerce).\r
+ */\r
+ c = PyNumber_CoerceEx(&v, &w);\r
+ if (c < 0)\r
+ return -2;\r
+ if (c > 0)\r
+ return 2;\r
+ f = v->ob_type->tp_compare;\r
+ if (f != NULL && f == w->ob_type->tp_compare) {\r
+ c = (*f)(v, w);\r
+ Py_DECREF(v);\r
+ Py_DECREF(w);\r
+ return adjust_tp_compare(c);\r
+ }\r
+\r
+ /* No comparison defined */\r
+ Py_DECREF(v);\r
+ Py_DECREF(w);\r
+ return 2;\r
+}\r
+\r
+/* Final fallback 3-way comparison, returning an int. Return:\r
+ -2 if an error occurred;\r
+ -1 if v < w;\r
+ 0 if v == w;\r
+ 1 if v > w.\r
+*/\r
+static int\r
+default_3way_compare(PyObject *v, PyObject *w)\r
+{\r
+ int c;\r
+ const char *vname, *wname;\r
+\r
+ if (v->ob_type == w->ob_type) {\r
+ /* When comparing these pointers, they must be cast to\r
+ * integer types (i.e. Py_uintptr_t, our spelling of C9X's\r
+ * uintptr_t). ANSI specifies that pointer compares other\r
+ * than == and != to non-related structures are undefined.\r
+ */\r
+ Py_uintptr_t vv = (Py_uintptr_t)v;\r
+ Py_uintptr_t ww = (Py_uintptr_t)w;\r
+ return (vv < ww) ? -1 : (vv > ww) ? 1 : 0;\r
+ }\r
+\r
+ /* None is smaller than anything */\r
+ if (v == Py_None)\r
+ return -1;\r
+ if (w == Py_None)\r
+ return 1;\r
+\r
+ /* different type: compare type names; numbers are smaller */\r
+ if (PyNumber_Check(v))\r
+ vname = "";\r
+ else\r
+ vname = v->ob_type->tp_name;\r
+ if (PyNumber_Check(w))\r
+ wname = "";\r
+ else\r
+ wname = w->ob_type->tp_name;\r
+ c = strcmp(vname, wname);\r
+ if (c < 0)\r
+ return -1;\r
+ if (c > 0)\r
+ return 1;\r
+ /* Same type name, or (more likely) incomparable numeric types */\r
+ return ((Py_uintptr_t)(v->ob_type) < (\r
+ Py_uintptr_t)(w->ob_type)) ? -1 : 1;\r
+}\r
+\r
+/* Do a 3-way comparison, by hook or by crook. Return:\r
+ -2 for an exception (but see below);\r
+ -1 if v < w;\r
+ 0 if v == w;\r
+ 1 if v > w;\r
+ BUT: if the object implements a tp_compare function, it returns\r
+ whatever this function returns (whether with an exception or not).\r
+*/\r
+static int\r
+do_cmp(PyObject *v, PyObject *w)\r
+{\r
+ int c;\r
+ cmpfunc f;\r
+\r
+ if (v->ob_type == w->ob_type\r
+ && (f = v->ob_type->tp_compare) != NULL) {\r
+ c = (*f)(v, w);\r
+ if (PyInstance_Check(v)) {\r
+ /* Instance tp_compare has a different signature.\r
+ But if it returns undefined we fall through. */\r
+ if (c != 2)\r
+ return c;\r
+ /* Else fall through to try_rich_to_3way_compare() */\r
+ }\r
+ else\r
+ return adjust_tp_compare(c);\r
+ }\r
+ /* We only get here if one of the following is true:\r
+ a) v and w have different types\r
+ b) v and w have the same type, which doesn't have tp_compare\r
+ c) v and w are instances, and either __cmp__ is not defined or\r
+ __cmp__ returns NotImplemented\r
+ */\r
+ c = try_rich_to_3way_compare(v, w);\r
+ if (c < 2)\r
+ return c;\r
+ c = try_3way_compare(v, w);\r
+ if (c < 2)\r
+ return c;\r
+ return default_3way_compare(v, w);\r
+}\r
+\r
+/* Compare v to w. Return\r
+ -1 if v < w or exception (PyErr_Occurred() true in latter case).\r
+ 0 if v == w.\r
+ 1 if v > w.\r
+ XXX The docs (C API manual) say the return value is undefined in case\r
+ XXX of error.\r
+*/\r
+int\r
+PyObject_Compare(PyObject *v, PyObject *w)\r
+{\r
+ int result;\r
+\r
+ if (v == NULL || w == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ if (v == w)\r
+ return 0;\r
+ if (Py_EnterRecursiveCall(" in cmp"))\r
+ return -1;\r
+ result = do_cmp(v, w);\r
+ Py_LeaveRecursiveCall();\r
+ return result < 0 ? -1 : result;\r
+}\r
+\r
+/* Return (new reference to) Py_True or Py_False. */\r
+static PyObject *\r
+convert_3way_to_object(int op, int c)\r
+{\r
+ PyObject *result;\r
+ switch (op) {\r
+ case Py_LT: c = c < 0; break;\r
+ case Py_LE: c = c <= 0; break;\r
+ case Py_EQ: c = c == 0; break;\r
+ case Py_NE: c = c != 0; break;\r
+ case Py_GT: c = c > 0; break;\r
+ case Py_GE: c = c >= 0; break;\r
+ }\r
+ result = c ? Py_True : Py_False;\r
+ Py_INCREF(result);\r
+ return result;\r
+}\r
+\r
+/* We want a rich comparison but don't have one. Try a 3-way cmp instead.\r
+ Return\r
+ NULL if error\r
+ Py_True if v op w\r
+ Py_False if not (v op w)\r
+*/\r
+static PyObject *\r
+try_3way_to_rich_compare(PyObject *v, PyObject *w, int op)\r
+{\r
+ int c;\r
+\r
+ c = try_3way_compare(v, w);\r
+ if (c >= 2) {\r
+\r
+ /* Py3K warning if types are not equal and comparison isn't == or != */\r
+ if (Py_Py3kWarningFlag &&\r
+ v->ob_type != w->ob_type && op != Py_EQ && op != Py_NE &&\r
+ PyErr_WarnEx(PyExc_DeprecationWarning,\r
+ "comparing unequal types not supported "\r
+ "in 3.x", 1) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ c = default_3way_compare(v, w);\r
+ }\r
+ if (c <= -2)\r
+ return NULL;\r
+ return convert_3way_to_object(op, c);\r
+}\r
+\r
+/* Do rich comparison on v and w. Return\r
+ NULL if error\r
+ Else a new reference to an object other than Py_NotImplemented, usually(?):\r
+ Py_True if v op w\r
+ Py_False if not (v op w)\r
+*/\r
+static PyObject *\r
+do_richcmp(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyObject *res;\r
+\r
+ res = try_rich_compare(v, w, op);\r
+ if (res != Py_NotImplemented)\r
+ return res;\r
+ Py_DECREF(res);\r
+\r
+ return try_3way_to_rich_compare(v, w, op);\r
+}\r
+\r
+/* Return:\r
+ NULL for exception;\r
+ some object not equal to NotImplemented if it is implemented\r
+ (this latter object may not be a Boolean).\r
+*/\r
+PyObject *\r
+PyObject_RichCompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyObject *res;\r
+\r
+ assert(Py_LT <= op && op <= Py_GE);\r
+ if (Py_EnterRecursiveCall(" in cmp"))\r
+ return NULL;\r
+\r
+ /* If the types are equal, and not old-style instances, try to\r
+ get out cheap (don't bother with coercions etc.). */\r
+ if (v->ob_type == w->ob_type && !PyInstance_Check(v)) {\r
+ cmpfunc fcmp;\r
+ richcmpfunc frich = RICHCOMPARE(v->ob_type);\r
+ /* If the type has richcmp, try it first. try_rich_compare\r
+ tries it two-sided, which is not needed since we've a\r
+ single type only. */\r
+ if (frich != NULL) {\r
+ res = (*frich)(v, w, op);\r
+ if (res != Py_NotImplemented)\r
+ goto Done;\r
+ Py_DECREF(res);\r
+ }\r
+ /* No richcmp, or this particular richmp not implemented.\r
+ Try 3-way cmp. */\r
+ fcmp = v->ob_type->tp_compare;\r
+ if (fcmp != NULL) {\r
+ int c = (*fcmp)(v, w);\r
+ c = adjust_tp_compare(c);\r
+ if (c == -2) {\r
+ res = NULL;\r
+ goto Done;\r
+ }\r
+ res = convert_3way_to_object(op, c);\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ /* Fast path not taken, or couldn't deliver a useful result. */\r
+ res = do_richcmp(v, w, op);\r
+Done:\r
+ Py_LeaveRecursiveCall();\r
+ return res;\r
+}\r
+\r
+/* Return -1 if error; 1 if v op w; 0 if not (v op w). */\r
+int\r
+PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyObject *res;\r
+ int ok;\r
+\r
+ /* Quick result when objects are the same.\r
+ Guarantees that identity implies equality. */\r
+ if (v == w) {\r
+ if (op == Py_EQ)\r
+ return 1;\r
+ else if (op == Py_NE)\r
+ return 0;\r
+ }\r
+\r
+ res = PyObject_RichCompare(v, w, op);\r
+ if (res == NULL)\r
+ return -1;\r
+ if (PyBool_Check(res))\r
+ ok = (res == Py_True);\r
+ else\r
+ ok = PyObject_IsTrue(res);\r
+ Py_DECREF(res);\r
+ return ok;\r
+}\r
+\r
+/* Set of hash utility functions to help maintaining the invariant that\r
+ if a==b then hash(a)==hash(b)\r
+\r
+ All the utility functions (_Py_Hash*()) return "-1" to signify an error.\r
+*/\r
+\r
+long\r
+_Py_HashDouble(double v)\r
+{\r
+ double intpart, fractpart;\r
+ int expo;\r
+ long hipart;\r
+ long x; /* the final hash value */\r
+ /* This is designed so that Python numbers of different types\r
+ * that compare equal hash to the same value; otherwise comparisons\r
+ * of mapping keys will turn out weird.\r
+ */\r
+\r
+ if (!Py_IS_FINITE(v)) {\r
+ if (Py_IS_INFINITY(v))\r
+ return v < 0 ? -271828 : 314159;\r
+ else\r
+ return 0;\r
+ }\r
+ fractpart = modf(v, &intpart);\r
+ if (fractpart == 0.0) {\r
+ /* This must return the same hash as an equal int or long. */\r
+ if (intpart > LONG_MAX/2 || -intpart > LONG_MAX/2) {\r
+ /* Convert to long and use its hash. */\r
+ PyObject *plong; /* converted to Python long */\r
+ plong = PyLong_FromDouble(v);\r
+ if (plong == NULL)\r
+ return -1;\r
+ x = PyObject_Hash(plong);\r
+ Py_DECREF(plong);\r
+ return x;\r
+ }\r
+ /* Fits in a C long == a Python int, so is its own hash. */\r
+ x = (long)intpart;\r
+ if (x == -1)\r
+ x = -2;\r
+ return x;\r
+ }\r
+ /* The fractional part is non-zero, so we don't have to worry about\r
+ * making this match the hash of some other type.\r
+ * Use frexp to get at the bits in the double.\r
+ * Since the VAX D double format has 56 mantissa bits, which is the\r
+ * most of any double format in use, each of these parts may have as\r
+ * many as (but no more than) 56 significant bits.\r
+ * So, assuming sizeof(long) >= 4, each part can be broken into two\r
+ * longs; frexp and multiplication are used to do that.\r
+ * Also, since the Cray double format has 15 exponent bits, which is\r
+ * the most of any double format in use, shifting the exponent field\r
+ * left by 15 won't overflow a long (again assuming sizeof(long) >= 4).\r
+ */\r
+ v = frexp(v, &expo);\r
+ v *= 2147483648.0; /* 2**31 */\r
+ hipart = (long)v; /* take the top 32 bits */\r
+ v = (v - (double)hipart) * 2147483648.0; /* get the next 32 bits */\r
+ x = hipart + (long)v + (expo << 15);\r
+ if (x == -1)\r
+ x = -2;\r
+ return x;\r
+}\r
+\r
+long\r
+_Py_HashPointer(void *p)\r
+{\r
+ long x;\r
+ size_t y = (size_t)p;\r
+ /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid\r
+ excessive hash collisions for dicts and sets */\r
+ y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4));\r
+ x = (long)y;\r
+ if (x == -1)\r
+ x = -2;\r
+ return x;\r
+}\r
+\r
+long\r
+PyObject_HashNotImplemented(PyObject *self)\r
+{\r
+ PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'",\r
+ self->ob_type->tp_name);\r
+ return -1;\r
+}\r
+\r
+_Py_HashSecret_t _Py_HashSecret;\r
+\r
+long\r
+PyObject_Hash(PyObject *v)\r
+{\r
+ PyTypeObject *tp = v->ob_type;\r
+ if (tp->tp_hash != NULL)\r
+ return (*tp->tp_hash)(v);\r
+ /* To keep to the general practice that inheriting\r
+ * solely from object in C code should work without\r
+ * an explicit call to PyType_Ready, we implicitly call\r
+ * PyType_Ready here and then check the tp_hash slot again\r
+ */\r
+ if (tp->tp_dict == NULL) {\r
+ if (PyType_Ready(tp) < 0)\r
+ return -1;\r
+ if (tp->tp_hash != NULL)\r
+ return (*tp->tp_hash)(v);\r
+ }\r
+ if (tp->tp_compare == NULL && RICHCOMPARE(tp) == NULL) {\r
+ return _Py_HashPointer(v); /* Use address as hash value */\r
+ }\r
+ /* If there's a cmp but no hash defined, the object can't be hashed */\r
+ return PyObject_HashNotImplemented(v);\r
+}\r
+\r
+PyObject *\r
+PyObject_GetAttrString(PyObject *v, const char *name)\r
+{\r
+ PyObject *w, *res;\r
+\r
+ if (Py_TYPE(v)->tp_getattr != NULL)\r
+ return (*Py_TYPE(v)->tp_getattr)(v, (char*)name);\r
+ w = PyString_InternFromString(name);\r
+ if (w == NULL)\r
+ return NULL;\r
+ res = PyObject_GetAttr(v, w);\r
+ Py_XDECREF(w);\r
+ return res;\r
+}\r
+\r
+int\r
+PyObject_HasAttrString(PyObject *v, const char *name)\r
+{\r
+ PyObject *res = PyObject_GetAttrString(v, name);\r
+ if (res != NULL) {\r
+ Py_DECREF(res);\r
+ return 1;\r
+ }\r
+ PyErr_Clear();\r
+ return 0;\r
+}\r
+\r
+int\r
+PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w)\r
+{\r
+ PyObject *s;\r
+ int res;\r
+\r
+ if (Py_TYPE(v)->tp_setattr != NULL)\r
+ return (*Py_TYPE(v)->tp_setattr)(v, (char*)name, w);\r
+ s = PyString_InternFromString(name);\r
+ if (s == NULL)\r
+ return -1;\r
+ res = PyObject_SetAttr(v, s, w);\r
+ Py_XDECREF(s);\r
+ return res;\r
+}\r
+\r
+PyObject *\r
+PyObject_GetAttr(PyObject *v, PyObject *name)\r
+{\r
+ PyTypeObject *tp = Py_TYPE(v);\r
+\r
+ if (!PyString_Check(name)) {\r
+#ifdef Py_USING_UNICODE\r
+ /* The Unicode to string conversion is done here because the\r
+ existing tp_getattro slots expect a string object as name\r
+ and we wouldn't want to break those. */\r
+ if (PyUnicode_Check(name)) {\r
+ name = _PyUnicode_AsDefaultEncodedString(name, NULL);\r
+ if (name == NULL)\r
+ return NULL;\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "attribute name must be string, not '%.200s'",\r
+ Py_TYPE(name)->tp_name);\r
+ return NULL;\r
+ }\r
+ }\r
+ if (tp->tp_getattro != NULL)\r
+ return (*tp->tp_getattro)(v, name);\r
+ if (tp->tp_getattr != NULL)\r
+ return (*tp->tp_getattr)(v, PyString_AS_STRING(name));\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "'%.50s' object has no attribute '%.400s'",\r
+ tp->tp_name, PyString_AS_STRING(name));\r
+ return NULL;\r
+}\r
+\r
+int\r
+PyObject_HasAttr(PyObject *v, PyObject *name)\r
+{\r
+ PyObject *res = PyObject_GetAttr(v, name);\r
+ if (res != NULL) {\r
+ Py_DECREF(res);\r
+ return 1;\r
+ }\r
+ PyErr_Clear();\r
+ return 0;\r
+}\r
+\r
+int\r
+PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)\r
+{\r
+ PyTypeObject *tp = Py_TYPE(v);\r
+ int err;\r
+\r
+ if (!PyString_Check(name)){\r
+#ifdef Py_USING_UNICODE\r
+ /* The Unicode to string conversion is done here because the\r
+ existing tp_setattro slots expect a string object as name\r
+ and we wouldn't want to break those. */\r
+ if (PyUnicode_Check(name)) {\r
+ name = PyUnicode_AsEncodedString(name, NULL, NULL);\r
+ if (name == NULL)\r
+ return -1;\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "attribute name must be string, not '%.200s'",\r
+ Py_TYPE(name)->tp_name);\r
+ return -1;\r
+ }\r
+ }\r
+ else\r
+ Py_INCREF(name);\r
+\r
+ PyString_InternInPlace(&name);\r
+ if (tp->tp_setattro != NULL) {\r
+ err = (*tp->tp_setattro)(v, name, value);\r
+ Py_DECREF(name);\r
+ return err;\r
+ }\r
+ if (tp->tp_setattr != NULL) {\r
+ err = (*tp->tp_setattr)(v, PyString_AS_STRING(name), value);\r
+ Py_DECREF(name);\r
+ return err;\r
+ }\r
+ Py_DECREF(name);\r
+ if (tp->tp_getattr == NULL && tp->tp_getattro == NULL)\r
+ PyErr_Format(PyExc_TypeError,\r
+ "'%.100s' object has no attributes "\r
+ "(%s .%.100s)",\r
+ tp->tp_name,\r
+ value==NULL ? "del" : "assign to",\r
+ PyString_AS_STRING(name));\r
+ else\r
+ PyErr_Format(PyExc_TypeError,\r
+ "'%.100s' object has only read-only attributes "\r
+ "(%s .%.100s)",\r
+ tp->tp_name,\r
+ value==NULL ? "del" : "assign to",\r
+ PyString_AS_STRING(name));\r
+ return -1;\r
+}\r
+\r
+/* Helper to get a pointer to an object's __dict__ slot, if any */\r
+\r
+PyObject **\r
+_PyObject_GetDictPtr(PyObject *obj)\r
+{\r
+ Py_ssize_t dictoffset;\r
+ PyTypeObject *tp = Py_TYPE(obj);\r
+\r
+ if (!(tp->tp_flags & Py_TPFLAGS_HAVE_CLASS))\r
+ return NULL;\r
+ dictoffset = tp->tp_dictoffset;\r
+ if (dictoffset == 0)\r
+ return NULL;\r
+ if (dictoffset < 0) {\r
+ Py_ssize_t tsize;\r
+ size_t size;\r
+\r
+ tsize = ((PyVarObject *)obj)->ob_size;\r
+ if (tsize < 0)\r
+ tsize = -tsize;\r
+ size = _PyObject_VAR_SIZE(tp, tsize);\r
+\r
+ dictoffset += (long)size;\r
+ assert(dictoffset > 0);\r
+ assert(dictoffset % SIZEOF_VOID_P == 0);\r
+ }\r
+ return (PyObject **) ((char *)obj + dictoffset);\r
+}\r
+\r
+PyObject *\r
+PyObject_SelfIter(PyObject *obj)\r
+{\r
+ Py_INCREF(obj);\r
+ return obj;\r
+}\r
+\r
+/* Helper used when the __next__ method is removed from a type:\r
+ tp_iternext is never NULL and can be safely called without checking\r
+ on every iteration.\r
+ */\r
+\r
+PyObject *\r
+_PyObject_NextNotImplemented(PyObject *self)\r
+{\r
+ PyErr_Format(PyExc_TypeError,\r
+ "'%.200s' object is not iterable",\r
+ Py_TYPE(self)->tp_name);\r
+ return NULL;\r
+}\r
+\r
+/* Generic GetAttr functions - put these in your tp_[gs]etattro slot */\r
+\r
+PyObject *\r
+_PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)\r
+{\r
+ PyTypeObject *tp = Py_TYPE(obj);\r
+ PyObject *descr = NULL;\r
+ PyObject *res = NULL;\r
+ descrgetfunc f;\r
+ Py_ssize_t dictoffset;\r
+ PyObject **dictptr;\r
+\r
+ if (!PyString_Check(name)){\r
+#ifdef Py_USING_UNICODE\r
+ /* The Unicode to string conversion is done here because the\r
+ existing tp_setattro slots expect a string object as name\r
+ and we wouldn't want to break those. */\r
+ if (PyUnicode_Check(name)) {\r
+ name = PyUnicode_AsEncodedString(name, NULL, NULL);\r
+ if (name == NULL)\r
+ return NULL;\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "attribute name must be string, not '%.200s'",\r
+ Py_TYPE(name)->tp_name);\r
+ return NULL;\r
+ }\r
+ }\r
+ else\r
+ Py_INCREF(name);\r
+\r
+ if (tp->tp_dict == NULL) {\r
+ if (PyType_Ready(tp) < 0)\r
+ goto done;\r
+ }\r
+\r
+#if 0 /* XXX this is not quite _PyType_Lookup anymore */\r
+ /* Inline _PyType_Lookup */\r
+ {\r
+ Py_ssize_t i, n;\r
+ PyObject *mro, *base, *dict;\r
+\r
+ /* Look in tp_dict of types in MRO */\r
+ mro = tp->tp_mro;\r
+ assert(mro != NULL);\r
+ assert(PyTuple_Check(mro));\r
+ n = PyTuple_GET_SIZE(mro);\r
+ for (i = 0; i < n; i++) {\r
+ base = PyTuple_GET_ITEM(mro, i);\r
+ if (PyClass_Check(base))\r
+ dict = ((PyClassObject *)base)->cl_dict;\r
+ else {\r
+ assert(PyType_Check(base));\r
+ dict = ((PyTypeObject *)base)->tp_dict;\r
+ }\r
+ assert(dict && PyDict_Check(dict));\r
+ descr = PyDict_GetItem(dict, name);\r
+ if (descr != NULL)\r
+ break;\r
+ }\r
+ }\r
+#else\r
+ descr = _PyType_Lookup(tp, name);\r
+#endif\r
+\r
+ Py_XINCREF(descr);\r
+\r
+ f = NULL;\r
+ if (descr != NULL &&\r
+ PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) {\r
+ f = descr->ob_type->tp_descr_get;\r
+ if (f != NULL && PyDescr_IsData(descr)) {\r
+ res = f(descr, obj, (PyObject *)obj->ob_type);\r
+ Py_DECREF(descr);\r
+ goto done;\r
+ }\r
+ }\r
+\r
+ if (dict == NULL) {\r
+ /* Inline _PyObject_GetDictPtr */\r
+ dictoffset = tp->tp_dictoffset;\r
+ if (dictoffset != 0) {\r
+ if (dictoffset < 0) {\r
+ Py_ssize_t tsize;\r
+ size_t size;\r
+\r
+ tsize = ((PyVarObject *)obj)->ob_size;\r
+ if (tsize < 0)\r
+ tsize = -tsize;\r
+ size = _PyObject_VAR_SIZE(tp, tsize);\r
+\r
+ dictoffset += (long)size;\r
+ assert(dictoffset > 0);\r
+ assert(dictoffset % SIZEOF_VOID_P == 0);\r
+ }\r
+ dictptr = (PyObject **) ((char *)obj + dictoffset);\r
+ dict = *dictptr;\r
+ }\r
+ }\r
+ if (dict != NULL) {\r
+ Py_INCREF(dict);\r
+ res = PyDict_GetItem(dict, name);\r
+ if (res != NULL) {\r
+ Py_INCREF(res);\r
+ Py_XDECREF(descr);\r
+ Py_DECREF(dict);\r
+ goto done;\r
+ }\r
+ Py_DECREF(dict);\r
+ }\r
+\r
+ if (f != NULL) {\r
+ res = f(descr, obj, (PyObject *)Py_TYPE(obj));\r
+ Py_DECREF(descr);\r
+ goto done;\r
+ }\r
+\r
+ if (descr != NULL) {\r
+ res = descr;\r
+ /* descr was already increfed above */\r
+ goto done;\r
+ }\r
+\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "'%.50s' object has no attribute '%.400s'",\r
+ tp->tp_name, PyString_AS_STRING(name));\r
+ done:\r
+ Py_DECREF(name);\r
+ return res;\r
+}\r
+\r
+PyObject *\r
+PyObject_GenericGetAttr(PyObject *obj, PyObject *name)\r
+{\r
+ return _PyObject_GenericGetAttrWithDict(obj, name, NULL);\r
+}\r
+\r
+int\r
+_PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,\r
+ PyObject *value, PyObject *dict)\r
+{\r
+ PyTypeObject *tp = Py_TYPE(obj);\r
+ PyObject *descr;\r
+ descrsetfunc f;\r
+ PyObject **dictptr;\r
+ int res = -1;\r
+\r
+ if (!PyString_Check(name)){\r
+#ifdef Py_USING_UNICODE\r
+ /* The Unicode to string conversion is done here because the\r
+ existing tp_setattro slots expect a string object as name\r
+ and we wouldn't want to break those. */\r
+ if (PyUnicode_Check(name)) {\r
+ name = PyUnicode_AsEncodedString(name, NULL, NULL);\r
+ if (name == NULL)\r
+ return -1;\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "attribute name must be string, not '%.200s'",\r
+ Py_TYPE(name)->tp_name);\r
+ return -1;\r
+ }\r
+ }\r
+ else\r
+ Py_INCREF(name);\r
+\r
+ if (tp->tp_dict == NULL) {\r
+ if (PyType_Ready(tp) < 0)\r
+ goto done;\r
+ }\r
+\r
+ descr = _PyType_Lookup(tp, name);\r
+ f = NULL;\r
+ if (descr != NULL &&\r
+ PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) {\r
+ f = descr->ob_type->tp_descr_set;\r
+ if (f != NULL && PyDescr_IsData(descr)) {\r
+ res = f(descr, obj, value);\r
+ goto done;\r
+ }\r
+ }\r
+\r
+ if (dict == NULL) {\r
+ dictptr = _PyObject_GetDictPtr(obj);\r
+ if (dictptr != NULL) {\r
+ dict = *dictptr;\r
+ if (dict == NULL && value != NULL) {\r
+ dict = PyDict_New();\r
+ if (dict == NULL)\r
+ goto done;\r
+ *dictptr = dict;\r
+ }\r
+ }\r
+ }\r
+ if (dict != NULL) {\r
+ Py_INCREF(dict);\r
+ if (value == NULL)\r
+ res = PyDict_DelItem(dict, name);\r
+ else\r
+ res = PyDict_SetItem(dict, name, value);\r
+ if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))\r
+ PyErr_SetObject(PyExc_AttributeError, name);\r
+ Py_DECREF(dict);\r
+ goto done;\r
+ }\r
+\r
+ if (f != NULL) {\r
+ res = f(descr, obj, value);\r
+ goto done;\r
+ }\r
+\r
+ if (descr == NULL) {\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "'%.100s' object has no attribute '%.200s'",\r
+ tp->tp_name, PyString_AS_STRING(name));\r
+ goto done;\r
+ }\r
+\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "'%.50s' object attribute '%.400s' is read-only",\r
+ tp->tp_name, PyString_AS_STRING(name));\r
+ done:\r
+ Py_DECREF(name);\r
+ return res;\r
+}\r
+\r
+int\r
+PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)\r
+{\r
+ return _PyObject_GenericSetAttrWithDict(obj, name, value, NULL);\r
+}\r
+\r
+\r
+/* Test a value used as condition, e.g., in a for or if statement.\r
+ Return -1 if an error occurred */\r
+\r
+int\r
+PyObject_IsTrue(PyObject *v)\r
+{\r
+ Py_ssize_t res;\r
+ if (v == Py_True)\r
+ return 1;\r
+ if (v == Py_False)\r
+ return 0;\r
+ if (v == Py_None)\r
+ return 0;\r
+ else if (v->ob_type->tp_as_number != NULL &&\r
+ v->ob_type->tp_as_number->nb_nonzero != NULL)\r
+ res = (*v->ob_type->tp_as_number->nb_nonzero)(v);\r
+ else if (v->ob_type->tp_as_mapping != NULL &&\r
+ v->ob_type->tp_as_mapping->mp_length != NULL)\r
+ res = (*v->ob_type->tp_as_mapping->mp_length)(v);\r
+ else if (v->ob_type->tp_as_sequence != NULL &&\r
+ v->ob_type->tp_as_sequence->sq_length != NULL)\r
+ res = (*v->ob_type->tp_as_sequence->sq_length)(v);\r
+ else\r
+ return 1;\r
+ /* if it is negative, it should be either -1 or -2 */\r
+ return (res > 0) ? 1 : Py_SAFE_DOWNCAST(res, Py_ssize_t, int);\r
+}\r
+\r
+/* equivalent of 'not v'\r
+ Return -1 if an error occurred */\r
+\r
+int\r
+PyObject_Not(PyObject *v)\r
+{\r
+ int res;\r
+ res = PyObject_IsTrue(v);\r
+ if (res < 0)\r
+ return res;\r
+ return res == 0;\r
+}\r
+\r
+/* Coerce two numeric types to the "larger" one.\r
+ Increment the reference count on each argument.\r
+ Return value:\r
+ -1 if an error occurred;\r
+ 0 if the coercion succeeded (and then the reference counts are increased);\r
+ 1 if no coercion is possible (and no error is raised).\r
+*/\r
+int\r
+PyNumber_CoerceEx(PyObject **pv, PyObject **pw)\r
+{\r
+ register PyObject *v = *pv;\r
+ register PyObject *w = *pw;\r
+ int res;\r
+\r
+ /* Shortcut only for old-style types */\r
+ if (v->ob_type == w->ob_type &&\r
+ !PyType_HasFeature(v->ob_type, Py_TPFLAGS_CHECKTYPES))\r
+ {\r
+ Py_INCREF(v);\r
+ Py_INCREF(w);\r
+ return 0;\r
+ }\r
+ if (v->ob_type->tp_as_number && v->ob_type->tp_as_number->nb_coerce) {\r
+ res = (*v->ob_type->tp_as_number->nb_coerce)(pv, pw);\r
+ if (res <= 0)\r
+ return res;\r
+ }\r
+ if (w->ob_type->tp_as_number && w->ob_type->tp_as_number->nb_coerce) {\r
+ res = (*w->ob_type->tp_as_number->nb_coerce)(pw, pv);\r
+ if (res <= 0)\r
+ return res;\r
+ }\r
+ return 1;\r
+}\r
+\r
+/* Coerce two numeric types to the "larger" one.\r
+ Increment the reference count on each argument.\r
+ Return -1 and raise an exception if no coercion is possible\r
+ (and then no reference count is incremented).\r
+*/\r
+int\r
+PyNumber_Coerce(PyObject **pv, PyObject **pw)\r
+{\r
+ int err = PyNumber_CoerceEx(pv, pw);\r
+ if (err <= 0)\r
+ return err;\r
+ PyErr_SetString(PyExc_TypeError, "number coercion failed");\r
+ return -1;\r
+}\r
+\r
+\r
+/* Test whether an object can be called */\r
+\r
+int\r
+PyCallable_Check(PyObject *x)\r
+{\r
+ if (x == NULL)\r
+ return 0;\r
+ if (PyInstance_Check(x)) {\r
+ PyObject *call = PyObject_GetAttrString(x, "__call__");\r
+ if (call == NULL) {\r
+ PyErr_Clear();\r
+ return 0;\r
+ }\r
+ /* Could test recursively but don't, for fear of endless\r
+ recursion if some joker sets self.__call__ = self */\r
+ Py_DECREF(call);\r
+ return 1;\r
+ }\r
+ else {\r
+ return x->ob_type->tp_call != NULL;\r
+ }\r
+}\r
+\r
+/* ------------------------- PyObject_Dir() helpers ------------------------- */\r
+\r
+/* Helper for PyObject_Dir.\r
+ Merge the __dict__ of aclass into dict, and recursively also all\r
+ the __dict__s of aclass's base classes. The order of merging isn't\r
+ defined, as it's expected that only the final set of dict keys is\r
+ interesting.\r
+ Return 0 on success, -1 on error.\r
+*/\r
+\r
+static int\r
+merge_class_dict(PyObject* dict, PyObject* aclass)\r
+{\r
+ PyObject *classdict;\r
+ PyObject *bases;\r
+\r
+ assert(PyDict_Check(dict));\r
+ assert(aclass);\r
+\r
+ /* Merge in the type's dict (if any). */\r
+ classdict = PyObject_GetAttrString(aclass, "__dict__");\r
+ if (classdict == NULL)\r
+ PyErr_Clear();\r
+ else {\r
+ int status = PyDict_Update(dict, classdict);\r
+ Py_DECREF(classdict);\r
+ if (status < 0)\r
+ return -1;\r
+ }\r
+\r
+ /* Recursively merge in the base types' (if any) dicts. */\r
+ bases = PyObject_GetAttrString(aclass, "__bases__");\r
+ if (bases == NULL)\r
+ PyErr_Clear();\r
+ else {\r
+ /* We have no guarantee that bases is a real tuple */\r
+ Py_ssize_t i, n;\r
+ n = PySequence_Size(bases); /* This better be right */\r
+ if (n < 0)\r
+ PyErr_Clear();\r
+ else {\r
+ for (i = 0; i < n; i++) {\r
+ int status;\r
+ PyObject *base = PySequence_GetItem(bases, i);\r
+ if (base == NULL) {\r
+ Py_DECREF(bases);\r
+ return -1;\r
+ }\r
+ status = merge_class_dict(dict, base);\r
+ Py_DECREF(base);\r
+ if (status < 0) {\r
+ Py_DECREF(bases);\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+ Py_DECREF(bases);\r
+ }\r
+ return 0;\r
+}\r
+\r
+/* Helper for PyObject_Dir.\r
+ If obj has an attr named attrname that's a list, merge its string\r
+ elements into keys of dict.\r
+ Return 0 on success, -1 on error. Errors due to not finding the attr,\r
+ or the attr not being a list, are suppressed.\r
+*/\r
+\r
+static int\r
+merge_list_attr(PyObject* dict, PyObject* obj, const char *attrname)\r
+{\r
+ PyObject *list;\r
+ int result = 0;\r
+\r
+ assert(PyDict_Check(dict));\r
+ assert(obj);\r
+ assert(attrname);\r
+\r
+ list = PyObject_GetAttrString(obj, attrname);\r
+ if (list == NULL)\r
+ PyErr_Clear();\r
+\r
+ else if (PyList_Check(list)) {\r
+ int i;\r
+ for (i = 0; i < PyList_GET_SIZE(list); ++i) {\r
+ PyObject *item = PyList_GET_ITEM(list, i);\r
+ if (PyString_Check(item)) {\r
+ result = PyDict_SetItem(dict, item, Py_None);\r
+ if (result < 0)\r
+ break;\r
+ }\r
+ }\r
+ if (Py_Py3kWarningFlag &&\r
+ (strcmp(attrname, "__members__") == 0 ||\r
+ strcmp(attrname, "__methods__") == 0)) {\r
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,\r
+ "__members__ and __methods__ not "\r
+ "supported in 3.x", 1) < 0) {\r
+ Py_XDECREF(list);\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+\r
+ Py_XDECREF(list);\r
+ return result;\r
+}\r
+\r
+/* Helper for PyObject_Dir without arguments: returns the local scope. */\r
+static PyObject *\r
+_dir_locals(void)\r
+{\r
+ PyObject *names;\r
+ PyObject *locals = PyEval_GetLocals();\r
+\r
+ if (locals == NULL) {\r
+ PyErr_SetString(PyExc_SystemError, "frame does not exist");\r
+ return NULL;\r
+ }\r
+\r
+ names = PyMapping_Keys(locals);\r
+ if (!names)\r
+ return NULL;\r
+ if (!PyList_Check(names)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "dir(): expected keys() of locals to be a list, "\r
+ "not '%.200s'", Py_TYPE(names)->tp_name);\r
+ Py_DECREF(names);\r
+ return NULL;\r
+ }\r
+ /* the locals don't need to be DECREF'd */\r
+ return names;\r
+}\r
+\r
+/* Helper for PyObject_Dir of type objects: returns __dict__ and __bases__.\r
+ We deliberately don't suck up its __class__, as methods belonging to the\r
+ metaclass would probably be more confusing than helpful.\r
+*/\r
+static PyObject *\r
+_specialized_dir_type(PyObject *obj)\r
+{\r
+ PyObject *result = NULL;\r
+ PyObject *dict = PyDict_New();\r
+\r
+ if (dict != NULL && merge_class_dict(dict, obj) == 0)\r
+ result = PyDict_Keys(dict);\r
+\r
+ Py_XDECREF(dict);\r
+ return result;\r
+}\r
+\r
+/* Helper for PyObject_Dir of module objects: returns the module's __dict__. */\r
+static PyObject *\r
+_specialized_dir_module(PyObject *obj)\r
+{\r
+ PyObject *result = NULL;\r
+ PyObject *dict = PyObject_GetAttrString(obj, "__dict__");\r
+\r
+ if (dict != NULL) {\r
+ if (PyDict_Check(dict))\r
+ result = PyDict_Keys(dict);\r
+ else {\r
+ char *name = PyModule_GetName(obj);\r
+ if (name)\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%.200s.__dict__ is not a dictionary",\r
+ name);\r
+ }\r
+ }\r
+\r
+ Py_XDECREF(dict);\r
+ return result;\r
+}\r
+\r
+/* Helper for PyObject_Dir of generic objects: returns __dict__, __class__,\r
+ and recursively up the __class__.__bases__ chain.\r
+*/\r
+static PyObject *\r
+_generic_dir(PyObject *obj)\r
+{\r
+ PyObject *result = NULL;\r
+ PyObject *dict = NULL;\r
+ PyObject *itsclass = NULL;\r
+\r
+ /* Get __dict__ (which may or may not be a real dict...) */\r
+ dict = PyObject_GetAttrString(obj, "__dict__");\r
+ if (dict == NULL) {\r
+ PyErr_Clear();\r
+ dict = PyDict_New();\r
+ }\r
+ else if (!PyDict_Check(dict)) {\r
+ Py_DECREF(dict);\r
+ dict = PyDict_New();\r
+ }\r
+ else {\r
+ /* Copy __dict__ to avoid mutating it. */\r
+ PyObject *temp = PyDict_Copy(dict);\r
+ Py_DECREF(dict);\r
+ dict = temp;\r
+ }\r
+\r
+ if (dict == NULL)\r
+ goto error;\r
+\r
+ /* Merge in __members__ and __methods__ (if any).\r
+ * This is removed in Python 3000. */\r
+ if (merge_list_attr(dict, obj, "__members__") < 0)\r
+ goto error;\r
+ if (merge_list_attr(dict, obj, "__methods__") < 0)\r
+ goto error;\r
+\r
+ /* Merge in attrs reachable from its class. */\r
+ itsclass = PyObject_GetAttrString(obj, "__class__");\r
+ if (itsclass == NULL)\r
+ /* XXX(tomer): Perhaps fall back to obj->ob_type if no\r
+ __class__ exists? */\r
+ PyErr_Clear();\r
+ else {\r
+ if (merge_class_dict(dict, itsclass) != 0)\r
+ goto error;\r
+ }\r
+\r
+ result = PyDict_Keys(dict);\r
+ /* fall through */\r
+error:\r
+ Py_XDECREF(itsclass);\r
+ Py_XDECREF(dict);\r
+ return result;\r
+}\r
+\r
+/* Helper for PyObject_Dir: object introspection.\r
+ This calls one of the above specialized versions if no __dir__ method\r
+ exists. */\r
+static PyObject *\r
+_dir_object(PyObject *obj)\r
+{\r
+ PyObject *result = NULL;\r
+ static PyObject *dir_str = NULL;\r
+ PyObject *dirfunc;\r
+\r
+ assert(obj);\r
+ if (PyInstance_Check(obj)) {\r
+ dirfunc = PyObject_GetAttrString(obj, "__dir__");\r
+ if (dirfunc == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_AttributeError))\r
+ PyErr_Clear();\r
+ else\r
+ return NULL;\r
+ }\r
+ }\r
+ else {\r
+ dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str);\r
+ if (PyErr_Occurred())\r
+ return NULL;\r
+ }\r
+ if (dirfunc == NULL) {\r
+ /* use default implementation */\r
+ if (PyModule_Check(obj))\r
+ result = _specialized_dir_module(obj);\r
+ else if (PyType_Check(obj) || PyClass_Check(obj))\r
+ result = _specialized_dir_type(obj);\r
+ else\r
+ result = _generic_dir(obj);\r
+ }\r
+ else {\r
+ /* use __dir__ */\r
+ result = PyObject_CallFunctionObjArgs(dirfunc, NULL);\r
+ Py_DECREF(dirfunc);\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ /* result must be a list */\r
+ /* XXX(gbrandl): could also check if all items are strings */\r
+ if (!PyList_Check(result)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__dir__() must return a list, not %.200s",\r
+ Py_TYPE(result)->tp_name);\r
+ Py_DECREF(result);\r
+ result = NULL;\r
+ }\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+/* Implementation of dir() -- if obj is NULL, returns the names in the current\r
+ (local) scope. Otherwise, performs introspection of the object: returns a\r
+ sorted list of attribute names (supposedly) accessible from the object\r
+*/\r
+PyObject *\r
+PyObject_Dir(PyObject *obj)\r
+{\r
+ PyObject * result;\r
+\r
+ if (obj == NULL)\r
+ /* no object -- introspect the locals */\r
+ result = _dir_locals();\r
+ else\r
+ /* object -- introspect the object */\r
+ result = _dir_object(obj);\r
+\r
+ assert(result == NULL || PyList_Check(result));\r
+\r
+ if (result != NULL && PyList_Sort(result) != 0) {\r
+ /* sorting the list failed */\r
+ Py_DECREF(result);\r
+ result = NULL;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+/*\r
+NoObject is usable as a non-NULL undefined value, used by the macro None.\r
+There is (and should be!) no way to create other objects of this type,\r
+so there is exactly one (which is indestructible, by the way).\r
+(XXX This type and the type of NotImplemented below should be unified.)\r
+*/\r
+\r
+/* ARGSUSED */\r
+static PyObject *\r
+none_repr(PyObject *op)\r
+{\r
+ return PyString_FromString("None");\r
+}\r
+\r
+/* ARGUSED */\r
+static void\r
+none_dealloc(PyObject* ignore)\r
+{\r
+ /* This should never get called, but we also don't want to SEGV if\r
+ * we accidentally decref None out of existence.\r
+ */\r
+ Py_FatalError("deallocating None");\r
+}\r
+\r
+\r
+static PyTypeObject PyNone_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "NoneType",\r
+ 0,\r
+ 0,\r
+ none_dealloc, /*tp_dealloc*/ /*never called*/\r
+ 0, /*tp_print*/\r
+ 0, /*tp_getattr*/\r
+ 0, /*tp_setattr*/\r
+ 0, /*tp_compare*/\r
+ none_repr, /*tp_repr*/\r
+ 0, /*tp_as_number*/\r
+ 0, /*tp_as_sequence*/\r
+ 0, /*tp_as_mapping*/\r
+ (hashfunc)_Py_HashPointer, /*tp_hash */\r
+};\r
+\r
+PyObject _Py_NoneStruct = {\r
+ _PyObject_EXTRA_INIT\r
+ 1, &PyNone_Type\r
+};\r
+\r
+/* NotImplemented is an object that can be used to signal that an\r
+ operation is not implemented for the given type combination. */\r
+\r
+static PyObject *\r
+NotImplemented_repr(PyObject *op)\r
+{\r
+ return PyString_FromString("NotImplemented");\r
+}\r
+\r
+static PyTypeObject PyNotImplemented_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "NotImplementedType",\r
+ 0,\r
+ 0,\r
+ none_dealloc, /*tp_dealloc*/ /*never called*/\r
+ 0, /*tp_print*/\r
+ 0, /*tp_getattr*/\r
+ 0, /*tp_setattr*/\r
+ 0, /*tp_compare*/\r
+ NotImplemented_repr, /*tp_repr*/\r
+ 0, /*tp_as_number*/\r
+ 0, /*tp_as_sequence*/\r
+ 0, /*tp_as_mapping*/\r
+ 0, /*tp_hash */\r
+};\r
+\r
+PyObject _Py_NotImplementedStruct = {\r
+ _PyObject_EXTRA_INIT\r
+ 1, &PyNotImplemented_Type\r
+};\r
+\r
+void\r
+_Py_ReadyTypes(void)\r
+{\r
+ if (PyType_Ready(&PyType_Type) < 0)\r
+ Py_FatalError("Can't initialize type type");\r
+\r
+ if (PyType_Ready(&_PyWeakref_RefType) < 0)\r
+ Py_FatalError("Can't initialize weakref type");\r
+\r
+ if (PyType_Ready(&_PyWeakref_CallableProxyType) < 0)\r
+ Py_FatalError("Can't initialize callable weakref proxy type");\r
+\r
+ if (PyType_Ready(&_PyWeakref_ProxyType) < 0)\r
+ Py_FatalError("Can't initialize weakref proxy type");\r
+\r
+ if (PyType_Ready(&PyBool_Type) < 0)\r
+ Py_FatalError("Can't initialize bool type");\r
+\r
+ if (PyType_Ready(&PyString_Type) < 0)\r
+ Py_FatalError("Can't initialize str type");\r
+\r
+ if (PyType_Ready(&PyByteArray_Type) < 0)\r
+ Py_FatalError("Can't initialize bytearray type");\r
+\r
+ if (PyType_Ready(&PyList_Type) < 0)\r
+ Py_FatalError("Can't initialize list type");\r
+\r
+ if (PyType_Ready(&PyNone_Type) < 0)\r
+ Py_FatalError("Can't initialize None type");\r
+\r
+ if (PyType_Ready(&PyNotImplemented_Type) < 0)\r
+ Py_FatalError("Can't initialize NotImplemented type");\r
+\r
+ if (PyType_Ready(&PyTraceBack_Type) < 0)\r
+ Py_FatalError("Can't initialize traceback type");\r
+\r
+ if (PyType_Ready(&PySuper_Type) < 0)\r
+ Py_FatalError("Can't initialize super type");\r
+\r
+ if (PyType_Ready(&PyBaseObject_Type) < 0)\r
+ Py_FatalError("Can't initialize object type");\r
+\r
+ if (PyType_Ready(&PyRange_Type) < 0)\r
+ Py_FatalError("Can't initialize xrange type");\r
+\r
+ if (PyType_Ready(&PyDict_Type) < 0)\r
+ Py_FatalError("Can't initialize dict type");\r
+\r
+ if (PyType_Ready(&PySet_Type) < 0)\r
+ Py_FatalError("Can't initialize set type");\r
+\r
+#ifdef Py_USING_UNICODE\r
+ if (PyType_Ready(&PyUnicode_Type) < 0)\r
+ Py_FatalError("Can't initialize unicode type");\r
+#endif\r
+\r
+ if (PyType_Ready(&PySlice_Type) < 0)\r
+ Py_FatalError("Can't initialize slice type");\r
+\r
+ if (PyType_Ready(&PyStaticMethod_Type) < 0)\r
+ Py_FatalError("Can't initialize static method type");\r
+\r
+#ifndef WITHOUT_COMPLEX\r
+ if (PyType_Ready(&PyComplex_Type) < 0)\r
+ Py_FatalError("Can't initialize complex type");\r
+#endif\r
+\r
+ if (PyType_Ready(&PyFloat_Type) < 0)\r
+ Py_FatalError("Can't initialize float type");\r
+\r
+ if (PyType_Ready(&PyBuffer_Type) < 0)\r
+ Py_FatalError("Can't initialize buffer type");\r
+\r
+ if (PyType_Ready(&PyLong_Type) < 0)\r
+ Py_FatalError("Can't initialize long type");\r
+\r
+ if (PyType_Ready(&PyInt_Type) < 0)\r
+ Py_FatalError("Can't initialize int type");\r
+\r
+ if (PyType_Ready(&PyFrozenSet_Type) < 0)\r
+ Py_FatalError("Can't initialize frozenset type");\r
+\r
+ if (PyType_Ready(&PyProperty_Type) < 0)\r
+ Py_FatalError("Can't initialize property type");\r
+\r
+ if (PyType_Ready(&PyMemoryView_Type) < 0)\r
+ Py_FatalError("Can't initialize memoryview type");\r
+\r
+ if (PyType_Ready(&PyTuple_Type) < 0)\r
+ Py_FatalError("Can't initialize tuple type");\r
+\r
+ if (PyType_Ready(&PyEnum_Type) < 0)\r
+ Py_FatalError("Can't initialize enumerate type");\r
+\r
+ if (PyType_Ready(&PyReversed_Type) < 0)\r
+ Py_FatalError("Can't initialize reversed type");\r
+\r
+ if (PyType_Ready(&PyCode_Type) < 0)\r
+ Py_FatalError("Can't initialize code type");\r
+\r
+ if (PyType_Ready(&PyFrame_Type) < 0)\r
+ Py_FatalError("Can't initialize frame type");\r
+\r
+ if (PyType_Ready(&PyCFunction_Type) < 0)\r
+ Py_FatalError("Can't initialize builtin function type");\r
+\r
+ if (PyType_Ready(&PyMethod_Type) < 0)\r
+ Py_FatalError("Can't initialize method type");\r
+\r
+ if (PyType_Ready(&PyFunction_Type) < 0)\r
+ Py_FatalError("Can't initialize function type");\r
+\r
+ if (PyType_Ready(&PyClass_Type) < 0)\r
+ Py_FatalError("Can't initialize class type");\r
+\r
+ if (PyType_Ready(&PyDictProxy_Type) < 0)\r
+ Py_FatalError("Can't initialize dict proxy type");\r
+\r
+ if (PyType_Ready(&PyGen_Type) < 0)\r
+ Py_FatalError("Can't initialize generator type");\r
+\r
+ if (PyType_Ready(&PyGetSetDescr_Type) < 0)\r
+ Py_FatalError("Can't initialize get-set descriptor type");\r
+\r
+ if (PyType_Ready(&PyWrapperDescr_Type) < 0)\r
+ Py_FatalError("Can't initialize wrapper type");\r
+\r
+ if (PyType_Ready(&PyInstance_Type) < 0)\r
+ Py_FatalError("Can't initialize instance type");\r
+\r
+ if (PyType_Ready(&PyEllipsis_Type) < 0)\r
+ Py_FatalError("Can't initialize ellipsis type");\r
+\r
+ if (PyType_Ready(&PyMemberDescr_Type) < 0)\r
+ Py_FatalError("Can't initialize member descriptor type");\r
+\r
+ if (PyType_Ready(&PyFile_Type) < 0)\r
+ Py_FatalError("Can't initialize file type");\r
+\r
+ if (PyType_Ready(&PyCapsule_Type) < 0)\r
+ Py_FatalError("Can't initialize capsule type");\r
+\r
+ if (PyType_Ready(&PyCell_Type) < 0)\r
+ Py_FatalError("Can't initialize cell type");\r
+\r
+ if (PyType_Ready(&PyCallIter_Type) < 0)\r
+ Py_FatalError("Can't initialize call iter type");\r
+\r
+ if (PyType_Ready(&PySeqIter_Type) < 0)\r
+ Py_FatalError("Can't initialize sequence iterator type");\r
+}\r
+\r
+\r
+#ifdef Py_TRACE_REFS\r
+\r
+void\r
+_Py_NewReference(PyObject *op)\r
+{\r
+ _Py_INC_REFTOTAL;\r
+ op->ob_refcnt = 1;\r
+ _Py_AddToAllObjects(op, 1);\r
+ _Py_INC_TPALLOCS(op);\r
+}\r
+\r
+void\r
+_Py_ForgetReference(register PyObject *op)\r
+{\r
+#ifdef SLOW_UNREF_CHECK\r
+ register PyObject *p;\r
+#endif\r
+ if (op->ob_refcnt < 0)\r
+ Py_FatalError("UNREF negative refcnt");\r
+ if (op == &refchain ||\r
+ op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op)\r
+ Py_FatalError("UNREF invalid object");\r
+#ifdef SLOW_UNREF_CHECK\r
+ for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {\r
+ if (p == op)\r
+ break;\r
+ }\r
+ if (p == &refchain) /* Not found */\r
+ Py_FatalError("UNREF unknown object");\r
+#endif\r
+ op->_ob_next->_ob_prev = op->_ob_prev;\r
+ op->_ob_prev->_ob_next = op->_ob_next;\r
+ op->_ob_next = op->_ob_prev = NULL;\r
+ _Py_INC_TPFREES(op);\r
+}\r
+\r
+void\r
+_Py_Dealloc(PyObject *op)\r
+{\r
+ destructor dealloc = Py_TYPE(op)->tp_dealloc;\r
+ _Py_ForgetReference(op);\r
+ (*dealloc)(op);\r
+}\r
+\r
+/* Print all live objects. Because PyObject_Print is called, the\r
+ * interpreter must be in a healthy state.\r
+ */\r
+void\r
+_Py_PrintReferences(FILE *fp)\r
+{\r
+ PyObject *op;\r
+ fprintf(fp, "Remaining objects:\n");\r
+ for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) {\r
+ fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] ", op, op->ob_refcnt);\r
+ if (PyObject_Print(op, fp, 0) != 0)\r
+ PyErr_Clear();\r
+ putc('\n', fp);\r
+ }\r
+}\r
+\r
+/* Print the addresses of all live objects. Unlike _Py_PrintReferences, this\r
+ * doesn't make any calls to the Python C API, so is always safe to call.\r
+ */\r
+void\r
+_Py_PrintReferenceAddresses(FILE *fp)\r
+{\r
+ PyObject *op;\r
+ fprintf(fp, "Remaining object addresses:\n");\r
+ for (op = refchain._ob_next; op != &refchain; op = op->_ob_next)\r
+ fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] %s\n", op,\r
+ op->ob_refcnt, Py_TYPE(op)->tp_name);\r
+}\r
+\r
+PyObject *\r
+_Py_GetObjects(PyObject *self, PyObject *args)\r
+{\r
+ int i, n;\r
+ PyObject *t = NULL;\r
+ PyObject *res, *op;\r
+\r
+ if (!PyArg_ParseTuple(args, "i|O", &n, &t))\r
+ return NULL;\r
+ op = refchain._ob_next;\r
+ res = PyList_New(0);\r
+ if (res == NULL)\r
+ return NULL;\r
+ for (i = 0; (n == 0 || i < n) && op != &refchain; i++) {\r
+ while (op == self || op == args || op == res || op == t ||\r
+ (t != NULL && Py_TYPE(op) != (PyTypeObject *) t)) {\r
+ op = op->_ob_next;\r
+ if (op == &refchain)\r
+ return res;\r
+ }\r
+ if (PyList_Append(res, op) < 0) {\r
+ Py_DECREF(res);\r
+ return NULL;\r
+ }\r
+ op = op->_ob_next;\r
+ }\r
+ return res;\r
+}\r
+\r
+#endif\r
+\r
+\r
+/* Hack to force loading of capsule.o */\r
+PyTypeObject *_Py_capsule_hack = &PyCapsule_Type;\r
+\r
+\r
+/* Hack to force loading of cobject.o */\r
+PyTypeObject *_Py_cobject_hack = &PyCObject_Type;\r
+\r
+\r
+/* Hack to force loading of abstract.o */\r
+Py_ssize_t (*_Py_abstract_hack)(PyObject *) = PyObject_Size;\r
+\r
+\r
+/* Python's malloc wrappers (see pymem.h) */\r
+\r
+void *\r
+PyMem_Malloc(size_t nbytes)\r
+{\r
+ return PyMem_MALLOC(nbytes);\r
+}\r
+\r
+void *\r
+PyMem_Realloc(void *p, size_t nbytes)\r
+{\r
+ return PyMem_REALLOC(p, nbytes);\r
+}\r
+\r
+void\r
+PyMem_Free(void *p)\r
+{\r
+ PyMem_FREE(p);\r
+}\r
+\r
+\r
+/* These methods are used to control infinite recursion in repr, str, print,\r
+ etc. Container objects that may recursively contain themselves,\r
+ e.g. builtin dictionaries and lists, should used Py_ReprEnter() and\r
+ Py_ReprLeave() to avoid infinite recursion.\r
+\r
+ Py_ReprEnter() returns 0 the first time it is called for a particular\r
+ object and 1 every time thereafter. It returns -1 if an exception\r
+ occurred. Py_ReprLeave() has no return value.\r
+\r
+ See dictobject.c and listobject.c for examples of use.\r
+*/\r
+\r
+#define KEY "Py_Repr"\r
+\r
+int\r
+Py_ReprEnter(PyObject *obj)\r
+{\r
+ PyObject *dict;\r
+ PyObject *list;\r
+ Py_ssize_t i;\r
+\r
+ dict = PyThreadState_GetDict();\r
+ if (dict == NULL)\r
+ return 0;\r
+ list = PyDict_GetItemString(dict, KEY);\r
+ if (list == NULL) {\r
+ list = PyList_New(0);\r
+ if (list == NULL)\r
+ return -1;\r
+ if (PyDict_SetItemString(dict, KEY, list) < 0)\r
+ return -1;\r
+ Py_DECREF(list);\r
+ }\r
+ i = PyList_GET_SIZE(list);\r
+ while (--i >= 0) {\r
+ if (PyList_GET_ITEM(list, i) == obj)\r
+ return 1;\r
+ }\r
+ PyList_Append(list, obj);\r
+ return 0;\r
+}\r
+\r
+void\r
+Py_ReprLeave(PyObject *obj)\r
+{\r
+ PyObject *dict;\r
+ PyObject *list;\r
+ Py_ssize_t i;\r
+\r
+ dict = PyThreadState_GetDict();\r
+ if (dict == NULL)\r
+ return;\r
+ list = PyDict_GetItemString(dict, KEY);\r
+ if (list == NULL || !PyList_Check(list))\r
+ return;\r
+ i = PyList_GET_SIZE(list);\r
+ /* Count backwards because we always expect obj to be list[-1] */\r
+ while (--i >= 0) {\r
+ if (PyList_GET_ITEM(list, i) == obj) {\r
+ PyList_SetSlice(list, i, i + 1, NULL);\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+/* Trashcan support. */\r
+\r
+/* Current call-stack depth of tp_dealloc calls. */\r
+int _PyTrash_delete_nesting = 0;\r
+\r
+/* List of objects that still need to be cleaned up, singly linked via their\r
+ * gc headers' gc_prev pointers.\r
+ */\r
+PyObject *_PyTrash_delete_later = NULL;\r
+\r
+/* Add op to the _PyTrash_delete_later list. Called when the current\r
+ * call-stack depth gets large. op must be a currently untracked gc'ed\r
+ * object, with refcount 0. Py_DECREF must already have been called on it.\r
+ */\r
+void\r
+_PyTrash_deposit_object(PyObject *op)\r
+{\r
+ assert(PyObject_IS_GC(op));\r
+ assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED);\r
+ assert(op->ob_refcnt == 0);\r
+ _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *)_PyTrash_delete_later;\r
+ _PyTrash_delete_later = op;\r
+}\r
+\r
+/* The equivalent API, using per-thread state recursion info */\r
+void\r
+_PyTrash_thread_deposit_object(PyObject *op)\r
+{\r
+ PyThreadState *tstate = PyThreadState_GET();\r
+ assert(PyObject_IS_GC(op));\r
+ assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED);\r
+ assert(op->ob_refcnt == 0);\r
+ _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *) tstate->trash_delete_later;\r
+ tstate->trash_delete_later = op;\r
+}\r
+\r
+/* Dealloccate all the objects in the _PyTrash_delete_later list. Called when\r
+ * the call-stack unwinds again.\r
+ */\r
+void\r
+_PyTrash_destroy_chain(void)\r
+{\r
+ while (_PyTrash_delete_later) {\r
+ PyObject *op = _PyTrash_delete_later;\r
+ destructor dealloc = Py_TYPE(op)->tp_dealloc;\r
+\r
+ _PyTrash_delete_later =\r
+ (PyObject*) _Py_AS_GC(op)->gc.gc_prev;\r
+\r
+ /* Call the deallocator directly. This used to try to\r
+ * fool Py_DECREF into calling it indirectly, but\r
+ * Py_DECREF was already called on this object, and in\r
+ * assorted non-release builds calling Py_DECREF again ends\r
+ * up distorting allocation statistics.\r
+ */\r
+ assert(op->ob_refcnt == 0);\r
+ ++_PyTrash_delete_nesting;\r
+ (*dealloc)(op);\r
+ --_PyTrash_delete_nesting;\r
+ }\r
+}\r
+\r
+/* The equivalent API, using per-thread state recursion info */\r
+void\r
+_PyTrash_thread_destroy_chain(void)\r
+{\r
+ PyThreadState *tstate = PyThreadState_GET();\r
+ while (tstate->trash_delete_later) {\r
+ PyObject *op = tstate->trash_delete_later;\r
+ destructor dealloc = Py_TYPE(op)->tp_dealloc;\r
+\r
+ tstate->trash_delete_later =\r
+ (PyObject*) _Py_AS_GC(op)->gc.gc_prev;\r
+\r
+ /* Call the deallocator directly. This used to try to\r
+ * fool Py_DECREF into calling it indirectly, but\r
+ * Py_DECREF was already called on this object, and in\r
+ * assorted non-release builds calling Py_DECREF again ends\r
+ * up distorting allocation statistics.\r
+ */\r
+ assert(op->ob_refcnt == 0);\r
+ ++tstate->trash_delete_nesting;\r
+ (*dealloc)(op);\r
+ --tstate->trash_delete_nesting;\r
+ }\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+#include "Python.h"\r
+\r
+#if defined(__has_feature) /* Clang */\r
+ #if __has_feature(address_sanitizer) /* is ASAN enabled? */\r
+ #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \\r
+ __attribute__((no_address_safety_analysis)) \\r
+ __attribute__ ((noinline))\r
+ #else\r
+ #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS\r
+ #endif\r
+#else\r
+ #if defined(__SANITIZE_ADDRESS__) /* GCC 4.8.x, is ASAN enabled? */\r
+ #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \\r
+ __attribute__((no_address_safety_analysis)) \\r
+ __attribute__ ((noinline))\r
+ #else\r
+ #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS\r
+ #endif\r
+#endif\r
+\r
+#ifdef WITH_PYMALLOC\r
+\r
+#ifdef HAVE_MMAP\r
+ #include <sys/mman.h>\r
+ #ifdef MAP_ANONYMOUS\r
+ #define ARENAS_USE_MMAP\r
+ #endif\r
+#endif\r
+\r
+#ifdef WITH_VALGRIND\r
+#include <valgrind/valgrind.h>\r
+\r
+/* If we're using GCC, use __builtin_expect() to reduce overhead of\r
+ the valgrind checks */\r
+#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)\r
+# define UNLIKELY(value) __builtin_expect((value), 0)\r
+#else\r
+# define UNLIKELY(value) (value)\r
+#endif\r
+\r
+/* -1 indicates that we haven't checked that we're running on valgrind yet. */\r
+static int running_on_valgrind = -1;\r
+#endif\r
+\r
+/* An object allocator for Python.\r
+\r
+ Here is an introduction to the layers of the Python memory architecture,\r
+ showing where the object allocator is actually used (layer +2), It is\r
+ called for every object allocation and deallocation (PyObject_New/Del),\r
+ unless the object-specific allocators implement a proprietary allocation\r
+ scheme (ex.: ints use a simple free list). This is also the place where\r
+ the cyclic garbage collector operates selectively on container objects.\r
+\r
+\r
+ Object-specific allocators\r
+ _____ ______ ______ ________\r
+ [ int ] [ dict ] [ list ] ... [ string ] Python core |\r
++3 | <----- Object-specific memory -----> | <-- Non-object memory --> |\r
+ _______________________________ | |\r
+ [ Python's object allocator ] | |\r
++2 | ####### Object memory ####### | <------ Internal buffers ------> |\r
+ ______________________________________________________________ |\r
+ [ Python's raw memory allocator (PyMem_ API) ] |\r
++1 | <----- Python memory (under PyMem manager's control) ------> | |\r
+ __________________________________________________________________\r
+ [ Underlying general-purpose allocator (ex: C library malloc) ]\r
+ 0 | <------ Virtual memory allocated for the python process -------> |\r
+\r
+ =========================================================================\r
+ _______________________________________________________________________\r
+ [ OS-specific Virtual Memory Manager (VMM) ]\r
+-1 | <--- Kernel dynamic storage allocation & management (page-based) ---> |\r
+ __________________________________ __________________________________\r
+ [ ] [ ]\r
+-2 | <-- Physical memory: ROM/RAM --> | | <-- Secondary storage (swap) --> |\r
+\r
+*/\r
+/*==========================================================================*/\r
+\r
+/* A fast, special-purpose memory allocator for small blocks, to be used\r
+ on top of a general-purpose malloc -- heavily based on previous art. */\r
+\r
+/* Vladimir Marangozov -- August 2000 */\r
+\r
+/*\r
+ * "Memory management is where the rubber meets the road -- if we do the wrong\r
+ * thing at any level, the results will not be good. And if we don't make the\r
+ * levels work well together, we are in serious trouble." (1)\r
+ *\r
+ * (1) Paul R. Wilson, Mark S. Johnstone, Michael Neely, and David Boles,\r
+ * "Dynamic Storage Allocation: A Survey and Critical Review",\r
+ * in Proc. 1995 Int'l. Workshop on Memory Management, September 1995.\r
+ */\r
+\r
+/* #undef WITH_MEMORY_LIMITS */ /* disable mem limit checks */\r
+\r
+/*==========================================================================*/\r
+\r
+/*\r
+ * Allocation strategy abstract:\r
+ *\r
+ * For small requests, the allocator sub-allocates <Big> blocks of memory.\r
+ * Requests greater than SMALL_REQUEST_THRESHOLD bytes are routed to the\r
+ * system's allocator. \r
+ *\r
+ * Small requests are grouped in size classes spaced 8 bytes apart, due\r
+ * to the required valid alignment of the returned address. Requests of\r
+ * a particular size are serviced from memory pools of 4K (one VMM page).\r
+ * Pools are fragmented on demand and contain free lists of blocks of one\r
+ * particular size class. In other words, there is a fixed-size allocator\r
+ * for each size class. Free pools are shared by the different allocators\r
+ * thus minimizing the space reserved for a particular size class.\r
+ *\r
+ * This allocation strategy is a variant of what is known as "simple\r
+ * segregated storage based on array of free lists". The main drawback of\r
+ * simple segregated storage is that we might end up with lot of reserved\r
+ * memory for the different free lists, which degenerate in time. To avoid\r
+ * this, we partition each free list in pools and we share dynamically the\r
+ * reserved space between all free lists. This technique is quite efficient\r
+ * for memory intensive programs which allocate mainly small-sized blocks.\r
+ *\r
+ * For small requests we have the following table:\r
+ *\r
+ * Request in bytes Size of allocated block Size class idx\r
+ * ----------------------------------------------------------------\r
+ * 1-8 8 0\r
+ * 9-16 16 1\r
+ * 17-24 24 2\r
+ * 25-32 32 3\r
+ * 33-40 40 4\r
+ * 41-48 48 5\r
+ * 49-56 56 6\r
+ * 57-64 64 7\r
+ * 65-72 72 8\r
+ * ... ... ...\r
+ * 497-504 504 62\r
+ * 505-512 512 63 \r
+ *\r
+ * 0, SMALL_REQUEST_THRESHOLD + 1 and up: routed to the underlying\r
+ * allocator.\r
+ */\r
+\r
+/*==========================================================================*/\r
+\r
+/*\r
+ * -- Main tunable settings section --\r
+ */\r
+\r
+/*\r
+ * Alignment of addresses returned to the user. 8-bytes alignment works\r
+ * on most current architectures (with 32-bit or 64-bit address busses).\r
+ * The alignment value is also used for grouping small requests in size\r
+ * classes spaced ALIGNMENT bytes apart.\r
+ *\r
+ * You shouldn't change this unless you know what you are doing.\r
+ */\r
+#define ALIGNMENT 8 /* must be 2^N */\r
+#define ALIGNMENT_SHIFT 3\r
+#define ALIGNMENT_MASK (ALIGNMENT - 1)\r
+\r
+/* Return the number of bytes in size class I, as a uint. */\r
+#define INDEX2SIZE(I) (((uint)(I) + 1) << ALIGNMENT_SHIFT)\r
+\r
+/*\r
+ * Max size threshold below which malloc requests are considered to be\r
+ * small enough in order to use preallocated memory pools. You can tune\r
+ * this value according to your application behaviour and memory needs.\r
+ *\r
+ * The following invariants must hold:\r
+ * 1) ALIGNMENT <= SMALL_REQUEST_THRESHOLD <= 256\r
+ * 2) SMALL_REQUEST_THRESHOLD is evenly divisible by ALIGNMENT\r
+ *\r
+ * Note: a size threshold of 512 guarantees that newly created dictionaries\r
+ * will be allocated from preallocated memory pools on 64-bit.\r
+ *\r
+ * Although not required, for better performance and space efficiency,\r
+ * it is recommended that SMALL_REQUEST_THRESHOLD is set to a power of 2.\r
+ */\r
+#define SMALL_REQUEST_THRESHOLD 512 \r
+#define NB_SMALL_SIZE_CLASSES (SMALL_REQUEST_THRESHOLD / ALIGNMENT)\r
+\r
+/*\r
+ * The system's VMM page size can be obtained on most unices with a\r
+ * getpagesize() call or deduced from various header files. To make\r
+ * things simpler, we assume that it is 4K, which is OK for most systems.\r
+ * It is probably better if this is the native page size, but it doesn't\r
+ * have to be. In theory, if SYSTEM_PAGE_SIZE is larger than the native page\r
+ * size, then `POOL_ADDR(p)->arenaindex' could rarely cause a segmentation\r
+ * violation fault. 4K is apparently OK for all the platforms that python\r
+ * currently targets.\r
+ */\r
+#define SYSTEM_PAGE_SIZE (4 * 1024)\r
+#define SYSTEM_PAGE_SIZE_MASK (SYSTEM_PAGE_SIZE - 1)\r
+\r
+/*\r
+ * Maximum amount of memory managed by the allocator for small requests.\r
+ */\r
+#ifdef WITH_MEMORY_LIMITS\r
+#ifndef SMALL_MEMORY_LIMIT\r
+#define SMALL_MEMORY_LIMIT (64 * 1024 * 1024) /* 64 MB -- more? */\r
+#endif\r
+#endif\r
+\r
+/*\r
+ * The allocator sub-allocates <Big> blocks of memory (called arenas) aligned\r
+ * on a page boundary. This is a reserved virtual address space for the\r
+ * current process (obtained through a malloc()/mmap() call). In no way this\r
+ * means that the memory arenas will be used entirely. A malloc(<Big>) is\r
+ * usually an address range reservation for <Big> bytes, unless all pages within\r
+ * this space are referenced subsequently. So malloc'ing big blocks and not\r
+ * using them does not mean "wasting memory". It's an addressable range\r
+ * wastage... \r
+ *\r
+ * Arenas are allocated with mmap() on systems supporting anonymous memory\r
+ * mappings to reduce heap fragmentation.\r
+ */\r
+#define ARENA_SIZE (256 << 10) /* 256KB */\r
+\r
+#ifdef WITH_MEMORY_LIMITS\r
+#define MAX_ARENAS (SMALL_MEMORY_LIMIT / ARENA_SIZE)\r
+#endif\r
+\r
+/*\r
+ * Size of the pools used for small blocks. Should be a power of 2,\r
+ * between 1K and SYSTEM_PAGE_SIZE, that is: 1k, 2k, 4k.\r
+ */\r
+#define POOL_SIZE SYSTEM_PAGE_SIZE /* must be 2^N */\r
+#define POOL_SIZE_MASK SYSTEM_PAGE_SIZE_MASK\r
+\r
+/*\r
+ * -- End of tunable settings section --\r
+ */\r
+\r
+/*==========================================================================*/\r
+\r
+/*\r
+ * Locking\r
+ *\r
+ * To reduce lock contention, it would probably be better to refine the\r
+ * crude function locking with per size class locking. I'm not positive\r
+ * however, whether it's worth switching to such locking policy because\r
+ * of the performance penalty it might introduce.\r
+ *\r
+ * The following macros describe the simplest (should also be the fastest)\r
+ * lock object on a particular platform and the init/fini/lock/unlock\r
+ * operations on it. The locks defined here are not expected to be recursive\r
+ * because it is assumed that they will always be called in the order:\r
+ * INIT, [LOCK, UNLOCK]*, FINI.\r
+ */\r
+\r
+/*\r
+ * Python's threads are serialized, so object malloc locking is disabled.\r
+ */\r
+#define SIMPLELOCK_DECL(lock) /* simple lock declaration */\r
+#define SIMPLELOCK_INIT(lock) /* allocate (if needed) and initialize */\r
+#define SIMPLELOCK_FINI(lock) /* free/destroy an existing lock */\r
+#define SIMPLELOCK_LOCK(lock) /* acquire released lock */\r
+#define SIMPLELOCK_UNLOCK(lock) /* release acquired lock */\r
+\r
+/*\r
+ * Basic types\r
+ * I don't care if these are defined in <sys/types.h> or elsewhere. Axiom.\r
+ */\r
+#undef uchar\r
+#define uchar unsigned char /* assuming == 8 bits */\r
+\r
+#undef uint\r
+#define uint unsigned int /* assuming >= 16 bits */\r
+\r
+#undef ulong\r
+#define ulong unsigned long /* assuming >= 32 bits */\r
+\r
+#undef uptr\r
+#define uptr Py_uintptr_t\r
+\r
+/* When you say memory, my mind reasons in terms of (pointers to) blocks */\r
+typedef uchar block;\r
+\r
+/* Pool for small blocks. */\r
+struct pool_header {\r
+ union { block *_padding;\r
+ uint count; } ref; /* number of allocated blocks */\r
+ block *freeblock; /* pool's free list head */\r
+ struct pool_header *nextpool; /* next pool of this size class */\r
+ struct pool_header *prevpool; /* previous pool "" */\r
+ uint arenaindex; /* index into arenas of base adr */\r
+ uint szidx; /* block size class index */\r
+ uint nextoffset; /* bytes to virgin block */\r
+ uint maxnextoffset; /* largest valid nextoffset */\r
+};\r
+\r
+typedef struct pool_header *poolp;\r
+\r
+/* Record keeping for arenas. */\r
+struct arena_object {\r
+ /* The address of the arena, as returned by malloc. Note that 0\r
+ * will never be returned by a successful malloc, and is used\r
+ * here to mark an arena_object that doesn't correspond to an\r
+ * allocated arena.\r
+ */\r
+ uptr address;\r
+\r
+ /* Pool-aligned pointer to the next pool to be carved off. */\r
+ block* pool_address;\r
+\r
+ /* The number of available pools in the arena: free pools + never-\r
+ * allocated pools.\r
+ */\r
+ uint nfreepools;\r
+\r
+ /* The total number of pools in the arena, whether or not available. */\r
+ uint ntotalpools;\r
+\r
+ /* Singly-linked list of available pools. */\r
+ struct pool_header* freepools;\r
+\r
+ /* Whenever this arena_object is not associated with an allocated\r
+ * arena, the nextarena member is used to link all unassociated\r
+ * arena_objects in the singly-linked `unused_arena_objects` list.\r
+ * The prevarena member is unused in this case.\r
+ *\r
+ * When this arena_object is associated with an allocated arena\r
+ * with at least one available pool, both members are used in the\r
+ * doubly-linked `usable_arenas` list, which is maintained in\r
+ * increasing order of `nfreepools` values.\r
+ *\r
+ * Else this arena_object is associated with an allocated arena\r
+ * all of whose pools are in use. `nextarena` and `prevarena`\r
+ * are both meaningless in this case.\r
+ */\r
+ struct arena_object* nextarena;\r
+ struct arena_object* prevarena;\r
+};\r
+\r
+#undef ROUNDUP\r
+#define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)\r
+#define POOL_OVERHEAD ROUNDUP(sizeof(struct pool_header))\r
+\r
+#define DUMMY_SIZE_IDX 0xffff /* size class of newly cached pools */\r
+\r
+/* Round pointer P down to the closest pool-aligned address <= P, as a poolp */\r
+#define POOL_ADDR(P) ((poolp)((uptr)(P) & ~(uptr)POOL_SIZE_MASK))\r
+\r
+/* Return total number of blocks in pool of size index I, as a uint. */\r
+#define NUMBLOCKS(I) ((uint)(POOL_SIZE - POOL_OVERHEAD) / INDEX2SIZE(I))\r
+\r
+/*==========================================================================*/\r
+\r
+/*\r
+ * This malloc lock\r
+ */\r
+SIMPLELOCK_DECL(_malloc_lock)\r
+#define LOCK() SIMPLELOCK_LOCK(_malloc_lock)\r
+#define UNLOCK() SIMPLELOCK_UNLOCK(_malloc_lock)\r
+#define LOCK_INIT() SIMPLELOCK_INIT(_malloc_lock)\r
+#define LOCK_FINI() SIMPLELOCK_FINI(_malloc_lock)\r
+\r
+/*\r
+ * Pool table -- headed, circular, doubly-linked lists of partially used pools.\r
+\r
+This is involved. For an index i, usedpools[i+i] is the header for a list of\r
+all partially used pools holding small blocks with "size class idx" i. So\r
+usedpools[0] corresponds to blocks of size 8, usedpools[2] to blocks of size\r
+16, and so on: index 2*i <-> blocks of size (i+1)<<ALIGNMENT_SHIFT.\r
+\r
+Pools are carved off an arena's highwater mark (an arena_object's pool_address\r
+member) as needed. Once carved off, a pool is in one of three states forever\r
+after:\r
+\r
+used == partially used, neither empty nor full\r
+ At least one block in the pool is currently allocated, and at least one\r
+ block in the pool is not currently allocated (note this implies a pool\r
+ has room for at least two blocks).\r
+ This is a pool's initial state, as a pool is created only when malloc\r
+ needs space.\r
+ The pool holds blocks of a fixed size, and is in the circular list headed\r
+ at usedpools[i] (see above). It's linked to the other used pools of the\r
+ same size class via the pool_header's nextpool and prevpool members.\r
+ If all but one block is currently allocated, a malloc can cause a\r
+ transition to the full state. If all but one block is not currently\r
+ allocated, a free can cause a transition to the empty state.\r
+\r
+full == all the pool's blocks are currently allocated\r
+ On transition to full, a pool is unlinked from its usedpools[] list.\r
+ It's not linked to from anything then anymore, and its nextpool and\r
+ prevpool members are meaningless until it transitions back to used.\r
+ A free of a block in a full pool puts the pool back in the used state.\r
+ Then it's linked in at the front of the appropriate usedpools[] list, so\r
+ that the next allocation for its size class will reuse the freed block.\r
+\r
+empty == all the pool's blocks are currently available for allocation\r
+ On transition to empty, a pool is unlinked from its usedpools[] list,\r
+ and linked to the front of its arena_object's singly-linked freepools list,\r
+ via its nextpool member. The prevpool member has no meaning in this case.\r
+ Empty pools have no inherent size class: the next time a malloc finds\r
+ an empty list in usedpools[], it takes the first pool off of freepools.\r
+ If the size class needed happens to be the same as the size class the pool\r
+ last had, some pool initialization can be skipped.\r
+\r
+\r
+Block Management\r
+\r
+Blocks within pools are again carved out as needed. pool->freeblock points to\r
+the start of a singly-linked list of free blocks within the pool. When a\r
+block is freed, it's inserted at the front of its pool's freeblock list. Note\r
+that the available blocks in a pool are *not* linked all together when a pool\r
+is initialized. Instead only "the first two" (lowest addresses) blocks are\r
+set up, returning the first such block, and setting pool->freeblock to a\r
+one-block list holding the second such block. This is consistent with that\r
+pymalloc strives at all levels (arena, pool, and block) never to touch a piece\r
+of memory until it's actually needed.\r
+\r
+So long as a pool is in the used state, we're certain there *is* a block\r
+available for allocating, and pool->freeblock is not NULL. If pool->freeblock\r
+points to the end of the free list before we've carved the entire pool into\r
+blocks, that means we simply haven't yet gotten to one of the higher-address\r
+blocks. The offset from the pool_header to the start of "the next" virgin\r
+block is stored in the pool_header nextoffset member, and the largest value\r
+of nextoffset that makes sense is stored in the maxnextoffset member when a\r
+pool is initialized. All the blocks in a pool have been passed out at least\r
+once when and only when nextoffset > maxnextoffset.\r
+\r
+\r
+Major obscurity: While the usedpools vector is declared to have poolp\r
+entries, it doesn't really. It really contains two pointers per (conceptual)\r
+poolp entry, the nextpool and prevpool members of a pool_header. The\r
+excruciating initialization code below fools C so that\r
+\r
+ usedpool[i+i]\r
+\r
+"acts like" a genuine poolp, but only so long as you only reference its\r
+nextpool and prevpool members. The "- 2*sizeof(block *)" gibberish is\r
+compensating for that a pool_header's nextpool and prevpool members\r
+immediately follow a pool_header's first two members:\r
+\r
+ union { block *_padding;\r
+ uint count; } ref;\r
+ block *freeblock;\r
+\r
+each of which consume sizeof(block *) bytes. So what usedpools[i+i] really\r
+contains is a fudged-up pointer p such that *if* C believes it's a poolp\r
+pointer, then p->nextpool and p->prevpool are both p (meaning that the headed\r
+circular list is empty).\r
+\r
+It's unclear why the usedpools setup is so convoluted. It could be to\r
+minimize the amount of cache required to hold this heavily-referenced table\r
+(which only *needs* the two interpool pointer members of a pool_header). OTOH,\r
+referencing code has to remember to "double the index" and doing so isn't\r
+free, usedpools[0] isn't a strictly legal pointer, and we're crucially relying\r
+on that C doesn't insert any padding anywhere in a pool_header at or before\r
+the prevpool member.\r
+**************************************************************************** */\r
+\r
+#define PTA(x) ((poolp )((uchar *)&(usedpools[2*(x)]) - 2*sizeof(block *)))\r
+#define PT(x) PTA(x), PTA(x)\r
+\r
+static poolp usedpools[2 * ((NB_SMALL_SIZE_CLASSES + 7) / 8) * 8] = {\r
+ PT(0), PT(1), PT(2), PT(3), PT(4), PT(5), PT(6), PT(7)\r
+#if NB_SMALL_SIZE_CLASSES > 8\r
+ , PT(8), PT(9), PT(10), PT(11), PT(12), PT(13), PT(14), PT(15)\r
+#if NB_SMALL_SIZE_CLASSES > 16\r
+ , PT(16), PT(17), PT(18), PT(19), PT(20), PT(21), PT(22), PT(23)\r
+#if NB_SMALL_SIZE_CLASSES > 24\r
+ , PT(24), PT(25), PT(26), PT(27), PT(28), PT(29), PT(30), PT(31)\r
+#if NB_SMALL_SIZE_CLASSES > 32\r
+ , PT(32), PT(33), PT(34), PT(35), PT(36), PT(37), PT(38), PT(39)\r
+#if NB_SMALL_SIZE_CLASSES > 40\r
+ , PT(40), PT(41), PT(42), PT(43), PT(44), PT(45), PT(46), PT(47)\r
+#if NB_SMALL_SIZE_CLASSES > 48\r
+ , PT(48), PT(49), PT(50), PT(51), PT(52), PT(53), PT(54), PT(55)\r
+#if NB_SMALL_SIZE_CLASSES > 56\r
+ , PT(56), PT(57), PT(58), PT(59), PT(60), PT(61), PT(62), PT(63)\r
+#if NB_SMALL_SIZE_CLASSES > 64\r
+#error "NB_SMALL_SIZE_CLASSES should be less than 64"\r
+#endif /* NB_SMALL_SIZE_CLASSES > 64 */\r
+#endif /* NB_SMALL_SIZE_CLASSES > 56 */\r
+#endif /* NB_SMALL_SIZE_CLASSES > 48 */\r
+#endif /* NB_SMALL_SIZE_CLASSES > 40 */\r
+#endif /* NB_SMALL_SIZE_CLASSES > 32 */\r
+#endif /* NB_SMALL_SIZE_CLASSES > 24 */\r
+#endif /* NB_SMALL_SIZE_CLASSES > 16 */\r
+#endif /* NB_SMALL_SIZE_CLASSES > 8 */\r
+};\r
+\r
+/*==========================================================================\r
+Arena management.\r
+\r
+`arenas` is a vector of arena_objects. It contains maxarenas entries, some of\r
+which may not be currently used (== they're arena_objects that aren't\r
+currently associated with an allocated arena). Note that arenas proper are\r
+separately malloc'ed.\r
+\r
+Prior to Python 2.5, arenas were never free()'ed. Starting with Python 2.5,\r
+we do try to free() arenas, and use some mild heuristic strategies to increase\r
+the likelihood that arenas eventually can be freed.\r
+\r
+unused_arena_objects\r
+\r
+ This is a singly-linked list of the arena_objects that are currently not\r
+ being used (no arena is associated with them). Objects are taken off the\r
+ head of the list in new_arena(), and are pushed on the head of the list in\r
+ PyObject_Free() when the arena is empty. Key invariant: an arena_object\r
+ is on this list if and only if its .address member is 0.\r
+\r
+usable_arenas\r
+\r
+ This is a doubly-linked list of the arena_objects associated with arenas\r
+ that have pools available. These pools are either waiting to be reused,\r
+ or have not been used before. The list is sorted to have the most-\r
+ allocated arenas first (ascending order based on the nfreepools member).\r
+ This means that the next allocation will come from a heavily used arena,\r
+ which gives the nearly empty arenas a chance to be returned to the system.\r
+ In my unscientific tests this dramatically improved the number of arenas\r
+ that could be freed.\r
+\r
+Note that an arena_object associated with an arena all of whose pools are\r
+currently in use isn't on either list.\r
+*/\r
+\r
+/* Array of objects used to track chunks of memory (arenas). */\r
+static struct arena_object* arenas = NULL;\r
+/* Number of slots currently allocated in the `arenas` vector. */\r
+static uint maxarenas = 0;\r
+\r
+/* The head of the singly-linked, NULL-terminated list of available\r
+ * arena_objects.\r
+ */\r
+static struct arena_object* unused_arena_objects = NULL;\r
+\r
+/* The head of the doubly-linked, NULL-terminated at each end, list of\r
+ * arena_objects associated with arenas that have pools available.\r
+ */\r
+static struct arena_object* usable_arenas = NULL;\r
+\r
+/* How many arena_objects do we initially allocate?\r
+ * 16 = can allocate 16 arenas = 16 * ARENA_SIZE = 4MB before growing the\r
+ * `arenas` vector.\r
+ */\r
+#define INITIAL_ARENA_OBJECTS 16\r
+\r
+/* Number of arenas allocated that haven't been free()'d. */\r
+static size_t narenas_currently_allocated = 0;\r
+\r
+#ifdef PYMALLOC_DEBUG\r
+/* Total number of times malloc() called to allocate an arena. */\r
+static size_t ntimes_arena_allocated = 0;\r
+/* High water mark (max value ever seen) for narenas_currently_allocated. */\r
+static size_t narenas_highwater = 0;\r
+#endif\r
+\r
+/* Allocate a new arena. If we run out of memory, return NULL. Else\r
+ * allocate a new arena, and return the address of an arena_object\r
+ * describing the new arena. It's expected that the caller will set\r
+ * `usable_arenas` to the return value.\r
+ */\r
+static struct arena_object*\r
+new_arena(void)\r
+{\r
+ struct arena_object* arenaobj;\r
+ uint excess; /* number of bytes above pool alignment */\r
+ void *address;\r
+ int err;\r
+\r
+#ifdef PYMALLOC_DEBUG\r
+ if (Py_GETENV("PYTHONMALLOCSTATS"))\r
+ _PyObject_DebugMallocStats();\r
+#endif\r
+ if (unused_arena_objects == NULL) {\r
+ uint i;\r
+ uint numarenas;\r
+ size_t nbytes;\r
+\r
+ /* Double the number of arena objects on each allocation.\r
+ * Note that it's possible for `numarenas` to overflow.\r
+ */\r
+ numarenas = maxarenas ? maxarenas << 1 : INITIAL_ARENA_OBJECTS;\r
+ if (numarenas <= maxarenas)\r
+ return NULL; /* overflow */\r
+#if SIZEOF_SIZE_T <= SIZEOF_INT\r
+ if (numarenas > PY_SIZE_MAX / sizeof(*arenas))\r
+ return NULL; /* overflow */\r
+#endif\r
+ nbytes = numarenas * sizeof(*arenas);\r
+ arenaobj = (struct arena_object *)realloc(arenas, nbytes);\r
+ if (arenaobj == NULL)\r
+ return NULL;\r
+ arenas = arenaobj;\r
+\r
+ /* We might need to fix pointers that were copied. However,\r
+ * new_arena only gets called when all the pages in the\r
+ * previous arenas are full. Thus, there are *no* pointers\r
+ * into the old array. Thus, we don't have to worry about\r
+ * invalid pointers. Just to be sure, some asserts:\r
+ */\r
+ assert(usable_arenas == NULL);\r
+ assert(unused_arena_objects == NULL);\r
+\r
+ /* Put the new arenas on the unused_arena_objects list. */\r
+ for (i = maxarenas; i < numarenas; ++i) {\r
+ arenas[i].address = 0; /* mark as unassociated */\r
+ arenas[i].nextarena = i < numarenas - 1 ?\r
+ &arenas[i+1] : NULL;\r
+ }\r
+\r
+ /* Update globals. */\r
+ unused_arena_objects = &arenas[maxarenas];\r
+ maxarenas = numarenas;\r
+ }\r
+\r
+ /* Take the next available arena object off the head of the list. */\r
+ assert(unused_arena_objects != NULL);\r
+ arenaobj = unused_arena_objects;\r
+ unused_arena_objects = arenaobj->nextarena;\r
+ assert(arenaobj->address == 0);\r
+#ifdef ARENAS_USE_MMAP\r
+ address = mmap(NULL, ARENA_SIZE, PROT_READ|PROT_WRITE,\r
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);\r
+ err = (address == MAP_FAILED);\r
+#else\r
+ address = malloc(ARENA_SIZE);\r
+ err = (address == 0);\r
+#endif \r
+ if (err) {\r
+ /* The allocation failed: return NULL after putting the\r
+ * arenaobj back.\r
+ */\r
+ arenaobj->nextarena = unused_arena_objects;\r
+ unused_arena_objects = arenaobj;\r
+ return NULL;\r
+ }\r
+ arenaobj->address = (uptr)address;\r
+\r
+ ++narenas_currently_allocated;\r
+#ifdef PYMALLOC_DEBUG\r
+ ++ntimes_arena_allocated;\r
+ if (narenas_currently_allocated > narenas_highwater)\r
+ narenas_highwater = narenas_currently_allocated;\r
+#endif\r
+ arenaobj->freepools = NULL;\r
+ /* pool_address <- first pool-aligned address in the arena\r
+ nfreepools <- number of whole pools that fit after alignment */\r
+ arenaobj->pool_address = (block*)arenaobj->address;\r
+ arenaobj->nfreepools = ARENA_SIZE / POOL_SIZE;\r
+ assert(POOL_SIZE * arenaobj->nfreepools == ARENA_SIZE);\r
+ excess = (uint)(arenaobj->address & POOL_SIZE_MASK);\r
+ if (excess != 0) {\r
+ --arenaobj->nfreepools;\r
+ arenaobj->pool_address += POOL_SIZE - excess;\r
+ }\r
+ arenaobj->ntotalpools = arenaobj->nfreepools;\r
+\r
+ return arenaobj;\r
+}\r
+\r
+/*\r
+Py_ADDRESS_IN_RANGE(P, POOL)\r
+\r
+Return true if and only if P is an address that was allocated by pymalloc.\r
+POOL must be the pool address associated with P, i.e., POOL = POOL_ADDR(P)\r
+(the caller is asked to compute this because the macro expands POOL more than\r
+once, and for efficiency it's best for the caller to assign POOL_ADDR(P) to a\r
+variable and pass the latter to the macro; because Py_ADDRESS_IN_RANGE is\r
+called on every alloc/realloc/free, micro-efficiency is important here).\r
+\r
+Tricky: Let B be the arena base address associated with the pool, B =\r
+arenas[(POOL)->arenaindex].address. Then P belongs to the arena if and only if\r
+\r
+ B <= P < B + ARENA_SIZE\r
+\r
+Subtracting B throughout, this is true iff\r
+\r
+ 0 <= P-B < ARENA_SIZE\r
+\r
+By using unsigned arithmetic, the "0 <=" half of the test can be skipped.\r
+\r
+Obscure: A PyMem "free memory" function can call the pymalloc free or realloc\r
+before the first arena has been allocated. `arenas` is still NULL in that\r
+case. We're relying on that maxarenas is also 0 in that case, so that\r
+(POOL)->arenaindex < maxarenas must be false, saving us from trying to index\r
+into a NULL arenas.\r
+\r
+Details: given P and POOL, the arena_object corresponding to P is AO =\r
+arenas[(POOL)->arenaindex]. Suppose obmalloc controls P. Then (barring wild\r
+stores, etc), POOL is the correct address of P's pool, AO.address is the\r
+correct base address of the pool's arena, and P must be within ARENA_SIZE of\r
+AO.address. In addition, AO.address is not 0 (no arena can start at address 0\r
+(NULL)). Therefore Py_ADDRESS_IN_RANGE correctly reports that obmalloc\r
+controls P.\r
+\r
+Now suppose obmalloc does not control P (e.g., P was obtained via a direct\r
+call to the system malloc() or realloc()). (POOL)->arenaindex may be anything\r
+in this case -- it may even be uninitialized trash. If the trash arenaindex\r
+is >= maxarenas, the macro correctly concludes at once that obmalloc doesn't\r
+control P.\r
+\r
+Else arenaindex is < maxarena, and AO is read up. If AO corresponds to an\r
+allocated arena, obmalloc controls all the memory in slice AO.address :\r
+AO.address+ARENA_SIZE. By case assumption, P is not controlled by obmalloc,\r
+so P doesn't lie in that slice, so the macro correctly reports that P is not\r
+controlled by obmalloc.\r
+\r
+Finally, if P is not controlled by obmalloc and AO corresponds to an unused\r
+arena_object (one not currently associated with an allocated arena),\r
+AO.address is 0, and the second test in the macro reduces to:\r
+\r
+ P < ARENA_SIZE\r
+\r
+If P >= ARENA_SIZE (extremely likely), the macro again correctly concludes\r
+that P is not controlled by obmalloc. However, if P < ARENA_SIZE, this part\r
+of the test still passes, and the third clause (AO.address != 0) is necessary\r
+to get the correct result: AO.address is 0 in this case, so the macro\r
+correctly reports that P is not controlled by obmalloc (despite that P lies in\r
+slice AO.address : AO.address + ARENA_SIZE).\r
+\r
+Note: The third (AO.address != 0) clause was added in Python 2.5. Before\r
+2.5, arenas were never free()'ed, and an arenaindex < maxarena always\r
+corresponded to a currently-allocated arena, so the "P is not controlled by\r
+obmalloc, AO corresponds to an unused arena_object, and P < ARENA_SIZE" case\r
+was impossible.\r
+\r
+Note that the logic is excruciating, and reading up possibly uninitialized\r
+memory when P is not controlled by obmalloc (to get at (POOL)->arenaindex)\r
+creates problems for some memory debuggers. The overwhelming advantage is\r
+that this test determines whether an arbitrary address is controlled by\r
+obmalloc in a small constant time, independent of the number of arenas\r
+obmalloc controls. Since this test is needed at every entry point, it's\r
+extremely desirable that it be this fast.\r
+\r
+Since Py_ADDRESS_IN_RANGE may be reading from memory which was not allocated\r
+by Python, it is important that (POOL)->arenaindex is read only once, as\r
+another thread may be concurrently modifying the value without holding the\r
+GIL. To accomplish this, the arenaindex_temp variable is used to store\r
+(POOL)->arenaindex for the duration of the Py_ADDRESS_IN_RANGE macro's\r
+execution. The caller of the macro is responsible for declaring this\r
+variable.\r
+*/\r
+#define Py_ADDRESS_IN_RANGE(P, POOL) \\r
+ ((arenaindex_temp = (POOL)->arenaindex) < maxarenas && \\r
+ (uptr)(P) - arenas[arenaindex_temp].address < (uptr)ARENA_SIZE && \\r
+ arenas[arenaindex_temp].address != 0)\r
+\r
+\r
+/* This is only useful when running memory debuggers such as\r
+ * Purify or Valgrind. Uncomment to use.\r
+ *\r
+#define Py_USING_MEMORY_DEBUGGER\r
+ */\r
+\r
+#ifdef Py_USING_MEMORY_DEBUGGER\r
+\r
+/* Py_ADDRESS_IN_RANGE may access uninitialized memory by design\r
+ * This leads to thousands of spurious warnings when using\r
+ * Purify or Valgrind. By making a function, we can easily\r
+ * suppress the uninitialized memory reads in this one function.\r
+ * So we won't ignore real errors elsewhere.\r
+ *\r
+ * Disable the macro and use a function.\r
+ */\r
+\r
+#undef Py_ADDRESS_IN_RANGE\r
+\r
+#if defined(__GNUC__) && ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) || \\r
+ (__GNUC__ >= 4))\r
+#define Py_NO_INLINE __attribute__((__noinline__))\r
+#else\r
+#define Py_NO_INLINE\r
+#endif\r
+\r
+/* Don't make static, to try to ensure this isn't inlined. */\r
+int Py_ADDRESS_IN_RANGE(void *P, poolp pool) Py_NO_INLINE;\r
+#undef Py_NO_INLINE\r
+#endif\r
+\r
+/*==========================================================================*/\r
+\r
+/* malloc. Note that nbytes==0 tries to return a non-NULL pointer, distinct\r
+ * from all other currently live pointers. This may not be possible.\r
+ */\r
+\r
+/*\r
+ * The basic blocks are ordered by decreasing execution frequency,\r
+ * which minimizes the number of jumps in the most common cases,\r
+ * improves branching prediction and instruction scheduling (small\r
+ * block allocations typically result in a couple of instructions).\r
+ * Unless the optimizer reorders everything, being too smart...\r
+ */\r
+\r
+#undef PyObject_Malloc\r
+void *\r
+PyObject_Malloc(size_t nbytes)\r
+{\r
+ block *bp;\r
+ poolp pool;\r
+ poolp next;\r
+ uint size;\r
+\r
+#ifdef WITH_VALGRIND\r
+ if (UNLIKELY(running_on_valgrind == -1))\r
+ running_on_valgrind = RUNNING_ON_VALGRIND;\r
+ if (UNLIKELY(running_on_valgrind))\r
+ goto redirect;\r
+#endif\r
+\r
+ /*\r
+ * Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes.\r
+ * Most python internals blindly use a signed Py_ssize_t to track\r
+ * things without checking for overflows or negatives.\r
+ * As size_t is unsigned, checking for nbytes < 0 is not required.\r
+ */\r
+ if (nbytes > PY_SSIZE_T_MAX)\r
+ return NULL;\r
+\r
+ /*\r
+ * This implicitly redirects malloc(0).\r
+ */\r
+ if ((nbytes - 1) < SMALL_REQUEST_THRESHOLD) {\r
+ LOCK();\r
+ /*\r
+ * Most frequent paths first\r
+ */\r
+ size = (uint)(nbytes - 1) >> ALIGNMENT_SHIFT;\r
+ pool = usedpools[size + size];\r
+ if (pool != pool->nextpool) {\r
+ /*\r
+ * There is a used pool for this size class.\r
+ * Pick up the head block of its free list.\r
+ */\r
+ ++pool->ref.count;\r
+ bp = pool->freeblock;\r
+ assert(bp != NULL);\r
+ if ((pool->freeblock = *(block **)bp) != NULL) {\r
+ UNLOCK();\r
+ return (void *)bp;\r
+ }\r
+ /*\r
+ * Reached the end of the free list, try to extend it.\r
+ */\r
+ if (pool->nextoffset <= pool->maxnextoffset) {\r
+ /* There is room for another block. */\r
+ pool->freeblock = (block*)pool +\r
+ pool->nextoffset;\r
+ pool->nextoffset += INDEX2SIZE(size);\r
+ *(block **)(pool->freeblock) = NULL;\r
+ UNLOCK();\r
+ return (void *)bp;\r
+ }\r
+ /* Pool is full, unlink from used pools. */\r
+ next = pool->nextpool;\r
+ pool = pool->prevpool;\r
+ next->prevpool = pool;\r
+ pool->nextpool = next;\r
+ UNLOCK();\r
+ return (void *)bp;\r
+ }\r
+\r
+ /* There isn't a pool of the right size class immediately\r
+ * available: use a free pool.\r
+ */\r
+ if (usable_arenas == NULL) {\r
+ /* No arena has a free pool: allocate a new arena. */\r
+#ifdef WITH_MEMORY_LIMITS\r
+ if (narenas_currently_allocated >= MAX_ARENAS) {\r
+ UNLOCK();\r
+ goto redirect;\r
+ }\r
+#endif\r
+ usable_arenas = new_arena();\r
+ if (usable_arenas == NULL) {\r
+ UNLOCK();\r
+ goto redirect;\r
+ }\r
+ usable_arenas->nextarena =\r
+ usable_arenas->prevarena = NULL;\r
+ }\r
+ assert(usable_arenas->address != 0);\r
+\r
+ /* Try to get a cached free pool. */\r
+ pool = usable_arenas->freepools;\r
+ if (pool != NULL) {\r
+ /* Unlink from cached pools. */\r
+ usable_arenas->freepools = pool->nextpool;\r
+\r
+ /* This arena already had the smallest nfreepools\r
+ * value, so decreasing nfreepools doesn't change\r
+ * that, and we don't need to rearrange the\r
+ * usable_arenas list. However, if the arena has\r
+ * become wholly allocated, we need to remove its\r
+ * arena_object from usable_arenas.\r
+ */\r
+ --usable_arenas->nfreepools;\r
+ if (usable_arenas->nfreepools == 0) {\r
+ /* Wholly allocated: remove. */\r
+ assert(usable_arenas->freepools == NULL);\r
+ assert(usable_arenas->nextarena == NULL ||\r
+ usable_arenas->nextarena->prevarena ==\r
+ usable_arenas);\r
+\r
+ usable_arenas = usable_arenas->nextarena;\r
+ if (usable_arenas != NULL) {\r
+ usable_arenas->prevarena = NULL;\r
+ assert(usable_arenas->address != 0);\r
+ }\r
+ }\r
+ else {\r
+ /* nfreepools > 0: it must be that freepools\r
+ * isn't NULL, or that we haven't yet carved\r
+ * off all the arena's pools for the first\r
+ * time.\r
+ */\r
+ assert(usable_arenas->freepools != NULL ||\r
+ usable_arenas->pool_address <=\r
+ (block*)usable_arenas->address +\r
+ ARENA_SIZE - POOL_SIZE);\r
+ }\r
+ init_pool:\r
+ /* Frontlink to used pools. */\r
+ next = usedpools[size + size]; /* == prev */\r
+ pool->nextpool = next;\r
+ pool->prevpool = next;\r
+ next->nextpool = pool;\r
+ next->prevpool = pool;\r
+ pool->ref.count = 1;\r
+ if (pool->szidx == size) {\r
+ /* Luckily, this pool last contained blocks\r
+ * of the same size class, so its header\r
+ * and free list are already initialized.\r
+ */\r
+ bp = pool->freeblock;\r
+ pool->freeblock = *(block **)bp;\r
+ UNLOCK();\r
+ return (void *)bp;\r
+ }\r
+ /*\r
+ * Initialize the pool header, set up the free list to\r
+ * contain just the second block, and return the first\r
+ * block.\r
+ */\r
+ pool->szidx = size;\r
+ size = INDEX2SIZE(size);\r
+ bp = (block *)pool + POOL_OVERHEAD;\r
+ pool->nextoffset = POOL_OVERHEAD + (size << 1);\r
+ pool->maxnextoffset = POOL_SIZE - size;\r
+ pool->freeblock = bp + size;\r
+ *(block **)(pool->freeblock) = NULL;\r
+ UNLOCK();\r
+ return (void *)bp;\r
+ }\r
+\r
+ /* Carve off a new pool. */\r
+ assert(usable_arenas->nfreepools > 0);\r
+ assert(usable_arenas->freepools == NULL);\r
+ pool = (poolp)usable_arenas->pool_address;\r
+ assert((block*)pool <= (block*)usable_arenas->address +\r
+ ARENA_SIZE - POOL_SIZE);\r
+ pool->arenaindex = usable_arenas - arenas;\r
+ assert(&arenas[pool->arenaindex] == usable_arenas);\r
+ pool->szidx = DUMMY_SIZE_IDX;\r
+ usable_arenas->pool_address += POOL_SIZE;\r
+ --usable_arenas->nfreepools;\r
+\r
+ if (usable_arenas->nfreepools == 0) {\r
+ assert(usable_arenas->nextarena == NULL ||\r
+ usable_arenas->nextarena->prevarena ==\r
+ usable_arenas);\r
+ /* Unlink the arena: it is completely allocated. */\r
+ usable_arenas = usable_arenas->nextarena;\r
+ if (usable_arenas != NULL) {\r
+ usable_arenas->prevarena = NULL;\r
+ assert(usable_arenas->address != 0);\r
+ }\r
+ }\r
+\r
+ goto init_pool;\r
+ }\r
+\r
+ /* The small block allocator ends here. */\r
+\r
+redirect:\r
+ /* Redirect the original request to the underlying (libc) allocator.\r
+ * We jump here on bigger requests, on error in the code above (as a\r
+ * last chance to serve the request) or when the max memory limit\r
+ * has been reached.\r
+ */\r
+ if (nbytes == 0)\r
+ nbytes = 1;\r
+ return (void *)malloc(nbytes);\r
+}\r
+\r
+/* free */\r
+\r
+#undef PyObject_Free\r
+ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS\r
+void\r
+PyObject_Free(void *p)\r
+{\r
+ poolp pool;\r
+ block *lastfree;\r
+ poolp next, prev;\r
+ uint size;\r
+#ifndef Py_USING_MEMORY_DEBUGGER\r
+ uint arenaindex_temp;\r
+#endif\r
+\r
+ if (p == NULL) /* free(NULL) has no effect */\r
+ return;\r
+\r
+#ifdef WITH_VALGRIND\r
+ if (UNLIKELY(running_on_valgrind > 0))\r
+ goto redirect;\r
+#endif\r
+\r
+ pool = POOL_ADDR(p);\r
+ if (Py_ADDRESS_IN_RANGE(p, pool)) {\r
+ /* We allocated this address. */\r
+ LOCK();\r
+ /* Link p to the start of the pool's freeblock list. Since\r
+ * the pool had at least the p block outstanding, the pool\r
+ * wasn't empty (so it's already in a usedpools[] list, or\r
+ * was full and is in no list -- it's not in the freeblocks\r
+ * list in any case).\r
+ */\r
+ assert(pool->ref.count > 0); /* else it was empty */\r
+ *(block **)p = lastfree = pool->freeblock;\r
+ pool->freeblock = (block *)p;\r
+ if (lastfree) {\r
+ struct arena_object* ao;\r
+ uint nf; /* ao->nfreepools */\r
+\r
+ /* freeblock wasn't NULL, so the pool wasn't full,\r
+ * and the pool is in a usedpools[] list.\r
+ */\r
+ if (--pool->ref.count != 0) {\r
+ /* pool isn't empty: leave it in usedpools */\r
+ UNLOCK();\r
+ return;\r
+ }\r
+ /* Pool is now empty: unlink from usedpools, and\r
+ * link to the front of freepools. This ensures that\r
+ * previously freed pools will be allocated later\r
+ * (being not referenced, they are perhaps paged out).\r
+ */\r
+ next = pool->nextpool;\r
+ prev = pool->prevpool;\r
+ next->prevpool = prev;\r
+ prev->nextpool = next;\r
+\r
+ /* Link the pool to freepools. This is a singly-linked\r
+ * list, and pool->prevpool isn't used there.\r
+ */\r
+ ao = &arenas[pool->arenaindex];\r
+ pool->nextpool = ao->freepools;\r
+ ao->freepools = pool;\r
+ nf = ++ao->nfreepools;\r
+\r
+ /* All the rest is arena management. We just freed\r
+ * a pool, and there are 4 cases for arena mgmt:\r
+ * 1. If all the pools are free, return the arena to\r
+ * the system free().\r
+ * 2. If this is the only free pool in the arena,\r
+ * add the arena back to the `usable_arenas` list.\r
+ * 3. If the "next" arena has a smaller count of free\r
+ * pools, we have to "slide this arena right" to\r
+ * restore that usable_arenas is sorted in order of\r
+ * nfreepools.\r
+ * 4. Else there's nothing more to do.\r
+ */\r
+ if (nf == ao->ntotalpools) {\r
+ /* Case 1. First unlink ao from usable_arenas.\r
+ */\r
+ assert(ao->prevarena == NULL ||\r
+ ao->prevarena->address != 0);\r
+ assert(ao ->nextarena == NULL ||\r
+ ao->nextarena->address != 0);\r
+\r
+ /* Fix the pointer in the prevarena, or the\r
+ * usable_arenas pointer.\r
+ */\r
+ if (ao->prevarena == NULL) {\r
+ usable_arenas = ao->nextarena;\r
+ assert(usable_arenas == NULL ||\r
+ usable_arenas->address != 0);\r
+ }\r
+ else {\r
+ assert(ao->prevarena->nextarena == ao);\r
+ ao->prevarena->nextarena =\r
+ ao->nextarena;\r
+ }\r
+ /* Fix the pointer in the nextarena. */\r
+ if (ao->nextarena != NULL) {\r
+ assert(ao->nextarena->prevarena == ao);\r
+ ao->nextarena->prevarena =\r
+ ao->prevarena;\r
+ }\r
+ /* Record that this arena_object slot is\r
+ * available to be reused.\r
+ */\r
+ ao->nextarena = unused_arena_objects;\r
+ unused_arena_objects = ao;\r
+\r
+ /* Free the entire arena. */\r
+#ifdef ARENAS_USE_MMAP\r
+ munmap((void *)ao->address, ARENA_SIZE);\r
+#else\r
+ free((void *)ao->address);\r
+#endif\r
+ ao->address = 0; /* mark unassociated */\r
+ --narenas_currently_allocated;\r
+\r
+ UNLOCK();\r
+ return;\r
+ }\r
+ if (nf == 1) {\r
+ /* Case 2. Put ao at the head of\r
+ * usable_arenas. Note that because\r
+ * ao->nfreepools was 0 before, ao isn't\r
+ * currently on the usable_arenas list.\r
+ */\r
+ ao->nextarena = usable_arenas;\r
+ ao->prevarena = NULL;\r
+ if (usable_arenas)\r
+ usable_arenas->prevarena = ao;\r
+ usable_arenas = ao;\r
+ assert(usable_arenas->address != 0);\r
+\r
+ UNLOCK();\r
+ return;\r
+ }\r
+ /* If this arena is now out of order, we need to keep\r
+ * the list sorted. The list is kept sorted so that\r
+ * the "most full" arenas are used first, which allows\r
+ * the nearly empty arenas to be completely freed. In\r
+ * a few un-scientific tests, it seems like this\r
+ * approach allowed a lot more memory to be freed.\r
+ */\r
+ if (ao->nextarena == NULL ||\r
+ nf <= ao->nextarena->nfreepools) {\r
+ /* Case 4. Nothing to do. */\r
+ UNLOCK();\r
+ return;\r
+ }\r
+ /* Case 3: We have to move the arena towards the end\r
+ * of the list, because it has more free pools than\r
+ * the arena to its right.\r
+ * First unlink ao from usable_arenas.\r
+ */\r
+ if (ao->prevarena != NULL) {\r
+ /* ao isn't at the head of the list */\r
+ assert(ao->prevarena->nextarena == ao);\r
+ ao->prevarena->nextarena = ao->nextarena;\r
+ }\r
+ else {\r
+ /* ao is at the head of the list */\r
+ assert(usable_arenas == ao);\r
+ usable_arenas = ao->nextarena;\r
+ }\r
+ ao->nextarena->prevarena = ao->prevarena;\r
+\r
+ /* Locate the new insertion point by iterating over\r
+ * the list, using our nextarena pointer.\r
+ */\r
+ while (ao->nextarena != NULL &&\r
+ nf > ao->nextarena->nfreepools) {\r
+ ao->prevarena = ao->nextarena;\r
+ ao->nextarena = ao->nextarena->nextarena;\r
+ }\r
+\r
+ /* Insert ao at this point. */\r
+ assert(ao->nextarena == NULL ||\r
+ ao->prevarena == ao->nextarena->prevarena);\r
+ assert(ao->prevarena->nextarena == ao->nextarena);\r
+\r
+ ao->prevarena->nextarena = ao;\r
+ if (ao->nextarena != NULL)\r
+ ao->nextarena->prevarena = ao;\r
+\r
+ /* Verify that the swaps worked. */\r
+ assert(ao->nextarena == NULL ||\r
+ nf <= ao->nextarena->nfreepools);\r
+ assert(ao->prevarena == NULL ||\r
+ nf > ao->prevarena->nfreepools);\r
+ assert(ao->nextarena == NULL ||\r
+ ao->nextarena->prevarena == ao);\r
+ assert((usable_arenas == ao &&\r
+ ao->prevarena == NULL) ||\r
+ ao->prevarena->nextarena == ao);\r
+\r
+ UNLOCK();\r
+ return;\r
+ }\r
+ /* Pool was full, so doesn't currently live in any list:\r
+ * link it to the front of the appropriate usedpools[] list.\r
+ * This mimics LRU pool usage for new allocations and\r
+ * targets optimal filling when several pools contain\r
+ * blocks of the same size class.\r
+ */\r
+ --pool->ref.count;\r
+ assert(pool->ref.count > 0); /* else the pool is empty */\r
+ size = pool->szidx;\r
+ next = usedpools[size + size];\r
+ prev = next->prevpool;\r
+ /* insert pool before next: prev <-> pool <-> next */\r
+ pool->nextpool = next;\r
+ pool->prevpool = prev;\r
+ next->prevpool = pool;\r
+ prev->nextpool = pool;\r
+ UNLOCK();\r
+ return;\r
+ }\r
+\r
+#ifdef WITH_VALGRIND\r
+redirect:\r
+#endif\r
+ /* We didn't allocate this address. */\r
+ free(p);\r
+}\r
+\r
+/* realloc. If p is NULL, this acts like malloc(nbytes). Else if nbytes==0,\r
+ * then as the Python docs promise, we do not treat this like free(p), and\r
+ * return a non-NULL result.\r
+ */\r
+\r
+#undef PyObject_Realloc\r
+ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS\r
+void *\r
+PyObject_Realloc(void *p, size_t nbytes)\r
+{\r
+ void *bp;\r
+ poolp pool;\r
+ size_t size;\r
+#ifndef Py_USING_MEMORY_DEBUGGER\r
+ uint arenaindex_temp;\r
+#endif\r
+\r
+ if (p == NULL)\r
+ return PyObject_Malloc(nbytes);\r
+\r
+ /*\r
+ * Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes.\r
+ * Most python internals blindly use a signed Py_ssize_t to track\r
+ * things without checking for overflows or negatives.\r
+ * As size_t is unsigned, checking for nbytes < 0 is not required.\r
+ */\r
+ if (nbytes > PY_SSIZE_T_MAX)\r
+ return NULL;\r
+\r
+#ifdef WITH_VALGRIND\r
+ /* Treat running_on_valgrind == -1 the same as 0 */\r
+ if (UNLIKELY(running_on_valgrind > 0))\r
+ goto redirect;\r
+#endif\r
+\r
+ pool = POOL_ADDR(p);\r
+ if (Py_ADDRESS_IN_RANGE(p, pool)) {\r
+ /* We're in charge of this block */\r
+ size = INDEX2SIZE(pool->szidx);\r
+ if (nbytes <= size) {\r
+ /* The block is staying the same or shrinking. If\r
+ * it's shrinking, there's a tradeoff: it costs\r
+ * cycles to copy the block to a smaller size class,\r
+ * but it wastes memory not to copy it. The\r
+ * compromise here is to copy on shrink only if at\r
+ * least 25% of size can be shaved off.\r
+ */\r
+ if (4 * nbytes > 3 * size) {\r
+ /* It's the same,\r
+ * or shrinking and new/old > 3/4.\r
+ */\r
+ return p;\r
+ }\r
+ size = nbytes;\r
+ }\r
+ bp = PyObject_Malloc(nbytes);\r
+ if (bp != NULL) {\r
+ memcpy(bp, p, size);\r
+ PyObject_Free(p);\r
+ }\r
+ return bp;\r
+ }\r
+#ifdef WITH_VALGRIND\r
+ redirect:\r
+#endif\r
+ /* We're not managing this block. If nbytes <=\r
+ * SMALL_REQUEST_THRESHOLD, it's tempting to try to take over this\r
+ * block. However, if we do, we need to copy the valid data from\r
+ * the C-managed block to one of our blocks, and there's no portable\r
+ * way to know how much of the memory space starting at p is valid.\r
+ * As bug 1185883 pointed out the hard way, it's possible that the\r
+ * C-managed block is "at the end" of allocated VM space, so that\r
+ * a memory fault can occur if we try to copy nbytes bytes starting\r
+ * at p. Instead we punt: let C continue to manage this block.\r
+ */\r
+ if (nbytes)\r
+ return realloc(p, nbytes);\r
+ /* C doesn't define the result of realloc(p, 0) (it may or may not\r
+ * return NULL then), but Python's docs promise that nbytes==0 never\r
+ * returns NULL. We don't pass 0 to realloc(), to avoid that endcase\r
+ * to begin with. Even then, we can't be sure that realloc() won't\r
+ * return NULL.\r
+ */\r
+ bp = realloc(p, 1);\r
+ return bp ? bp : p;\r
+}\r
+\r
+#else /* ! WITH_PYMALLOC */\r
+\r
+/*==========================================================================*/\r
+/* pymalloc not enabled: Redirect the entry points to malloc. These will\r
+ * only be used by extensions that are compiled with pymalloc enabled. */\r
+\r
+void *\r
+PyObject_Malloc(size_t n)\r
+{\r
+ return PyMem_MALLOC(n);\r
+}\r
+\r
+void *\r
+PyObject_Realloc(void *p, size_t n)\r
+{\r
+ return PyMem_REALLOC(p, n);\r
+}\r
+\r
+void\r
+PyObject_Free(void *p)\r
+{\r
+ PyMem_FREE(p);\r
+}\r
+#endif /* WITH_PYMALLOC */\r
+\r
+#ifdef PYMALLOC_DEBUG\r
+/*==========================================================================*/\r
+/* A x-platform debugging allocator. This doesn't manage memory directly,\r
+ * it wraps a real allocator, adding extra debugging info to the memory blocks.\r
+ */\r
+\r
+/* Special bytes broadcast into debug memory blocks at appropriate times.\r
+ * Strings of these are unlikely to be valid addresses, floats, ints or\r
+ * 7-bit ASCII.\r
+ */\r
+#undef CLEANBYTE\r
+#undef DEADBYTE\r
+#undef FORBIDDENBYTE\r
+#define CLEANBYTE 0xCB /* clean (newly allocated) memory */\r
+#define DEADBYTE 0xDB /* dead (newly freed) memory */\r
+#define FORBIDDENBYTE 0xFB /* untouchable bytes at each end of a block */\r
+\r
+/* We tag each block with an API ID in order to tag API violations */\r
+#define _PYMALLOC_MEM_ID 'm' /* the PyMem_Malloc() API */\r
+#define _PYMALLOC_OBJ_ID 'o' /* The PyObject_Malloc() API */\r
+\r
+static size_t serialno = 0; /* incremented on each debug {m,re}alloc */\r
+\r
+/* serialno is always incremented via calling this routine. The point is\r
+ * to supply a single place to set a breakpoint.\r
+ */\r
+static void\r
+bumpserialno(void)\r
+{\r
+ ++serialno;\r
+}\r
+\r
+#define SST SIZEOF_SIZE_T\r
+\r
+/* Read sizeof(size_t) bytes at p as a big-endian size_t. */\r
+static size_t\r
+read_size_t(const void *p)\r
+{\r
+ const uchar *q = (const uchar *)p;\r
+ size_t result = *q++;\r
+ int i;\r
+\r
+ for (i = SST; --i > 0; ++q)\r
+ result = (result << 8) | *q;\r
+ return result;\r
+}\r
+\r
+/* Write n as a big-endian size_t, MSB at address p, LSB at\r
+ * p + sizeof(size_t) - 1.\r
+ */\r
+static void\r
+write_size_t(void *p, size_t n)\r
+{\r
+ uchar *q = (uchar *)p + SST - 1;\r
+ int i;\r
+\r
+ for (i = SST; --i >= 0; --q) {\r
+ *q = (uchar)(n & 0xff);\r
+ n >>= 8;\r
+ }\r
+}\r
+\r
+#ifdef Py_DEBUG\r
+/* Is target in the list? The list is traversed via the nextpool pointers.\r
+ * The list may be NULL-terminated, or circular. Return 1 if target is in\r
+ * list, else 0.\r
+ */\r
+static int\r
+pool_is_in_list(const poolp target, poolp list)\r
+{\r
+ poolp origlist = list;\r
+ assert(target != NULL);\r
+ if (list == NULL)\r
+ return 0;\r
+ do {\r
+ if (target == list)\r
+ return 1;\r
+ list = list->nextpool;\r
+ } while (list != NULL && list != origlist);\r
+ return 0;\r
+}\r
+\r
+#else\r
+#define pool_is_in_list(X, Y) 1\r
+\r
+#endif /* Py_DEBUG */\r
+\r
+/* Let S = sizeof(size_t). The debug malloc asks for 4*S extra bytes and\r
+ fills them with useful stuff, here calling the underlying malloc's result p:\r
+\r
+p[0: S]\r
+ Number of bytes originally asked for. This is a size_t, big-endian (easier\r
+ to read in a memory dump).\r
+p[S: 2*S]\r
+ Copies of FORBIDDENBYTE. Used to catch under- writes and reads.\r
+p[2*S: 2*S+n]\r
+ The requested memory, filled with copies of CLEANBYTE.\r
+ Used to catch reference to uninitialized memory.\r
+ &p[2*S] is returned. Note that this is 8-byte aligned if pymalloc\r
+ handled the request itself.\r
+p[2*S+n: 2*S+n+S]\r
+ Copies of FORBIDDENBYTE. Used to catch over- writes and reads.\r
+p[2*S+n+S: 2*S+n+2*S]\r
+ A serial number, incremented by 1 on each call to _PyObject_DebugMalloc\r
+ and _PyObject_DebugRealloc.\r
+ This is a big-endian size_t.\r
+ If "bad memory" is detected later, the serial number gives an\r
+ excellent way to set a breakpoint on the next run, to capture the\r
+ instant at which this block was passed out.\r
+*/\r
+\r
+/* debug replacements for the PyMem_* memory API */\r
+void *\r
+_PyMem_DebugMalloc(size_t nbytes)\r
+{\r
+ return _PyObject_DebugMallocApi(_PYMALLOC_MEM_ID, nbytes);\r
+}\r
+void *\r
+_PyMem_DebugRealloc(void *p, size_t nbytes)\r
+{\r
+ return _PyObject_DebugReallocApi(_PYMALLOC_MEM_ID, p, nbytes);\r
+}\r
+void\r
+_PyMem_DebugFree(void *p)\r
+{\r
+ _PyObject_DebugFreeApi(_PYMALLOC_MEM_ID, p);\r
+}\r
+\r
+/* debug replacements for the PyObject_* memory API */\r
+void *\r
+_PyObject_DebugMalloc(size_t nbytes)\r
+{\r
+ return _PyObject_DebugMallocApi(_PYMALLOC_OBJ_ID, nbytes);\r
+}\r
+void *\r
+_PyObject_DebugRealloc(void *p, size_t nbytes)\r
+{\r
+ return _PyObject_DebugReallocApi(_PYMALLOC_OBJ_ID, p, nbytes);\r
+}\r
+void\r
+_PyObject_DebugFree(void *p)\r
+{\r
+ _PyObject_DebugFreeApi(_PYMALLOC_OBJ_ID, p);\r
+}\r
+void\r
+_PyObject_DebugCheckAddress(const void *p)\r
+{\r
+ _PyObject_DebugCheckAddressApi(_PYMALLOC_OBJ_ID, p);\r
+}\r
+\r
+\r
+/* generic debug memory api, with an "id" to identify the API in use */\r
+void *\r
+_PyObject_DebugMallocApi(char id, size_t nbytes)\r
+{\r
+ uchar *p; /* base address of malloc'ed block */\r
+ uchar *tail; /* p + 2*SST + nbytes == pointer to tail pad bytes */\r
+ size_t total; /* nbytes + 4*SST */\r
+\r
+ bumpserialno();\r
+ total = nbytes + 4*SST;\r
+ if (total < nbytes)\r
+ /* overflow: can't represent total as a size_t */\r
+ return NULL;\r
+\r
+ p = (uchar *)PyObject_Malloc(total);\r
+ if (p == NULL)\r
+ return NULL;\r
+\r
+ /* at p, write size (SST bytes), id (1 byte), pad (SST-1 bytes) */\r
+ write_size_t(p, nbytes);\r
+ p[SST] = (uchar)id;\r
+ memset(p + SST + 1 , FORBIDDENBYTE, SST-1);\r
+\r
+ if (nbytes > 0)\r
+ memset(p + 2*SST, CLEANBYTE, nbytes);\r
+\r
+ /* at tail, write pad (SST bytes) and serialno (SST bytes) */\r
+ tail = p + 2*SST + nbytes;\r
+ memset(tail, FORBIDDENBYTE, SST);\r
+ write_size_t(tail + SST, serialno);\r
+\r
+ return p + 2*SST;\r
+}\r
+\r
+/* The debug free first checks the 2*SST bytes on each end for sanity (in\r
+ particular, that the FORBIDDENBYTEs with the api ID are still intact).\r
+ Then fills the original bytes with DEADBYTE.\r
+ Then calls the underlying free.\r
+*/\r
+void\r
+_PyObject_DebugFreeApi(char api, void *p)\r
+{\r
+ uchar *q = (uchar *)p - 2*SST; /* address returned from malloc */\r
+ size_t nbytes;\r
+\r
+ if (p == NULL)\r
+ return;\r
+ _PyObject_DebugCheckAddressApi(api, p);\r
+ nbytes = read_size_t(q);\r
+ nbytes += 4*SST;\r
+ if (nbytes > 0)\r
+ memset(q, DEADBYTE, nbytes);\r
+ PyObject_Free(q);\r
+}\r
+\r
+void *\r
+_PyObject_DebugReallocApi(char api, void *p, size_t nbytes)\r
+{\r
+ uchar *q = (uchar *)p;\r
+ uchar *tail;\r
+ size_t total; /* nbytes + 4*SST */\r
+ size_t original_nbytes;\r
+ int i;\r
+\r
+ if (p == NULL)\r
+ return _PyObject_DebugMallocApi(api, nbytes);\r
+\r
+ _PyObject_DebugCheckAddressApi(api, p);\r
+ bumpserialno();\r
+ original_nbytes = read_size_t(q - 2*SST);\r
+ total = nbytes + 4*SST;\r
+ if (total < nbytes)\r
+ /* overflow: can't represent total as a size_t */\r
+ return NULL;\r
+\r
+ if (nbytes < original_nbytes) {\r
+ /* shrinking: mark old extra memory dead */\r
+ memset(q + nbytes, DEADBYTE, original_nbytes - nbytes + 2*SST);\r
+ }\r
+\r
+ /* Resize and add decorations. We may get a new pointer here, in which\r
+ * case we didn't get the chance to mark the old memory with DEADBYTE,\r
+ * but we live with that.\r
+ */\r
+ q = (uchar *)PyObject_Realloc(q - 2*SST, total);\r
+ if (q == NULL)\r
+ return NULL;\r
+\r
+ write_size_t(q, nbytes);\r
+ assert(q[SST] == (uchar)api);\r
+ for (i = 1; i < SST; ++i)\r
+ assert(q[SST + i] == FORBIDDENBYTE);\r
+ q += 2*SST;\r
+ tail = q + nbytes;\r
+ memset(tail, FORBIDDENBYTE, SST);\r
+ write_size_t(tail + SST, serialno);\r
+\r
+ if (nbytes > original_nbytes) {\r
+ /* growing: mark new extra memory clean */\r
+ memset(q + original_nbytes, CLEANBYTE,\r
+ nbytes - original_nbytes);\r
+ }\r
+\r
+ return q;\r
+}\r
+\r
+/* Check the forbidden bytes on both ends of the memory allocated for p.\r
+ * If anything is wrong, print info to stderr via _PyObject_DebugDumpAddress,\r
+ * and call Py_FatalError to kill the program.\r
+ * The API id, is also checked.\r
+ */\r
+ void\r
+_PyObject_DebugCheckAddressApi(char api, const void *p)\r
+{\r
+ const uchar *q = (const uchar *)p;\r
+ char msgbuf[64];\r
+ char *msg;\r
+ size_t nbytes;\r
+ const uchar *tail;\r
+ int i;\r
+ char id;\r
+\r
+ if (p == NULL) {\r
+ msg = "didn't expect a NULL pointer";\r
+ goto error;\r
+ }\r
+\r
+ /* Check the API id */\r
+ id = (char)q[-SST];\r
+ if (id != api) {\r
+ msg = msgbuf;\r
+ snprintf(msg, sizeof(msgbuf), "bad ID: Allocated using API '%c', verified using API '%c'", id, api);\r
+ msgbuf[sizeof(msgbuf)-1] = 0;\r
+ goto error;\r
+ }\r
+\r
+ /* Check the stuff at the start of p first: if there's underwrite\r
+ * corruption, the number-of-bytes field may be nuts, and checking\r
+ * the tail could lead to a segfault then.\r
+ */\r
+ for (i = SST-1; i >= 1; --i) {\r
+ if (*(q-i) != FORBIDDENBYTE) {\r
+ msg = "bad leading pad byte";\r
+ goto error;\r
+ }\r
+ }\r
+\r
+ nbytes = read_size_t(q - 2*SST);\r
+ tail = q + nbytes;\r
+ for (i = 0; i < SST; ++i) {\r
+ if (tail[i] != FORBIDDENBYTE) {\r
+ msg = "bad trailing pad byte";\r
+ goto error;\r
+ }\r
+ }\r
+\r
+ return;\r
+\r
+error:\r
+ _PyObject_DebugDumpAddress(p);\r
+ Py_FatalError(msg);\r
+}\r
+\r
+/* Display info to stderr about the memory block at p. */\r
+void\r
+_PyObject_DebugDumpAddress(const void *p)\r
+{\r
+ const uchar *q = (const uchar *)p;\r
+ const uchar *tail;\r
+ size_t nbytes, serial;\r
+ int i;\r
+ int ok;\r
+ char id;\r
+\r
+ fprintf(stderr, "Debug memory block at address p=%p:", p);\r
+ if (p == NULL) {\r
+ fprintf(stderr, "\n");\r
+ return;\r
+ }\r
+ id = (char)q[-SST];\r
+ fprintf(stderr, " API '%c'\n", id);\r
+\r
+ nbytes = read_size_t(q - 2*SST);\r
+ fprintf(stderr, " %" PY_FORMAT_SIZE_T "u bytes originally "\r
+ "requested\n", nbytes);\r
+\r
+ /* In case this is nuts, check the leading pad bytes first. */\r
+ fprintf(stderr, " The %d pad bytes at p-%d are ", SST-1, SST-1);\r
+ ok = 1;\r
+ for (i = 1; i <= SST-1; ++i) {\r
+ if (*(q-i) != FORBIDDENBYTE) {\r
+ ok = 0;\r
+ break;\r
+ }\r
+ }\r
+ if (ok)\r
+ fputs("FORBIDDENBYTE, as expected.\n", stderr);\r
+ else {\r
+ fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",\r
+ FORBIDDENBYTE);\r
+ for (i = SST-1; i >= 1; --i) {\r
+ const uchar byte = *(q-i);\r
+ fprintf(stderr, " at p-%d: 0x%02x", i, byte);\r
+ if (byte != FORBIDDENBYTE)\r
+ fputs(" *** OUCH", stderr);\r
+ fputc('\n', stderr);\r
+ }\r
+\r
+ fputs(" Because memory is corrupted at the start, the "\r
+ "count of bytes requested\n"\r
+ " may be bogus, and checking the trailing pad "\r
+ "bytes may segfault.\n", stderr);\r
+ }\r
+\r
+ tail = q + nbytes;\r
+ fprintf(stderr, " The %d pad bytes at tail=%p are ", SST, tail);\r
+ ok = 1;\r
+ for (i = 0; i < SST; ++i) {\r
+ if (tail[i] != FORBIDDENBYTE) {\r
+ ok = 0;\r
+ break;\r
+ }\r
+ }\r
+ if (ok)\r
+ fputs("FORBIDDENBYTE, as expected.\n", stderr);\r
+ else {\r
+ fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",\r
+ FORBIDDENBYTE);\r
+ for (i = 0; i < SST; ++i) {\r
+ const uchar byte = tail[i];\r
+ fprintf(stderr, " at tail+%d: 0x%02x",\r
+ i, byte);\r
+ if (byte != FORBIDDENBYTE)\r
+ fputs(" *** OUCH", stderr);\r
+ fputc('\n', stderr);\r
+ }\r
+ }\r
+\r
+ serial = read_size_t(tail + SST);\r
+ fprintf(stderr, " The block was made by call #%" PY_FORMAT_SIZE_T\r
+ "u to debug malloc/realloc.\n", serial);\r
+\r
+ if (nbytes > 0) {\r
+ i = 0;\r
+ fputs(" Data at p:", stderr);\r
+ /* print up to 8 bytes at the start */\r
+ while (q < tail && i < 8) {\r
+ fprintf(stderr, " %02x", *q);\r
+ ++i;\r
+ ++q;\r
+ }\r
+ /* and up to 8 at the end */\r
+ if (q < tail) {\r
+ if (tail - q > 8) {\r
+ fputs(" ...", stderr);\r
+ q = tail - 8;\r
+ }\r
+ while (q < tail) {\r
+ fprintf(stderr, " %02x", *q);\r
+ ++q;\r
+ }\r
+ }\r
+ fputc('\n', stderr);\r
+ }\r
+}\r
+\r
+static size_t\r
+printone(const char* msg, size_t value)\r
+{\r
+ int i, k;\r
+ char buf[100];\r
+ size_t origvalue = value;\r
+\r
+ fputs(msg, stderr);\r
+ for (i = (int)strlen(msg); i < 35; ++i)\r
+ fputc(' ', stderr);\r
+ fputc('=', stderr);\r
+\r
+ /* Write the value with commas. */\r
+ i = 22;\r
+ buf[i--] = '\0';\r
+ buf[i--] = '\n';\r
+ k = 3;\r
+ do {\r
+ size_t nextvalue = value / 10;\r
+ unsigned int digit = (unsigned int)(value - nextvalue * 10);\r
+ value = nextvalue;\r
+ buf[i--] = (char)(digit + '0');\r
+ --k;\r
+ if (k == 0 && value && i >= 0) {\r
+ k = 3;\r
+ buf[i--] = ',';\r
+ }\r
+ } while (value && i >= 0);\r
+\r
+ while (i >= 0)\r
+ buf[i--] = ' ';\r
+ fputs(buf, stderr);\r
+\r
+ return origvalue;\r
+}\r
+\r
+/* Print summary info to stderr about the state of pymalloc's structures.\r
+ * In Py_DEBUG mode, also perform some expensive internal consistency\r
+ * checks.\r
+ */\r
+void\r
+_PyObject_DebugMallocStats(void)\r
+{\r
+ uint i;\r
+ const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;\r
+ /* # of pools, allocated blocks, and free blocks per class index */\r
+ size_t numpools[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];\r
+ size_t numblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];\r
+ size_t numfreeblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];\r
+ /* total # of allocated bytes in used and full pools */\r
+ size_t allocated_bytes = 0;\r
+ /* total # of available bytes in used pools */\r
+ size_t available_bytes = 0;\r
+ /* # of free pools + pools not yet carved out of current arena */\r
+ uint numfreepools = 0;\r
+ /* # of bytes for arena alignment padding */\r
+ size_t arena_alignment = 0;\r
+ /* # of bytes in used and full pools used for pool_headers */\r
+ size_t pool_header_bytes = 0;\r
+ /* # of bytes in used and full pools wasted due to quantization,\r
+ * i.e. the necessarily leftover space at the ends of used and\r
+ * full pools.\r
+ */\r
+ size_t quantization = 0;\r
+ /* # of arenas actually allocated. */\r
+ size_t narenas = 0;\r
+ /* running total -- should equal narenas * ARENA_SIZE */\r
+ size_t total;\r
+ char buf[128];\r
+\r
+ fprintf(stderr, "Small block threshold = %d, in %u size classes.\n",\r
+ SMALL_REQUEST_THRESHOLD, numclasses);\r
+\r
+ for (i = 0; i < numclasses; ++i)\r
+ numpools[i] = numblocks[i] = numfreeblocks[i] = 0;\r
+\r
+ /* Because full pools aren't linked to from anything, it's easiest\r
+ * to march over all the arenas. If we're lucky, most of the memory\r
+ * will be living in full pools -- would be a shame to miss them.\r
+ */\r
+ for (i = 0; i < maxarenas; ++i) {\r
+ uint j;\r
+ uptr base = arenas[i].address;\r
+\r
+ /* Skip arenas which are not allocated. */\r
+ if (arenas[i].address == (uptr)NULL)\r
+ continue;\r
+ narenas += 1;\r
+\r
+ numfreepools += arenas[i].nfreepools;\r
+\r
+ /* round up to pool alignment */\r
+ if (base & (uptr)POOL_SIZE_MASK) {\r
+ arena_alignment += POOL_SIZE;\r
+ base &= ~(uptr)POOL_SIZE_MASK;\r
+ base += POOL_SIZE;\r
+ }\r
+\r
+ /* visit every pool in the arena */\r
+ assert(base <= (uptr) arenas[i].pool_address);\r
+ for (j = 0;\r
+ base < (uptr) arenas[i].pool_address;\r
+ ++j, base += POOL_SIZE) {\r
+ poolp p = (poolp)base;\r
+ const uint sz = p->szidx;\r
+ uint freeblocks;\r
+\r
+ if (p->ref.count == 0) {\r
+ /* currently unused */\r
+ assert(pool_is_in_list(p, arenas[i].freepools));\r
+ continue;\r
+ }\r
+ ++numpools[sz];\r
+ numblocks[sz] += p->ref.count;\r
+ freeblocks = NUMBLOCKS(sz) - p->ref.count;\r
+ numfreeblocks[sz] += freeblocks;\r
+#ifdef Py_DEBUG\r
+ if (freeblocks > 0)\r
+ assert(pool_is_in_list(p, usedpools[sz + sz]));\r
+#endif\r
+ }\r
+ }\r
+ assert(narenas == narenas_currently_allocated);\r
+\r
+ fputc('\n', stderr);\r
+ fputs("class size num pools blocks in use avail blocks\n"\r
+ "----- ---- --------- ------------- ------------\n",\r
+ stderr);\r
+\r
+ for (i = 0; i < numclasses; ++i) {\r
+ size_t p = numpools[i];\r
+ size_t b = numblocks[i];\r
+ size_t f = numfreeblocks[i];\r
+ uint size = INDEX2SIZE(i);\r
+ if (p == 0) {\r
+ assert(b == 0 && f == 0);\r
+ continue;\r
+ }\r
+ fprintf(stderr, "%5u %6u "\r
+ "%11" PY_FORMAT_SIZE_T "u "\r
+ "%15" PY_FORMAT_SIZE_T "u "\r
+ "%13" PY_FORMAT_SIZE_T "u\n",\r
+ i, size, p, b, f);\r
+ allocated_bytes += b * size;\r
+ available_bytes += f * size;\r
+ pool_header_bytes += p * POOL_OVERHEAD;\r
+ quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);\r
+ }\r
+ fputc('\n', stderr);\r
+ (void)printone("# times object malloc called", serialno);\r
+\r
+ (void)printone("# arenas allocated total", ntimes_arena_allocated);\r
+ (void)printone("# arenas reclaimed", ntimes_arena_allocated - narenas);\r
+ (void)printone("# arenas highwater mark", narenas_highwater);\r
+ (void)printone("# arenas allocated current", narenas);\r
+\r
+ PyOS_snprintf(buf, sizeof(buf),\r
+ "%" PY_FORMAT_SIZE_T "u arenas * %d bytes/arena",\r
+ narenas, ARENA_SIZE);\r
+ (void)printone(buf, narenas * ARENA_SIZE);\r
+\r
+ fputc('\n', stderr);\r
+\r
+ total = printone("# bytes in allocated blocks", allocated_bytes);\r
+ total += printone("# bytes in available blocks", available_bytes);\r
+\r
+ PyOS_snprintf(buf, sizeof(buf),\r
+ "%u unused pools * %d bytes", numfreepools, POOL_SIZE);\r
+ total += printone(buf, (size_t)numfreepools * POOL_SIZE);\r
+\r
+ total += printone("# bytes lost to pool headers", pool_header_bytes);\r
+ total += printone("# bytes lost to quantization", quantization);\r
+ total += printone("# bytes lost to arena alignment", arena_alignment);\r
+ (void)printone("Total", total);\r
+}\r
+\r
+#endif /* PYMALLOC_DEBUG */\r
+\r
+#ifdef Py_USING_MEMORY_DEBUGGER\r
+/* Make this function last so gcc won't inline it since the definition is\r
+ * after the reference.\r
+ */\r
+int\r
+Py_ADDRESS_IN_RANGE(void *P, poolp pool)\r
+{\r
+ uint arenaindex_temp = pool->arenaindex;\r
+\r
+ return arenaindex_temp < maxarenas &&\r
+ (uptr)P - arenas[arenaindex_temp].address < (uptr)ARENA_SIZE &&\r
+ arenas[arenaindex_temp].address != 0;\r
+}\r
+#endif\r
--- /dev/null
+/* Range object implementation */\r
+\r
+#include "Python.h"\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ long start;\r
+ long step;\r
+ long len;\r
+} rangeobject;\r
+\r
+/* Return number of items in range (lo, hi, step). step != 0\r
+ * required. The result always fits in an unsigned long.\r
+ */\r
+static unsigned long\r
+get_len_of_range(long lo, long hi, long step)\r
+{\r
+ /* -------------------------------------------------------------\r
+ If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty.\r
+ Else for step > 0, if n values are in the range, the last one is\r
+ lo + (n-1)*step, which must be <= hi-1. Rearranging,\r
+ n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives\r
+ the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so\r
+ the RHS is non-negative and so truncation is the same as the\r
+ floor. Letting M be the largest positive long, the worst case\r
+ for the RHS numerator is hi=M, lo=-M-1, and then\r
+ hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough\r
+ precision to compute the RHS exactly. The analysis for step < 0\r
+ is similar.\r
+ ---------------------------------------------------------------*/\r
+ assert(step != 0);\r
+ if (step > 0 && lo < hi)\r
+ return 1UL + (hi - 1UL - lo) / step;\r
+ else if (step < 0 && lo > hi)\r
+ return 1UL + (lo - 1UL - hi) / (0UL - step);\r
+ else\r
+ return 0UL;\r
+}\r
+\r
+/* Return a stop value suitable for reconstructing the xrange from\r
+ * a (start, stop, step) triple. Used in range_repr and range_reduce.\r
+ * Computes start + len * step, clipped to the range [LONG_MIN, LONG_MAX].\r
+ */\r
+static long\r
+get_stop_for_range(rangeobject *r)\r
+{\r
+ long last;\r
+\r
+ if (r->len == 0)\r
+ return r->start;\r
+\r
+ /* The tricky bit is avoiding overflow. We first compute the last entry in\r
+ the xrange, start + (len - 1) * step, which is guaranteed to lie within\r
+ the range of a long, and then add step to it. See the range_reverse\r
+ comments for an explanation of the casts below.\r
+ */\r
+ last = (long)(r->start + (unsigned long)(r->len - 1) * r->step);\r
+ if (r->step > 0)\r
+ return last > LONG_MAX - r->step ? LONG_MAX : last + r->step;\r
+ else\r
+ return last < LONG_MIN - r->step ? LONG_MIN : last + r->step;\r
+}\r
+\r
+static PyObject *\r
+range_new(PyTypeObject *type, PyObject *args, PyObject *kw)\r
+{\r
+ rangeobject *obj;\r
+ long ilow = 0, ihigh = 0, istep = 1;\r
+ unsigned long n;\r
+\r
+ if (!_PyArg_NoKeywords("xrange()", kw))\r
+ return NULL;\r
+\r
+ if (PyTuple_Size(args) <= 1) {\r
+ if (!PyArg_ParseTuple(args,\r
+ "l;xrange() requires 1-3 int arguments",\r
+ &ihigh))\r
+ return NULL;\r
+ }\r
+ else {\r
+ if (!PyArg_ParseTuple(args,\r
+ "ll|l;xrange() requires 1-3 int arguments",\r
+ &ilow, &ihigh, &istep))\r
+ return NULL;\r
+ }\r
+ if (istep == 0) {\r
+ PyErr_SetString(PyExc_ValueError, "xrange() arg 3 must not be zero");\r
+ return NULL;\r
+ }\r
+ n = get_len_of_range(ilow, ihigh, istep);\r
+ if (n > (unsigned long)LONG_MAX || (long)n > PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "xrange() result has too many items");\r
+ return NULL;\r
+ }\r
+\r
+ obj = PyObject_New(rangeobject, &PyRange_Type);\r
+ if (obj == NULL)\r
+ return NULL;\r
+ obj->start = ilow;\r
+ obj->len = (long)n;\r
+ obj->step = istep;\r
+ return (PyObject *) obj;\r
+}\r
+\r
+PyDoc_STRVAR(range_doc,\r
+"xrange(stop) -> xrange object\n\\r
+xrange(start, stop[, step]) -> xrange object\n\\r
+\n\\r
+Like range(), but instead of returning a list, returns an object that\n\\r
+generates the numbers in the range on demand. For looping, this is \n\\r
+slightly faster than range() and more memory efficient.");\r
+\r
+static PyObject *\r
+range_item(rangeobject *r, Py_ssize_t i)\r
+{\r
+ if (i < 0 || i >= r->len) {\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "xrange object index out of range");\r
+ return NULL;\r
+ }\r
+ /* do calculation entirely using unsigned longs, to avoid\r
+ undefined behaviour due to signed overflow. */\r
+ return PyInt_FromLong((long)(r->start + (unsigned long)i * r->step));\r
+}\r
+\r
+static Py_ssize_t\r
+range_length(rangeobject *r)\r
+{\r
+ return (Py_ssize_t)(r->len);\r
+}\r
+\r
+static PyObject *\r
+range_repr(rangeobject *r)\r
+{\r
+ PyObject *rtn;\r
+\r
+ if (r->start == 0 && r->step == 1)\r
+ rtn = PyString_FromFormat("xrange(%ld)",\r
+ get_stop_for_range(r));\r
+\r
+ else if (r->step == 1)\r
+ rtn = PyString_FromFormat("xrange(%ld, %ld)",\r
+ r->start,\r
+ get_stop_for_range(r));\r
+\r
+ else\r
+ rtn = PyString_FromFormat("xrange(%ld, %ld, %ld)",\r
+ r->start,\r
+ get_stop_for_range(r),\r
+ r->step);\r
+ return rtn;\r
+}\r
+\r
+/* Pickling support */\r
+static PyObject *\r
+range_reduce(rangeobject *r, PyObject *args)\r
+{\r
+ return Py_BuildValue("(O(lll))", Py_TYPE(r),\r
+ r->start,\r
+ get_stop_for_range(r),\r
+ r->step);\r
+}\r
+\r
+static PySequenceMethods range_as_sequence = {\r
+ (lenfunc)range_length, /* sq_length */\r
+ 0, /* sq_concat */\r
+ 0, /* sq_repeat */\r
+ (ssizeargfunc)range_item, /* sq_item */\r
+ 0, /* sq_slice */\r
+};\r
+\r
+static PyObject * range_iter(PyObject *seq);\r
+static PyObject * range_reverse(PyObject *seq);\r
+\r
+PyDoc_STRVAR(reverse_doc,\r
+"Returns a reverse iterator.");\r
+\r
+static PyMethodDef range_methods[] = {\r
+ {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, reverse_doc},\r
+ {"__reduce__", (PyCFunction)range_reduce, METH_VARARGS},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyRange_Type = {\r
+ PyObject_HEAD_INIT(&PyType_Type)\r
+ 0, /* Number of items for varobject */\r
+ "xrange", /* Name of this type */\r
+ sizeof(rangeobject), /* Basic object size */\r
+ 0, /* Item size for varobject */\r
+ (destructor)PyObject_Del, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)range_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &range_as_sequence, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT, /* tp_flags */\r
+ range_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ range_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ range_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ range_new, /* tp_new */\r
+};\r
+\r
+/*********************** Xrange Iterator **************************/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ long index;\r
+ long start;\r
+ long step;\r
+ long len;\r
+} rangeiterobject;\r
+\r
+static PyObject *\r
+rangeiter_next(rangeiterobject *r)\r
+{\r
+ if (r->index < r->len)\r
+ return PyInt_FromLong(r->start + (r->index++) * r->step);\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+rangeiter_len(rangeiterobject *r)\r
+{\r
+ return PyInt_FromLong(r->len - r->index);\r
+}\r
+\r
+PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
+\r
+static PyMethodDef rangeiter_methods[] = {\r
+ {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, length_hint_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyTypeObject Pyrangeiter_Type = {\r
+ PyObject_HEAD_INIT(&PyType_Type)\r
+ 0, /* ob_size */\r
+ "rangeiterator", /* tp_name */\r
+ sizeof(rangeiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)PyObject_Del, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)rangeiter_next, /* tp_iternext */\r
+ rangeiter_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *\r
+range_iter(PyObject *seq)\r
+{\r
+ rangeiterobject *it;\r
+\r
+ if (!PyRange_Check(seq)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+ it->index = 0;\r
+ it->start = ((rangeobject *)seq)->start;\r
+ it->step = ((rangeobject *)seq)->step;\r
+ it->len = ((rangeobject *)seq)->len;\r
+ return (PyObject *)it;\r
+}\r
+\r
+static PyObject *\r
+range_reverse(PyObject *seq)\r
+{\r
+ rangeiterobject *it;\r
+ long start, step, len;\r
+\r
+ if (!PyRange_Check(seq)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+\r
+ start = ((rangeobject *)seq)->start;\r
+ step = ((rangeobject *)seq)->step;\r
+ len = ((rangeobject *)seq)->len;\r
+\r
+ it->index = 0;\r
+ it->len = len;\r
+ /* the casts below guard against signed overflow by turning it\r
+ into unsigned overflow instead. The correctness of this\r
+ code still depends on conversion from unsigned long to long\r
+ wrapping modulo ULONG_MAX+1, which isn't guaranteed (see\r
+ C99 6.3.1.3p3) but seems to hold in practice for all\r
+ platforms we're likely to meet.\r
+\r
+ If step == LONG_MIN then we still end up with LONG_MIN\r
+ after negation; but this works out, since we've still got\r
+ the correct value modulo ULONG_MAX+1, and the range_item\r
+ calculation is also done modulo ULONG_MAX+1.\r
+ */\r
+ it->start = (long)(start + (unsigned long)(len-1) * step);\r
+ it->step = (long)(0UL-step);\r
+\r
+ return (PyObject *)it;\r
+}\r
--- /dev/null
+\r
+/* set object implementation\r
+ Written and maintained by Raymond D. Hettinger <python@rcn.com>\r
+ Derived from Lib/sets.py and Objects/dictobject.c.\r
+\r
+ Copyright (c) 2003-2007 Python Software Foundation.\r
+ All rights reserved.\r
+*/\r
+\r
+#include "Python.h"\r
+#include "structmember.h"\r
+\r
+/* Set a key error with the specified argument, wrapping it in a\r
+ * tuple automatically so that tuple keys are not unpacked as the\r
+ * exception arguments. */\r
+static void\r
+set_key_error(PyObject *arg)\r
+{\r
+ PyObject *tup;\r
+ tup = PyTuple_Pack(1, arg);\r
+ if (!tup)\r
+ return; /* caller will expect error to be set anyway */\r
+ PyErr_SetObject(PyExc_KeyError, tup);\r
+ Py_DECREF(tup);\r
+}\r
+\r
+/* This must be >= 1. */\r
+#define PERTURB_SHIFT 5\r
+\r
+/* Object used as dummy key to fill deleted entries */\r
+static PyObject *dummy = NULL; /* Initialized by first call to make_new_set() */\r
+\r
+#ifdef Py_REF_DEBUG\r
+PyObject *\r
+_PySet_Dummy(void)\r
+{\r
+ return dummy;\r
+}\r
+#endif\r
+\r
+#define INIT_NONZERO_SET_SLOTS(so) do { \\r
+ (so)->table = (so)->smalltable; \\r
+ (so)->mask = PySet_MINSIZE - 1; \\r
+ (so)->hash = -1; \\r
+ } while(0)\r
+\r
+#define EMPTY_TO_MINSIZE(so) do { \\r
+ memset((so)->smalltable, 0, sizeof((so)->smalltable)); \\r
+ (so)->used = (so)->fill = 0; \\r
+ INIT_NONZERO_SET_SLOTS(so); \\r
+ } while(0)\r
+\r
+/* Reuse scheme to save calls to malloc, free, and memset */\r
+#ifndef PySet_MAXFREELIST\r
+#define PySet_MAXFREELIST 80\r
+#endif\r
+static PySetObject *free_list[PySet_MAXFREELIST];\r
+static int numfree = 0;\r
+\r
+/*\r
+The basic lookup function used by all operations.\r
+This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.\r
+Open addressing is preferred over chaining since the link overhead for\r
+chaining would be substantial (100% with typical malloc overhead).\r
+\r
+The initial probe index is computed as hash mod the table size. Subsequent\r
+probe indices are computed as explained in Objects/dictobject.c.\r
+\r
+All arithmetic on hash should ignore overflow.\r
+\r
+Unlike the dictionary implementation, the lookkey functions can return\r
+NULL if the rich comparison returns an error.\r
+*/\r
+\r
+static setentry *\r
+set_lookkey(PySetObject *so, PyObject *key, register long hash)\r
+{\r
+ register Py_ssize_t i;\r
+ register size_t perturb;\r
+ register setentry *freeslot;\r
+ register size_t mask = so->mask;\r
+ setentry *table = so->table;\r
+ register setentry *entry;\r
+ register int cmp;\r
+ PyObject *startkey;\r
+\r
+ i = hash & mask;\r
+ entry = &table[i];\r
+ if (entry->key == NULL || entry->key == key)\r
+ return entry;\r
+\r
+ if (entry->key == dummy)\r
+ freeslot = entry;\r
+ else {\r
+ if (entry->hash == hash) {\r
+ startkey = entry->key;\r
+ Py_INCREF(startkey);\r
+ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);\r
+ Py_DECREF(startkey);\r
+ if (cmp < 0)\r
+ return NULL;\r
+ if (table == so->table && entry->key == startkey) {\r
+ if (cmp > 0)\r
+ return entry;\r
+ }\r
+ else {\r
+ /* The compare did major nasty stuff to the\r
+ * set: start over.\r
+ */\r
+ return set_lookkey(so, key, hash);\r
+ }\r
+ }\r
+ freeslot = NULL;\r
+ }\r
+\r
+ /* In the loop, key == dummy is by far (factor of 100s) the\r
+ least likely outcome, so test for that last. */\r
+ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {\r
+ i = (i << 2) + i + perturb + 1;\r
+ entry = &table[i & mask];\r
+ if (entry->key == NULL) {\r
+ if (freeslot != NULL)\r
+ entry = freeslot;\r
+ break;\r
+ }\r
+ if (entry->key == key)\r
+ break;\r
+ if (entry->hash == hash && entry->key != dummy) {\r
+ startkey = entry->key;\r
+ Py_INCREF(startkey);\r
+ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);\r
+ Py_DECREF(startkey);\r
+ if (cmp < 0)\r
+ return NULL;\r
+ if (table == so->table && entry->key == startkey) {\r
+ if (cmp > 0)\r
+ break;\r
+ }\r
+ else {\r
+ /* The compare did major nasty stuff to the\r
+ * set: start over.\r
+ */\r
+ return set_lookkey(so, key, hash);\r
+ }\r
+ }\r
+ else if (entry->key == dummy && freeslot == NULL)\r
+ freeslot = entry;\r
+ }\r
+ return entry;\r
+}\r
+\r
+/*\r
+ * Hacked up version of set_lookkey which can assume keys are always strings;\r
+ * This means we can always use _PyString_Eq directly and not have to check to\r
+ * see if the comparison altered the table.\r
+ */\r
+static setentry *\r
+set_lookkey_string(PySetObject *so, PyObject *key, register long hash)\r
+{\r
+ register Py_ssize_t i;\r
+ register size_t perturb;\r
+ register setentry *freeslot;\r
+ register size_t mask = so->mask;\r
+ setentry *table = so->table;\r
+ register setentry *entry;\r
+\r
+ /* Make sure this function doesn't have to handle non-string keys,\r
+ including subclasses of str; e.g., one reason to subclass\r
+ strings is to override __eq__, and for speed we don't cater to\r
+ that here. */\r
+ if (!PyString_CheckExact(key)) {\r
+ so->lookup = set_lookkey;\r
+ return set_lookkey(so, key, hash);\r
+ }\r
+ i = hash & mask;\r
+ entry = &table[i];\r
+ if (entry->key == NULL || entry->key == key)\r
+ return entry;\r
+ if (entry->key == dummy)\r
+ freeslot = entry;\r
+ else {\r
+ if (entry->hash == hash && _PyString_Eq(entry->key, key))\r
+ return entry;\r
+ freeslot = NULL;\r
+ }\r
+\r
+ /* In the loop, key == dummy is by far (factor of 100s) the\r
+ least likely outcome, so test for that last. */\r
+ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {\r
+ i = (i << 2) + i + perturb + 1;\r
+ entry = &table[i & mask];\r
+ if (entry->key == NULL)\r
+ return freeslot == NULL ? entry : freeslot;\r
+ if (entry->key == key\r
+ || (entry->hash == hash\r
+ && entry->key != dummy\r
+ && _PyString_Eq(entry->key, key)))\r
+ return entry;\r
+ if (entry->key == dummy && freeslot == NULL)\r
+ freeslot = entry;\r
+ }\r
+ assert(0); /* NOT REACHED */\r
+ return 0;\r
+}\r
+\r
+/*\r
+Internal routine to insert a new key into the table.\r
+Used by the public insert routine.\r
+Eats a reference to key.\r
+*/\r
+static int\r
+set_insert_key(register PySetObject *so, PyObject *key, long hash)\r
+{\r
+ register setentry *entry;\r
+\r
+ assert(so->lookup != NULL);\r
+ entry = so->lookup(so, key, hash);\r
+ if (entry == NULL)\r
+ return -1;\r
+ if (entry->key == NULL) {\r
+ /* UNUSED */\r
+ so->fill++;\r
+ entry->key = key;\r
+ entry->hash = hash;\r
+ so->used++;\r
+ } else if (entry->key == dummy) {\r
+ /* DUMMY */\r
+ entry->key = key;\r
+ entry->hash = hash;\r
+ so->used++;\r
+ Py_DECREF(dummy);\r
+ } else {\r
+ /* ACTIVE */\r
+ Py_DECREF(key);\r
+ }\r
+ return 0;\r
+}\r
+\r
+/*\r
+Internal routine used by set_table_resize() to insert an item which is\r
+known to be absent from the set. This routine also assumes that\r
+the set contains no deleted entries. Besides the performance benefit,\r
+using set_insert_clean() in set_table_resize() is dangerous (SF bug #1456209).\r
+Note that no refcounts are changed by this routine; if needed, the caller\r
+is responsible for incref'ing `key`.\r
+*/\r
+static void\r
+set_insert_clean(register PySetObject *so, PyObject *key, long hash)\r
+{\r
+ register size_t i;\r
+ register size_t perturb;\r
+ register size_t mask = (size_t)so->mask;\r
+ setentry *table = so->table;\r
+ register setentry *entry;\r
+\r
+ i = hash & mask;\r
+ entry = &table[i];\r
+ for (perturb = hash; entry->key != NULL; perturb >>= PERTURB_SHIFT) {\r
+ i = (i << 2) + i + perturb + 1;\r
+ entry = &table[i & mask];\r
+ }\r
+ so->fill++;\r
+ entry->key = key;\r
+ entry->hash = hash;\r
+ so->used++;\r
+}\r
+\r
+/*\r
+Restructure the table by allocating a new table and reinserting all\r
+keys again. When entries have been deleted, the new table may\r
+actually be smaller than the old one.\r
+*/\r
+static int\r
+set_table_resize(PySetObject *so, Py_ssize_t minused)\r
+{\r
+ Py_ssize_t newsize;\r
+ setentry *oldtable, *newtable, *entry;\r
+ Py_ssize_t i;\r
+ int is_oldtable_malloced;\r
+ setentry small_copy[PySet_MINSIZE];\r
+\r
+ assert(minused >= 0);\r
+\r
+ /* Find the smallest table size > minused. */\r
+ for (newsize = PySet_MINSIZE;\r
+ newsize <= minused && newsize > 0;\r
+ newsize <<= 1)\r
+ ;\r
+ if (newsize <= 0) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+\r
+ /* Get space for a new table. */\r
+ oldtable = so->table;\r
+ assert(oldtable != NULL);\r
+ is_oldtable_malloced = oldtable != so->smalltable;\r
+\r
+ if (newsize == PySet_MINSIZE) {\r
+ /* A large table is shrinking, or we can't get any smaller. */\r
+ newtable = so->smalltable;\r
+ if (newtable == oldtable) {\r
+ if (so->fill == so->used) {\r
+ /* No dummies, so no point doing anything. */\r
+ return 0;\r
+ }\r
+ /* We're not going to resize it, but rebuild the\r
+ table anyway to purge old dummy entries.\r
+ Subtle: This is *necessary* if fill==size,\r
+ as set_lookkey needs at least one virgin slot to\r
+ terminate failing searches. If fill < size, it's\r
+ merely desirable, as dummies slow searches. */\r
+ assert(so->fill > so->used);\r
+ memcpy(small_copy, oldtable, sizeof(small_copy));\r
+ oldtable = small_copy;\r
+ }\r
+ }\r
+ else {\r
+ newtable = PyMem_NEW(setentry, newsize);\r
+ if (newtable == NULL) {\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ /* Make the set empty, using the new table. */\r
+ assert(newtable != oldtable);\r
+ so->table = newtable;\r
+ so->mask = newsize - 1;\r
+ memset(newtable, 0, sizeof(setentry) * newsize);\r
+ so->used = 0;\r
+ i = so->fill;\r
+ so->fill = 0;\r
+\r
+ /* Copy the data over; this is refcount-neutral for active entries;\r
+ dummy entries aren't copied over, of course */\r
+ for (entry = oldtable; i > 0; entry++) {\r
+ if (entry->key == NULL) {\r
+ /* UNUSED */\r
+ ;\r
+ } else if (entry->key == dummy) {\r
+ /* DUMMY */\r
+ --i;\r
+ assert(entry->key == dummy);\r
+ Py_DECREF(entry->key);\r
+ } else {\r
+ /* ACTIVE */\r
+ --i;\r
+ set_insert_clean(so, entry->key, entry->hash);\r
+ }\r
+ }\r
+\r
+ if (is_oldtable_malloced)\r
+ PyMem_DEL(oldtable);\r
+ return 0;\r
+}\r
+\r
+/* CAUTION: set_add_key/entry() must guarantee it won't resize the table */\r
+\r
+static int\r
+set_add_entry(register PySetObject *so, setentry *entry)\r
+{\r
+ register Py_ssize_t n_used;\r
+ PyObject *key = entry->key;\r
+ long hash = entry->hash;\r
+\r
+ assert(so->fill <= so->mask); /* at least one empty slot */\r
+ n_used = so->used;\r
+ Py_INCREF(key);\r
+ if (set_insert_key(so, key, hash) == -1) {\r
+ Py_DECREF(key);\r
+ return -1;\r
+ }\r
+ if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2))\r
+ return 0;\r
+ return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);\r
+}\r
+\r
+static int\r
+set_add_key(register PySetObject *so, PyObject *key)\r
+{\r
+ register long hash;\r
+ register Py_ssize_t n_used;\r
+\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return -1;\r
+ }\r
+ assert(so->fill <= so->mask); /* at least one empty slot */\r
+ n_used = so->used;\r
+ Py_INCREF(key);\r
+ if (set_insert_key(so, key, hash) == -1) {\r
+ Py_DECREF(key);\r
+ return -1;\r
+ }\r
+ if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2))\r
+ return 0;\r
+ return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);\r
+}\r
+\r
+#define DISCARD_NOTFOUND 0\r
+#define DISCARD_FOUND 1\r
+\r
+static int\r
+set_discard_entry(PySetObject *so, setentry *oldentry)\r
+{ register setentry *entry;\r
+ PyObject *old_key;\r
+\r
+ entry = (so->lookup)(so, oldentry->key, oldentry->hash);\r
+ if (entry == NULL)\r
+ return -1;\r
+ if (entry->key == NULL || entry->key == dummy)\r
+ return DISCARD_NOTFOUND;\r
+ old_key = entry->key;\r
+ Py_INCREF(dummy);\r
+ entry->key = dummy;\r
+ so->used--;\r
+ Py_DECREF(old_key);\r
+ return DISCARD_FOUND;\r
+}\r
+\r
+static int\r
+set_discard_key(PySetObject *so, PyObject *key)\r
+{\r
+ register long hash;\r
+ register setentry *entry;\r
+ PyObject *old_key;\r
+\r
+ assert (PyAnySet_Check(so));\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return -1;\r
+ }\r
+ entry = (so->lookup)(so, key, hash);\r
+ if (entry == NULL)\r
+ return -1;\r
+ if (entry->key == NULL || entry->key == dummy)\r
+ return DISCARD_NOTFOUND;\r
+ old_key = entry->key;\r
+ Py_INCREF(dummy);\r
+ entry->key = dummy;\r
+ so->used--;\r
+ Py_DECREF(old_key);\r
+ return DISCARD_FOUND;\r
+}\r
+\r
+static int\r
+set_clear_internal(PySetObject *so)\r
+{\r
+ setentry *entry, *table;\r
+ int table_is_malloced;\r
+ Py_ssize_t fill;\r
+ setentry small_copy[PySet_MINSIZE];\r
+#ifdef Py_DEBUG\r
+ Py_ssize_t i, n;\r
+ assert (PyAnySet_Check(so));\r
+\r
+ n = so->mask + 1;\r
+ i = 0;\r
+#endif\r
+\r
+ table = so->table;\r
+ assert(table != NULL);\r
+ table_is_malloced = table != so->smalltable;\r
+\r
+ /* This is delicate. During the process of clearing the set,\r
+ * decrefs can cause the set to mutate. To avoid fatal confusion\r
+ * (voice of experience), we have to make the set empty before\r
+ * clearing the slots, and never refer to anything via so->ref while\r
+ * clearing.\r
+ */\r
+ fill = so->fill;\r
+ if (table_is_malloced)\r
+ EMPTY_TO_MINSIZE(so);\r
+\r
+ else if (fill > 0) {\r
+ /* It's a small table with something that needs to be cleared.\r
+ * Afraid the only safe way is to copy the set entries into\r
+ * another small table first.\r
+ */\r
+ memcpy(small_copy, table, sizeof(small_copy));\r
+ table = small_copy;\r
+ EMPTY_TO_MINSIZE(so);\r
+ }\r
+ /* else it's a small table that's already empty */\r
+\r
+ /* Now we can finally clear things. If C had refcounts, we could\r
+ * assert that the refcount on table is 1 now, i.e. that this function\r
+ * has unique access to it, so decref side-effects can't alter it.\r
+ */\r
+ for (entry = table; fill > 0; ++entry) {\r
+#ifdef Py_DEBUG\r
+ assert(i < n);\r
+ ++i;\r
+#endif\r
+ if (entry->key) {\r
+ --fill;\r
+ Py_DECREF(entry->key);\r
+ }\r
+#ifdef Py_DEBUG\r
+ else\r
+ assert(entry->key == NULL);\r
+#endif\r
+ }\r
+\r
+ if (table_is_malloced)\r
+ PyMem_DEL(table);\r
+ return 0;\r
+}\r
+\r
+/*\r
+ * Iterate over a set table. Use like so:\r
+ *\r
+ * Py_ssize_t pos;\r
+ * setentry *entry;\r
+ * pos = 0; # important! pos should not otherwise be changed by you\r
+ * while (set_next(yourset, &pos, &entry)) {\r
+ * Refer to borrowed reference in entry->key.\r
+ * }\r
+ *\r
+ * CAUTION: In general, it isn't safe to use set_next in a loop that\r
+ * mutates the table.\r
+ */\r
+static int\r
+set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr)\r
+{\r
+ Py_ssize_t i;\r
+ Py_ssize_t mask;\r
+ register setentry *table;\r
+\r
+ assert (PyAnySet_Check(so));\r
+ i = *pos_ptr;\r
+ assert(i >= 0);\r
+ table = so->table;\r
+ mask = so->mask;\r
+ while (i <= mask && (table[i].key == NULL || table[i].key == dummy))\r
+ i++;\r
+ *pos_ptr = i+1;\r
+ if (i > mask)\r
+ return 0;\r
+ assert(table[i].key != NULL);\r
+ *entry_ptr = &table[i];\r
+ return 1;\r
+}\r
+\r
+static void\r
+set_dealloc(PySetObject *so)\r
+{\r
+ register setentry *entry;\r
+ Py_ssize_t fill = so->fill;\r
+ PyObject_GC_UnTrack(so);\r
+ Py_TRASHCAN_SAFE_BEGIN(so)\r
+ if (so->weakreflist != NULL)\r
+ PyObject_ClearWeakRefs((PyObject *) so);\r
+\r
+ for (entry = so->table; fill > 0; entry++) {\r
+ if (entry->key) {\r
+ --fill;\r
+ Py_DECREF(entry->key);\r
+ }\r
+ }\r
+ if (so->table != so->smalltable)\r
+ PyMem_DEL(so->table);\r
+ if (numfree < PySet_MAXFREELIST && PyAnySet_CheckExact(so))\r
+ free_list[numfree++] = so;\r
+ else\r
+ Py_TYPE(so)->tp_free(so);\r
+ Py_TRASHCAN_SAFE_END(so)\r
+}\r
+\r
+static int\r
+set_tp_print(PySetObject *so, FILE *fp, int flags)\r
+{\r
+ setentry *entry;\r
+ Py_ssize_t pos=0;\r
+ char *emit = ""; /* No separator emitted on first pass */\r
+ char *separator = ", ";\r
+ int status = Py_ReprEnter((PyObject*)so);\r
+\r
+ if (status != 0) {\r
+ if (status < 0)\r
+ return status;\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "%s(...)", so->ob_type->tp_name);\r
+ Py_END_ALLOW_THREADS\r
+ return 0;\r
+ }\r
+\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "%s([", so->ob_type->tp_name);\r
+ Py_END_ALLOW_THREADS\r
+ while (set_next(so, &pos, &entry)) {\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fputs(emit, fp);\r
+ Py_END_ALLOW_THREADS\r
+ emit = separator;\r
+ if (PyObject_Print(entry->key, fp, 0) != 0) {\r
+ Py_ReprLeave((PyObject*)so);\r
+ return -1;\r
+ }\r
+ }\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fputs("])", fp);\r
+ Py_END_ALLOW_THREADS\r
+ Py_ReprLeave((PyObject*)so);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+set_repr(PySetObject *so)\r
+{\r
+ PyObject *keys, *result=NULL, *listrepr;\r
+ int status = Py_ReprEnter((PyObject*)so);\r
+\r
+ if (status != 0) {\r
+ if (status < 0)\r
+ return NULL;\r
+ return PyString_FromFormat("%s(...)", so->ob_type->tp_name);\r
+ }\r
+\r
+ keys = PySequence_List((PyObject *)so);\r
+ if (keys == NULL)\r
+ goto done;\r
+ listrepr = PyObject_Repr(keys);\r
+ Py_DECREF(keys);\r
+ if (listrepr == NULL)\r
+ goto done;\r
+\r
+ result = PyString_FromFormat("%s(%s)", so->ob_type->tp_name,\r
+ PyString_AS_STRING(listrepr));\r
+ Py_DECREF(listrepr);\r
+done:\r
+ Py_ReprLeave((PyObject*)so);\r
+ return result;\r
+}\r
+\r
+static Py_ssize_t\r
+set_len(PyObject *so)\r
+{\r
+ return ((PySetObject *)so)->used;\r
+}\r
+\r
+static int\r
+set_merge(PySetObject *so, PyObject *otherset)\r
+{\r
+ PySetObject *other;\r
+ PyObject *key;\r
+ long hash;\r
+ register Py_ssize_t i;\r
+ register setentry *entry;\r
+\r
+ assert (PyAnySet_Check(so));\r
+ assert (PyAnySet_Check(otherset));\r
+\r
+ other = (PySetObject*)otherset;\r
+ if (other == so || other->used == 0)\r
+ /* a.update(a) or a.update({}); nothing to do */\r
+ return 0;\r
+ /* Do one big resize at the start, rather than\r
+ * incrementally resizing as we insert new keys. Expect\r
+ * that there will be no (or few) overlapping keys.\r
+ */\r
+ if ((so->fill + other->used)*3 >= (so->mask+1)*2) {\r
+ if (set_table_resize(so, (so->used + other->used)*2) != 0)\r
+ return -1;\r
+ }\r
+ for (i = 0; i <= other->mask; i++) {\r
+ entry = &other->table[i];\r
+ key = entry->key;\r
+ hash = entry->hash;\r
+ if (key != NULL &&\r
+ key != dummy) {\r
+ Py_INCREF(key);\r
+ if (set_insert_key(so, key, hash) == -1) {\r
+ Py_DECREF(key);\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+set_contains_key(PySetObject *so, PyObject *key)\r
+{\r
+ long hash;\r
+ setentry *entry;\r
+\r
+ if (!PyString_CheckExact(key) ||\r
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {\r
+ hash = PyObject_Hash(key);\r
+ if (hash == -1)\r
+ return -1;\r
+ }\r
+ entry = (so->lookup)(so, key, hash);\r
+ if (entry == NULL)\r
+ return -1;\r
+ key = entry->key;\r
+ return key != NULL && key != dummy;\r
+}\r
+\r
+static int\r
+set_contains_entry(PySetObject *so, setentry *entry)\r
+{\r
+ PyObject *key;\r
+ setentry *lu_entry;\r
+\r
+ lu_entry = (so->lookup)(so, entry->key, entry->hash);\r
+ if (lu_entry == NULL)\r
+ return -1;\r
+ key = lu_entry->key;\r
+ return key != NULL && key != dummy;\r
+}\r
+\r
+static PyObject *\r
+set_pop(PySetObject *so)\r
+{\r
+ register Py_ssize_t i = 0;\r
+ register setentry *entry;\r
+ PyObject *key;\r
+\r
+ assert (PyAnySet_Check(so));\r
+ if (so->used == 0) {\r
+ PyErr_SetString(PyExc_KeyError, "pop from an empty set");\r
+ return NULL;\r
+ }\r
+\r
+ /* Set entry to "the first" unused or dummy set entry. We abuse\r
+ * the hash field of slot 0 to hold a search finger:\r
+ * If slot 0 has a value, use slot 0.\r
+ * Else slot 0 is being used to hold a search finger,\r
+ * and we use its hash value as the first index to look.\r
+ */\r
+ entry = &so->table[0];\r
+ if (entry->key == NULL || entry->key == dummy) {\r
+ i = entry->hash;\r
+ /* The hash field may be a real hash value, or it may be a\r
+ * legit search finger, or it may be a once-legit search\r
+ * finger that's out of bounds now because it wrapped around\r
+ * or the table shrunk -- simply make sure it's in bounds now.\r
+ */\r
+ if (i > so->mask || i < 1)\r
+ i = 1; /* skip slot 0 */\r
+ while ((entry = &so->table[i])->key == NULL || entry->key==dummy) {\r
+ i++;\r
+ if (i > so->mask)\r
+ i = 1;\r
+ }\r
+ }\r
+ key = entry->key;\r
+ Py_INCREF(dummy);\r
+ entry->key = dummy;\r
+ so->used--;\r
+ so->table[0].hash = i + 1; /* next place to start */\r
+ return key;\r
+}\r
+\r
+PyDoc_STRVAR(pop_doc, "Remove and return an arbitrary set element.\n\\r
+Raises KeyError if the set is empty.");\r
+\r
+static int\r
+set_traverse(PySetObject *so, visitproc visit, void *arg)\r
+{\r
+ Py_ssize_t pos = 0;\r
+ setentry *entry;\r
+\r
+ while (set_next(so, &pos, &entry))\r
+ Py_VISIT(entry->key);\r
+ return 0;\r
+}\r
+\r
+static long\r
+frozenset_hash(PyObject *self)\r
+{\r
+ PySetObject *so = (PySetObject *)self;\r
+ long h, hash = 1927868237L;\r
+ setentry *entry;\r
+ Py_ssize_t pos = 0;\r
+\r
+ if (so->hash != -1)\r
+ return so->hash;\r
+\r
+ hash *= PySet_GET_SIZE(self) + 1;\r
+ while (set_next(so, &pos, &entry)) {\r
+ /* Work to increase the bit dispersion for closely spaced hash\r
+ values. The is important because some use cases have many\r
+ combinations of a small number of elements with nearby\r
+ hashes so that many distinct combinations collapse to only\r
+ a handful of distinct hash values. */\r
+ h = entry->hash;\r
+ hash ^= (h ^ (h << 16) ^ 89869747L) * 3644798167u;\r
+ }\r
+ hash = hash * 69069L + 907133923L;\r
+ if (hash == -1)\r
+ hash = 590923713L;\r
+ so->hash = hash;\r
+ return hash;\r
+}\r
+\r
+/***** Set iterator type ***********************************************/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PySetObject *si_set; /* Set to NULL when iterator is exhausted */\r
+ Py_ssize_t si_used;\r
+ Py_ssize_t si_pos;\r
+ Py_ssize_t len;\r
+} setiterobject;\r
+\r
+static void\r
+setiter_dealloc(setiterobject *si)\r
+{\r
+ Py_XDECREF(si->si_set);\r
+ PyObject_GC_Del(si);\r
+}\r
+\r
+static int\r
+setiter_traverse(setiterobject *si, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(si->si_set);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+setiter_len(setiterobject *si)\r
+{\r
+ Py_ssize_t len = 0;\r
+ if (si->si_set != NULL && si->si_used == si->si_set->used)\r
+ len = si->len;\r
+ return PyInt_FromLong(len);\r
+}\r
+\r
+PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
+\r
+static PyMethodDef setiter_methods[] = {\r
+ {"__length_hint__", (PyCFunction)setiter_len, METH_NOARGS, length_hint_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyObject *setiter_iternext(setiterobject *si)\r
+{\r
+ PyObject *key;\r
+ register Py_ssize_t i, mask;\r
+ register setentry *entry;\r
+ PySetObject *so = si->si_set;\r
+\r
+ if (so == NULL)\r
+ return NULL;\r
+ assert (PyAnySet_Check(so));\r
+\r
+ if (si->si_used != so->used) {\r
+ PyErr_SetString(PyExc_RuntimeError,\r
+ "Set changed size during iteration");\r
+ si->si_used = -1; /* Make this state sticky */\r
+ return NULL;\r
+ }\r
+\r
+ i = si->si_pos;\r
+ assert(i>=0);\r
+ entry = so->table;\r
+ mask = so->mask;\r
+ while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy))\r
+ i++;\r
+ si->si_pos = i+1;\r
+ if (i > mask)\r
+ goto fail;\r
+ si->len--;\r
+ key = entry[i].key;\r
+ Py_INCREF(key);\r
+ return key;\r
+\r
+fail:\r
+ Py_DECREF(so);\r
+ si->si_set = NULL;\r
+ return NULL;\r
+}\r
+\r
+static PyTypeObject PySetIter_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "setiterator", /* tp_name */\r
+ sizeof(setiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)setiter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)setiter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)setiter_iternext, /* tp_iternext */\r
+ setiter_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *\r
+set_iter(PySetObject *so)\r
+{\r
+ setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);\r
+ if (si == NULL)\r
+ return NULL;\r
+ Py_INCREF(so);\r
+ si->si_set = so;\r
+ si->si_used = so->used;\r
+ si->si_pos = 0;\r
+ si->len = so->used;\r
+ _PyObject_GC_TRACK(si);\r
+ return (PyObject *)si;\r
+}\r
+\r
+static int\r
+set_update_internal(PySetObject *so, PyObject *other)\r
+{\r
+ PyObject *key, *it;\r
+\r
+ if (PyAnySet_Check(other))\r
+ return set_merge(so, other);\r
+\r
+ if (PyDict_CheckExact(other)) {\r
+ PyObject *value;\r
+ Py_ssize_t pos = 0;\r
+ long hash;\r
+ Py_ssize_t dictsize = PyDict_Size(other);\r
+\r
+ /* Do one big resize at the start, rather than\r
+ * incrementally resizing as we insert new keys. Expect\r
+ * that there will be no (or few) overlapping keys.\r
+ */\r
+ if (dictsize == -1)\r
+ return -1;\r
+ if ((so->fill + dictsize)*3 >= (so->mask+1)*2) {\r
+ if (set_table_resize(so, (so->used + dictsize)*2) != 0)\r
+ return -1;\r
+ }\r
+ while (_PyDict_Next(other, &pos, &key, &value, &hash)) {\r
+ setentry an_entry;\r
+\r
+ an_entry.hash = hash;\r
+ an_entry.key = key;\r
+ if (set_add_entry(so, &an_entry) == -1)\r
+ return -1;\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ it = PyObject_GetIter(other);\r
+ if (it == NULL)\r
+ return -1;\r
+\r
+ while ((key = PyIter_Next(it)) != NULL) {\r
+ if (set_add_key(so, key) == -1) {\r
+ Py_DECREF(it);\r
+ Py_DECREF(key);\r
+ return -1;\r
+ }\r
+ Py_DECREF(key);\r
+ }\r
+ Py_DECREF(it);\r
+ if (PyErr_Occurred())\r
+ return -1;\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+set_update(PySetObject *so, PyObject *args)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {\r
+ PyObject *other = PyTuple_GET_ITEM(args, i);\r
+ if (set_update_internal(so, other) == -1)\r
+ return NULL;\r
+ }\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(update_doc,\r
+"Update a set with the union of itself and others.");\r
+\r
+static PyObject *\r
+make_new_set(PyTypeObject *type, PyObject *iterable)\r
+{\r
+ register PySetObject *so = NULL;\r
+\r
+ if (dummy == NULL) { /* Auto-initialize dummy */\r
+ dummy = PyString_FromString("<dummy key>");\r
+ if (dummy == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ /* create PySetObject structure */\r
+ if (numfree &&\r
+ (type == &PySet_Type || type == &PyFrozenSet_Type)) {\r
+ so = free_list[--numfree];\r
+ assert (so != NULL && PyAnySet_CheckExact(so));\r
+ Py_TYPE(so) = type;\r
+ _Py_NewReference((PyObject *)so);\r
+ EMPTY_TO_MINSIZE(so);\r
+ PyObject_GC_Track(so);\r
+ } else {\r
+ so = (PySetObject *)type->tp_alloc(type, 0);\r
+ if (so == NULL)\r
+ return NULL;\r
+ /* tp_alloc has already zeroed the structure */\r
+ assert(so->table == NULL && so->fill == 0 && so->used == 0);\r
+ INIT_NONZERO_SET_SLOTS(so);\r
+ }\r
+\r
+ so->lookup = set_lookkey_string;\r
+ so->weakreflist = NULL;\r
+\r
+ if (iterable != NULL) {\r
+ if (set_update_internal(so, iterable) == -1) {\r
+ Py_DECREF(so);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ return (PyObject *)so;\r
+}\r
+\r
+/* The empty frozenset is a singleton */\r
+static PyObject *emptyfrozenset = NULL;\r
+\r
+static PyObject *\r
+frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *iterable = NULL, *result;\r
+\r
+ if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset()", kwds))\r
+ return NULL;\r
+\r
+ if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable))\r
+ return NULL;\r
+\r
+ if (type != &PyFrozenSet_Type)\r
+ return make_new_set(type, iterable);\r
+\r
+ if (iterable != NULL) {\r
+ /* frozenset(f) is idempotent */\r
+ if (PyFrozenSet_CheckExact(iterable)) {\r
+ Py_INCREF(iterable);\r
+ return iterable;\r
+ }\r
+ result = make_new_set(type, iterable);\r
+ if (result == NULL || PySet_GET_SIZE(result))\r
+ return result;\r
+ Py_DECREF(result);\r
+ }\r
+ /* The empty frozenset is a singleton */\r
+ if (emptyfrozenset == NULL)\r
+ emptyfrozenset = make_new_set(type, NULL);\r
+ Py_XINCREF(emptyfrozenset);\r
+ return emptyfrozenset;\r
+}\r
+\r
+void\r
+PySet_Fini(void)\r
+{\r
+ PySetObject *so;\r
+\r
+ while (numfree) {\r
+ numfree--;\r
+ so = free_list[numfree];\r
+ PyObject_GC_Del(so);\r
+ }\r
+ Py_CLEAR(dummy);\r
+ Py_CLEAR(emptyfrozenset);\r
+}\r
+\r
+static PyObject *\r
+set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ if (type == &PySet_Type && !_PyArg_NoKeywords("set()", kwds))\r
+ return NULL;\r
+\r
+ return make_new_set(type, NULL);\r
+}\r
+\r
+/* set_swap_bodies() switches the contents of any two sets by moving their\r
+ internal data pointers and, if needed, copying the internal smalltables.\r
+ Semantically equivalent to:\r
+\r
+ t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t\r
+\r
+ The function always succeeds and it leaves both objects in a stable state.\r
+ Useful for creating temporary frozensets from sets for membership testing\r
+ in __contains__(), discard(), and remove(). Also useful for operations\r
+ that update in-place (by allowing an intermediate result to be swapped\r
+ into one of the original inputs).\r
+*/\r
+\r
+static void\r
+set_swap_bodies(PySetObject *a, PySetObject *b)\r
+{\r
+ Py_ssize_t t;\r
+ setentry *u;\r
+ setentry *(*f)(PySetObject *so, PyObject *key, long hash);\r
+ setentry tab[PySet_MINSIZE];\r
+ long h;\r
+\r
+ t = a->fill; a->fill = b->fill; b->fill = t;\r
+ t = a->used; a->used = b->used; b->used = t;\r
+ t = a->mask; a->mask = b->mask; b->mask = t;\r
+\r
+ u = a->table;\r
+ if (a->table == a->smalltable)\r
+ u = b->smalltable;\r
+ a->table = b->table;\r
+ if (b->table == b->smalltable)\r
+ a->table = a->smalltable;\r
+ b->table = u;\r
+\r
+ f = a->lookup; a->lookup = b->lookup; b->lookup = f;\r
+\r
+ if (a->table == a->smalltable || b->table == b->smalltable) {\r
+ memcpy(tab, a->smalltable, sizeof(tab));\r
+ memcpy(a->smalltable, b->smalltable, sizeof(tab));\r
+ memcpy(b->smalltable, tab, sizeof(tab));\r
+ }\r
+\r
+ if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type) &&\r
+ PyType_IsSubtype(Py_TYPE(b), &PyFrozenSet_Type)) {\r
+ h = a->hash; a->hash = b->hash; b->hash = h;\r
+ } else {\r
+ a->hash = -1;\r
+ b->hash = -1;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+set_copy(PySetObject *so)\r
+{\r
+ return make_new_set(Py_TYPE(so), (PyObject *)so);\r
+}\r
+\r
+static PyObject *\r
+frozenset_copy(PySetObject *so)\r
+{\r
+ if (PyFrozenSet_CheckExact(so)) {\r
+ Py_INCREF(so);\r
+ return (PyObject *)so;\r
+ }\r
+ return set_copy(so);\r
+}\r
+\r
+PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set.");\r
+\r
+static PyObject *\r
+set_clear(PySetObject *so)\r
+{\r
+ set_clear_internal(so);\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(clear_doc, "Remove all elements from this set.");\r
+\r
+static PyObject *\r
+set_union(PySetObject *so, PyObject *args)\r
+{\r
+ PySetObject *result;\r
+ PyObject *other;\r
+ Py_ssize_t i;\r
+\r
+ result = (PySetObject *)set_copy(so);\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {\r
+ other = PyTuple_GET_ITEM(args, i);\r
+ if ((PyObject *)so == other)\r
+ continue;\r
+ if (set_update_internal(result, other) == -1) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ }\r
+ return (PyObject *)result;\r
+}\r
+\r
+PyDoc_STRVAR(union_doc,\r
+ "Return the union of sets as a new set.\n\\r
+\n\\r
+(i.e. all elements that are in either set.)");\r
+\r
+static PyObject *\r
+set_or(PySetObject *so, PyObject *other)\r
+{\r
+ PySetObject *result;\r
+\r
+ if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+\r
+ result = (PySetObject *)set_copy(so);\r
+ if (result == NULL)\r
+ return NULL;\r
+ if ((PyObject *)so == other)\r
+ return (PyObject *)result;\r
+ if (set_update_internal(result, other) == -1) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ return (PyObject *)result;\r
+}\r
+\r
+static PyObject *\r
+set_ior(PySetObject *so, PyObject *other)\r
+{\r
+ if (!PyAnySet_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ if (set_update_internal(so, other) == -1)\r
+ return NULL;\r
+ Py_INCREF(so);\r
+ return (PyObject *)so;\r
+}\r
+\r
+static PyObject *\r
+set_intersection(PySetObject *so, PyObject *other)\r
+{\r
+ PySetObject *result;\r
+ PyObject *key, *it, *tmp;\r
+\r
+ if ((PyObject *)so == other)\r
+ return set_copy(so);\r
+\r
+ result = (PySetObject *)make_new_set(Py_TYPE(so), NULL);\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ if (PyAnySet_Check(other)) {\r
+ Py_ssize_t pos = 0;\r
+ setentry *entry;\r
+\r
+ if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {\r
+ tmp = (PyObject *)so;\r
+ so = (PySetObject *)other;\r
+ other = tmp;\r
+ }\r
+\r
+ while (set_next((PySetObject *)other, &pos, &entry)) {\r
+ int rv = set_contains_entry(so, entry);\r
+ if (rv == -1) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ if (rv) {\r
+ if (set_add_entry(result, entry) == -1) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ }\r
+ }\r
+ return (PyObject *)result;\r
+ }\r
+\r
+ it = PyObject_GetIter(other);\r
+ if (it == NULL) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+\r
+ while ((key = PyIter_Next(it)) != NULL) {\r
+ int rv;\r
+ setentry entry;\r
+ long hash = PyObject_Hash(key);\r
+\r
+ if (hash == -1) {\r
+ Py_DECREF(it);\r
+ Py_DECREF(result);\r
+ Py_DECREF(key);\r
+ return NULL;\r
+ }\r
+ entry.hash = hash;\r
+ entry.key = key;\r
+ rv = set_contains_entry(so, &entry);\r
+ if (rv == -1) {\r
+ Py_DECREF(it);\r
+ Py_DECREF(result);\r
+ Py_DECREF(key);\r
+ return NULL;\r
+ }\r
+ if (rv) {\r
+ if (set_add_entry(result, &entry) == -1) {\r
+ Py_DECREF(it);\r
+ Py_DECREF(result);\r
+ Py_DECREF(key);\r
+ return NULL;\r
+ }\r
+ }\r
+ Py_DECREF(key);\r
+ }\r
+ Py_DECREF(it);\r
+ if (PyErr_Occurred()) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ return (PyObject *)result;\r
+}\r
+\r
+static PyObject *\r
+set_intersection_multi(PySetObject *so, PyObject *args)\r
+{\r
+ Py_ssize_t i;\r
+ PyObject *result = (PyObject *)so;\r
+\r
+ if (PyTuple_GET_SIZE(args) == 0)\r
+ return set_copy(so);\r
+\r
+ Py_INCREF(so);\r
+ for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {\r
+ PyObject *other = PyTuple_GET_ITEM(args, i);\r
+ PyObject *newresult = set_intersection((PySetObject *)result, other);\r
+ if (newresult == NULL) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ Py_DECREF(result);\r
+ result = newresult;\r
+ }\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(intersection_doc,\r
+"Return the intersection of two or more sets as a new set.\n\\r
+\n\\r
+(i.e. elements that are common to all of the sets.)");\r
+\r
+static PyObject *\r
+set_intersection_update(PySetObject *so, PyObject *other)\r
+{\r
+ PyObject *tmp;\r
+\r
+ tmp = set_intersection(so, other);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ set_swap_bodies(so, (PySetObject *)tmp);\r
+ Py_DECREF(tmp);\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+static PyObject *\r
+set_intersection_update_multi(PySetObject *so, PyObject *args)\r
+{\r
+ PyObject *tmp;\r
+\r
+ tmp = set_intersection_multi(so, args);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ set_swap_bodies(so, (PySetObject *)tmp);\r
+ Py_DECREF(tmp);\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(intersection_update_doc,\r
+"Update a set with the intersection of itself and another.");\r
+\r
+static PyObject *\r
+set_and(PySetObject *so, PyObject *other)\r
+{\r
+ if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ return set_intersection(so, other);\r
+}\r
+\r
+static PyObject *\r
+set_iand(PySetObject *so, PyObject *other)\r
+{\r
+ PyObject *result;\r
+\r
+ if (!PyAnySet_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ result = set_intersection_update(so, other);\r
+ if (result == NULL)\r
+ return NULL;\r
+ Py_DECREF(result);\r
+ Py_INCREF(so);\r
+ return (PyObject *)so;\r
+}\r
+\r
+static PyObject *\r
+set_isdisjoint(PySetObject *so, PyObject *other)\r
+{\r
+ PyObject *key, *it, *tmp;\r
+\r
+ if ((PyObject *)so == other) {\r
+ if (PySet_GET_SIZE(so) == 0)\r
+ Py_RETURN_TRUE;\r
+ else\r
+ Py_RETURN_FALSE;\r
+ }\r
+\r
+ if (PyAnySet_CheckExact(other)) {\r
+ Py_ssize_t pos = 0;\r
+ setentry *entry;\r
+\r
+ if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {\r
+ tmp = (PyObject *)so;\r
+ so = (PySetObject *)other;\r
+ other = tmp;\r
+ }\r
+ while (set_next((PySetObject *)other, &pos, &entry)) {\r
+ int rv = set_contains_entry(so, entry);\r
+ if (rv == -1)\r
+ return NULL;\r
+ if (rv)\r
+ Py_RETURN_FALSE;\r
+ }\r
+ Py_RETURN_TRUE;\r
+ }\r
+\r
+ it = PyObject_GetIter(other);\r
+ if (it == NULL)\r
+ return NULL;\r
+\r
+ while ((key = PyIter_Next(it)) != NULL) {\r
+ int rv;\r
+ setentry entry;\r
+ long hash = PyObject_Hash(key);\r
+\r
+ if (hash == -1) {\r
+ Py_DECREF(key);\r
+ Py_DECREF(it);\r
+ return NULL;\r
+ }\r
+ entry.hash = hash;\r
+ entry.key = key;\r
+ rv = set_contains_entry(so, &entry);\r
+ Py_DECREF(key);\r
+ if (rv == -1) {\r
+ Py_DECREF(it);\r
+ return NULL;\r
+ }\r
+ if (rv) {\r
+ Py_DECREF(it);\r
+ Py_RETURN_FALSE;\r
+ }\r
+ }\r
+ Py_DECREF(it);\r
+ if (PyErr_Occurred())\r
+ return NULL;\r
+ Py_RETURN_TRUE;\r
+}\r
+\r
+PyDoc_STRVAR(isdisjoint_doc,\r
+"Return True if two sets have a null intersection.");\r
+\r
+static int\r
+set_difference_update_internal(PySetObject *so, PyObject *other)\r
+{\r
+ if ((PyObject *)so == other)\r
+ return set_clear_internal(so);\r
+\r
+ if (PyAnySet_Check(other)) {\r
+ setentry *entry;\r
+ Py_ssize_t pos = 0;\r
+\r
+ while (set_next((PySetObject *)other, &pos, &entry))\r
+ if (set_discard_entry(so, entry) == -1)\r
+ return -1;\r
+ } else {\r
+ PyObject *key, *it;\r
+ it = PyObject_GetIter(other);\r
+ if (it == NULL)\r
+ return -1;\r
+\r
+ while ((key = PyIter_Next(it)) != NULL) {\r
+ if (set_discard_key(so, key) == -1) {\r
+ Py_DECREF(it);\r
+ Py_DECREF(key);\r
+ return -1;\r
+ }\r
+ Py_DECREF(key);\r
+ }\r
+ Py_DECREF(it);\r
+ if (PyErr_Occurred())\r
+ return -1;\r
+ }\r
+ /* If more than 1/5 are dummies, then resize them away. */\r
+ if ((so->fill - so->used) * 5 < so->mask)\r
+ return 0;\r
+ return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);\r
+}\r
+\r
+static PyObject *\r
+set_difference_update(PySetObject *so, PyObject *args)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {\r
+ PyObject *other = PyTuple_GET_ITEM(args, i);\r
+ if (set_difference_update_internal(so, other) == -1)\r
+ return NULL;\r
+ }\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(difference_update_doc,\r
+"Remove all elements of another set from this set.");\r
+\r
+static PyObject *\r
+set_difference(PySetObject *so, PyObject *other)\r
+{\r
+ PyObject *result;\r
+ setentry *entry;\r
+ Py_ssize_t pos = 0;\r
+\r
+ if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) {\r
+ result = set_copy(so);\r
+ if (result == NULL)\r
+ return NULL;\r
+ if (set_difference_update_internal((PySetObject *)result, other) != -1)\r
+ return result;\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+\r
+ result = make_new_set(Py_TYPE(so), NULL);\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ if (PyDict_CheckExact(other)) {\r
+ while (set_next(so, &pos, &entry)) {\r
+ setentry entrycopy;\r
+ entrycopy.hash = entry->hash;\r
+ entrycopy.key = entry->key;\r
+ if (!_PyDict_Contains(other, entry->key, entry->hash)) {\r
+ if (set_add_entry((PySetObject *)result, &entrycopy) == -1) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+ while (set_next(so, &pos, &entry)) {\r
+ int rv = set_contains_entry((PySetObject *)other, entry);\r
+ if (rv == -1) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ if (!rv) {\r
+ if (set_add_entry((PySetObject *)result, entry) == -1) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+set_difference_multi(PySetObject *so, PyObject *args)\r
+{\r
+ Py_ssize_t i;\r
+ PyObject *result, *other;\r
+\r
+ if (PyTuple_GET_SIZE(args) == 0)\r
+ return set_copy(so);\r
+\r
+ other = PyTuple_GET_ITEM(args, 0);\r
+ result = set_difference(so, other);\r
+ if (result == NULL)\r
+ return NULL;\r
+\r
+ for (i=1 ; i<PyTuple_GET_SIZE(args) ; i++) {\r
+ other = PyTuple_GET_ITEM(args, i);\r
+ if (set_difference_update_internal((PySetObject *)result, other) == -1) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ }\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(difference_doc,\r
+"Return the difference of two or more sets as a new set.\n\\r
+\n\\r
+(i.e. all elements that are in this set but not the others.)");\r
+static PyObject *\r
+set_sub(PySetObject *so, PyObject *other)\r
+{\r
+ if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ return set_difference(so, other);\r
+}\r
+\r
+static PyObject *\r
+set_isub(PySetObject *so, PyObject *other)\r
+{\r
+ if (!PyAnySet_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ if (set_difference_update_internal(so, other) == -1)\r
+ return NULL;\r
+ Py_INCREF(so);\r
+ return (PyObject *)so;\r
+}\r
+\r
+static PyObject *\r
+set_symmetric_difference_update(PySetObject *so, PyObject *other)\r
+{\r
+ PySetObject *otherset;\r
+ PyObject *key;\r
+ Py_ssize_t pos = 0;\r
+ setentry *entry;\r
+\r
+ if ((PyObject *)so == other)\r
+ return set_clear(so);\r
+\r
+ if (PyDict_CheckExact(other)) {\r
+ PyObject *value;\r
+ int rv;\r
+ long hash;\r
+ while (_PyDict_Next(other, &pos, &key, &value, &hash)) {\r
+ setentry an_entry;\r
+\r
+ Py_INCREF(key);\r
+ an_entry.hash = hash;\r
+ an_entry.key = key;\r
+\r
+ rv = set_discard_entry(so, &an_entry);\r
+ if (rv == -1) {\r
+ Py_DECREF(key);\r
+ return NULL;\r
+ }\r
+ if (rv == DISCARD_NOTFOUND) {\r
+ if (set_add_entry(so, &an_entry) == -1) {\r
+ Py_DECREF(key);\r
+ return NULL;\r
+ }\r
+ }\r
+ Py_DECREF(key);\r
+ }\r
+ Py_RETURN_NONE;\r
+ }\r
+\r
+ if (PyAnySet_Check(other)) {\r
+ Py_INCREF(other);\r
+ otherset = (PySetObject *)other;\r
+ } else {\r
+ otherset = (PySetObject *)make_new_set(Py_TYPE(so), other);\r
+ if (otherset == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ while (set_next(otherset, &pos, &entry)) {\r
+ int rv = set_discard_entry(so, entry);\r
+ if (rv == -1) {\r
+ Py_DECREF(otherset);\r
+ return NULL;\r
+ }\r
+ if (rv == DISCARD_NOTFOUND) {\r
+ if (set_add_entry(so, entry) == -1) {\r
+ Py_DECREF(otherset);\r
+ return NULL;\r
+ }\r
+ }\r
+ }\r
+ Py_DECREF(otherset);\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(symmetric_difference_update_doc,\r
+"Update a set with the symmetric difference of itself and another.");\r
+\r
+static PyObject *\r
+set_symmetric_difference(PySetObject *so, PyObject *other)\r
+{\r
+ PyObject *rv;\r
+ PySetObject *otherset;\r
+\r
+ otherset = (PySetObject *)make_new_set(Py_TYPE(so), other);\r
+ if (otherset == NULL)\r
+ return NULL;\r
+ rv = set_symmetric_difference_update(otherset, (PyObject *)so);\r
+ if (rv == NULL)\r
+ return NULL;\r
+ Py_DECREF(rv);\r
+ return (PyObject *)otherset;\r
+}\r
+\r
+PyDoc_STRVAR(symmetric_difference_doc,\r
+"Return the symmetric difference of two sets as a new set.\n\\r
+\n\\r
+(i.e. all elements that are in exactly one of the sets.)");\r
+\r
+static PyObject *\r
+set_xor(PySetObject *so, PyObject *other)\r
+{\r
+ if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ return set_symmetric_difference(so, other);\r
+}\r
+\r
+static PyObject *\r
+set_ixor(PySetObject *so, PyObject *other)\r
+{\r
+ PyObject *result;\r
+\r
+ if (!PyAnySet_Check(other)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ result = set_symmetric_difference_update(so, other);\r
+ if (result == NULL)\r
+ return NULL;\r
+ Py_DECREF(result);\r
+ Py_INCREF(so);\r
+ return (PyObject *)so;\r
+}\r
+\r
+static PyObject *\r
+set_issubset(PySetObject *so, PyObject *other)\r
+{\r
+ setentry *entry;\r
+ Py_ssize_t pos = 0;\r
+\r
+ if (!PyAnySet_Check(other)) {\r
+ PyObject *tmp, *result;\r
+ tmp = make_new_set(&PySet_Type, other);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ result = set_issubset(so, tmp);\r
+ Py_DECREF(tmp);\r
+ return result;\r
+ }\r
+ if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))\r
+ Py_RETURN_FALSE;\r
+\r
+ while (set_next(so, &pos, &entry)) {\r
+ int rv = set_contains_entry((PySetObject *)other, entry);\r
+ if (rv == -1)\r
+ return NULL;\r
+ if (!rv)\r
+ Py_RETURN_FALSE;\r
+ }\r
+ Py_RETURN_TRUE;\r
+}\r
+\r
+PyDoc_STRVAR(issubset_doc, "Report whether another set contains this set.");\r
+\r
+static PyObject *\r
+set_issuperset(PySetObject *so, PyObject *other)\r
+{\r
+ PyObject *tmp, *result;\r
+\r
+ if (!PyAnySet_Check(other)) {\r
+ tmp = make_new_set(&PySet_Type, other);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ result = set_issuperset(so, tmp);\r
+ Py_DECREF(tmp);\r
+ return result;\r
+ }\r
+ return set_issubset((PySetObject *)other, (PyObject *)so);\r
+}\r
+\r
+PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set.");\r
+\r
+static PyObject *\r
+set_richcompare(PySetObject *v, PyObject *w, int op)\r
+{\r
+ PyObject *r1, *r2;\r
+\r
+ if(!PyAnySet_Check(w)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ switch (op) {\r
+ case Py_EQ:\r
+ if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))\r
+ Py_RETURN_FALSE;\r
+ if (v->hash != -1 &&\r
+ ((PySetObject *)w)->hash != -1 &&\r
+ v->hash != ((PySetObject *)w)->hash)\r
+ Py_RETURN_FALSE;\r
+ return set_issubset(v, w);\r
+ case Py_NE:\r
+ r1 = set_richcompare(v, w, Py_EQ);\r
+ if (r1 == NULL)\r
+ return NULL;\r
+ r2 = PyBool_FromLong(PyObject_Not(r1));\r
+ Py_DECREF(r1);\r
+ return r2;\r
+ case Py_LE:\r
+ return set_issubset(v, w);\r
+ case Py_GE:\r
+ return set_issuperset(v, w);\r
+ case Py_LT:\r
+ if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w))\r
+ Py_RETURN_FALSE;\r
+ return set_issubset(v, w);\r
+ case Py_GT:\r
+ if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w))\r
+ Py_RETURN_FALSE;\r
+ return set_issuperset(v, w);\r
+ }\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+}\r
+\r
+static int\r
+set_nocmp(PyObject *self, PyObject *other)\r
+{\r
+ PyErr_SetString(PyExc_TypeError, "cannot compare sets using cmp()");\r
+ return -1;\r
+}\r
+\r
+static PyObject *\r
+set_add(PySetObject *so, PyObject *key)\r
+{\r
+ if (set_add_key(so, key) == -1)\r
+ return NULL;\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(add_doc,\r
+"Add an element to a set.\n\\r
+\n\\r
+This has no effect if the element is already present.");\r
+\r
+static int\r
+set_contains(PySetObject *so, PyObject *key)\r
+{\r
+ PyObject *tmpkey;\r
+ int rv;\r
+\r
+ rv = set_contains_key(so, key);\r
+ if (rv == -1) {\r
+ if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))\r
+ return -1;\r
+ PyErr_Clear();\r
+ tmpkey = make_new_set(&PyFrozenSet_Type, key);\r
+ if (tmpkey == NULL)\r
+ return -1;\r
+ rv = set_contains_key(so, tmpkey);\r
+ Py_DECREF(tmpkey);\r
+ }\r
+ return rv;\r
+}\r
+\r
+static PyObject *\r
+set_direct_contains(PySetObject *so, PyObject *key)\r
+{\r
+ long result;\r
+\r
+ result = set_contains(so, key);\r
+ if (result == -1)\r
+ return NULL;\r
+ return PyBool_FromLong(result);\r
+}\r
+\r
+PyDoc_STRVAR(contains_doc, "x.__contains__(y) <==> y in x.");\r
+\r
+static PyObject *\r
+set_remove(PySetObject *so, PyObject *key)\r
+{\r
+ PyObject *tmpkey;\r
+ int rv;\r
+\r
+ rv = set_discard_key(so, key);\r
+ if (rv == -1) {\r
+ if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ tmpkey = make_new_set(&PyFrozenSet_Type, key);\r
+ if (tmpkey == NULL)\r
+ return NULL;\r
+ rv = set_discard_key(so, tmpkey);\r
+ Py_DECREF(tmpkey);\r
+ if (rv == -1)\r
+ return NULL;\r
+ }\r
+\r
+ if (rv == DISCARD_NOTFOUND) {\r
+ set_key_error(key);\r
+ return NULL;\r
+ }\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(remove_doc,\r
+"Remove an element from a set; it must be a member.\n\\r
+\n\\r
+If the element is not a member, raise a KeyError.");\r
+\r
+static PyObject *\r
+set_discard(PySetObject *so, PyObject *key)\r
+{\r
+ PyObject *tmpkey;\r
+ int rv;\r
+\r
+ rv = set_discard_key(so, key);\r
+ if (rv == -1) {\r
+ if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ tmpkey = make_new_set(&PyFrozenSet_Type, key);\r
+ if (tmpkey == NULL)\r
+ return NULL;\r
+ rv = set_discard_key(so, tmpkey);\r
+ Py_DECREF(tmpkey);\r
+ if (rv == -1)\r
+ return NULL;\r
+ }\r
+ Py_RETURN_NONE;\r
+}\r
+\r
+PyDoc_STRVAR(discard_doc,\r
+"Remove an element from a set if it is a member.\n\\r
+\n\\r
+If the element is not a member, do nothing.");\r
+\r
+static PyObject *\r
+set_reduce(PySetObject *so)\r
+{\r
+ PyObject *keys=NULL, *args=NULL, *result=NULL, *dict=NULL;\r
+\r
+ keys = PySequence_List((PyObject *)so);\r
+ if (keys == NULL)\r
+ goto done;\r
+ args = PyTuple_Pack(1, keys);\r
+ if (args == NULL)\r
+ goto done;\r
+ dict = PyObject_GetAttrString((PyObject *)so, "__dict__");\r
+ if (dict == NULL) {\r
+ PyErr_Clear();\r
+ dict = Py_None;\r
+ Py_INCREF(dict);\r
+ }\r
+ result = PyTuple_Pack(3, Py_TYPE(so), args, dict);\r
+done:\r
+ Py_XDECREF(args);\r
+ Py_XDECREF(keys);\r
+ Py_XDECREF(dict);\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");\r
+\r
+static PyObject *\r
+set_sizeof(PySetObject *so)\r
+{\r
+ Py_ssize_t res;\r
+\r
+ res = sizeof(PySetObject);\r
+ if (so->table != so->smalltable)\r
+ res = res + (so->mask + 1) * sizeof(setentry);\r
+ return PyInt_FromSsize_t(res);\r
+}\r
+\r
+PyDoc_STRVAR(sizeof_doc, "S.__sizeof__() -> size of S in memory, in bytes");\r
+static int\r
+set_init(PySetObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *iterable = NULL;\r
+\r
+ if (!PyAnySet_Check(self))\r
+ return -1;\r
+ if (PySet_Check(self) && !_PyArg_NoKeywords("set()", kwds))\r
+ return -1;\r
+ if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))\r
+ return -1;\r
+ set_clear_internal(self);\r
+ self->hash = -1;\r
+ if (iterable == NULL)\r
+ return 0;\r
+ return set_update_internal(self, iterable);\r
+}\r
+\r
+static PySequenceMethods set_as_sequence = {\r
+ set_len, /* sq_length */\r
+ 0, /* sq_concat */\r
+ 0, /* sq_repeat */\r
+ 0, /* sq_item */\r
+ 0, /* sq_slice */\r
+ 0, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ (objobjproc)set_contains, /* sq_contains */\r
+};\r
+\r
+/* set object ********************************************************/\r
+\r
+#ifdef Py_DEBUG\r
+static PyObject *test_c_api(PySetObject *so);\r
+\r
+PyDoc_STRVAR(test_c_api_doc, "Exercises C API. Returns True.\n\\r
+All is well if assertions don't fail.");\r
+#endif\r
+\r
+static PyMethodDef set_methods[] = {\r
+ {"add", (PyCFunction)set_add, METH_O,\r
+ add_doc},\r
+ {"clear", (PyCFunction)set_clear, METH_NOARGS,\r
+ clear_doc},\r
+ {"__contains__",(PyCFunction)set_direct_contains, METH_O | METH_COEXIST,\r
+ contains_doc},\r
+ {"copy", (PyCFunction)set_copy, METH_NOARGS,\r
+ copy_doc},\r
+ {"discard", (PyCFunction)set_discard, METH_O,\r
+ discard_doc},\r
+ {"difference", (PyCFunction)set_difference_multi, METH_VARARGS,\r
+ difference_doc},\r
+ {"difference_update", (PyCFunction)set_difference_update, METH_VARARGS,\r
+ difference_update_doc},\r
+ {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS,\r
+ intersection_doc},\r
+ {"intersection_update",(PyCFunction)set_intersection_update_multi, METH_VARARGS,\r
+ intersection_update_doc},\r
+ {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O,\r
+ isdisjoint_doc},\r
+ {"issubset", (PyCFunction)set_issubset, METH_O,\r
+ issubset_doc},\r
+ {"issuperset", (PyCFunction)set_issuperset, METH_O,\r
+ issuperset_doc},\r
+ {"pop", (PyCFunction)set_pop, METH_NOARGS,\r
+ pop_doc},\r
+ {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS,\r
+ reduce_doc},\r
+ {"remove", (PyCFunction)set_remove, METH_O,\r
+ remove_doc},\r
+ {"__sizeof__", (PyCFunction)set_sizeof, METH_NOARGS,\r
+ sizeof_doc},\r
+ {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O,\r
+ symmetric_difference_doc},\r
+ {"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update, METH_O,\r
+ symmetric_difference_update_doc},\r
+#ifdef Py_DEBUG\r
+ {"test_c_api", (PyCFunction)test_c_api, METH_NOARGS,\r
+ test_c_api_doc},\r
+#endif\r
+ {"union", (PyCFunction)set_union, METH_VARARGS,\r
+ union_doc},\r
+ {"update", (PyCFunction)set_update, METH_VARARGS,\r
+ update_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyNumberMethods set_as_number = {\r
+ 0, /*nb_add*/\r
+ (binaryfunc)set_sub, /*nb_subtract*/\r
+ 0, /*nb_multiply*/\r
+ 0, /*nb_divide*/\r
+ 0, /*nb_remainder*/\r
+ 0, /*nb_divmod*/\r
+ 0, /*nb_power*/\r
+ 0, /*nb_negative*/\r
+ 0, /*nb_positive*/\r
+ 0, /*nb_absolute*/\r
+ 0, /*nb_nonzero*/\r
+ 0, /*nb_invert*/\r
+ 0, /*nb_lshift*/\r
+ 0, /*nb_rshift*/\r
+ (binaryfunc)set_and, /*nb_and*/\r
+ (binaryfunc)set_xor, /*nb_xor*/\r
+ (binaryfunc)set_or, /*nb_or*/\r
+ 0, /*nb_coerce*/\r
+ 0, /*nb_int*/\r
+ 0, /*nb_long*/\r
+ 0, /*nb_float*/\r
+ 0, /*nb_oct*/\r
+ 0, /*nb_hex*/\r
+ 0, /*nb_inplace_add*/\r
+ (binaryfunc)set_isub, /*nb_inplace_subtract*/\r
+ 0, /*nb_inplace_multiply*/\r
+ 0, /*nb_inplace_divide*/\r
+ 0, /*nb_inplace_remainder*/\r
+ 0, /*nb_inplace_power*/\r
+ 0, /*nb_inplace_lshift*/\r
+ 0, /*nb_inplace_rshift*/\r
+ (binaryfunc)set_iand, /*nb_inplace_and*/\r
+ (binaryfunc)set_ixor, /*nb_inplace_xor*/\r
+ (binaryfunc)set_ior, /*nb_inplace_or*/\r
+};\r
+\r
+PyDoc_STRVAR(set_doc,\r
+"set() -> new empty set object\n\\r
+set(iterable) -> new set object\n\\r
+\n\\r
+Build an unordered collection of unique elements.");\r
+\r
+PyTypeObject PySet_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "set", /* tp_name */\r
+ sizeof(PySetObject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)set_dealloc, /* tp_dealloc */\r
+ (printfunc)set_tp_print, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ set_nocmp, /* tp_compare */\r
+ (reprfunc)set_repr, /* tp_repr */\r
+ &set_as_number, /* tp_as_number */\r
+ &set_as_sequence, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)PyObject_HashNotImplemented, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES |\r
+ Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ set_doc, /* tp_doc */\r
+ (traverseproc)set_traverse, /* tp_traverse */\r
+ (inquiry)set_clear_internal, /* tp_clear */\r
+ (richcmpfunc)set_richcompare, /* tp_richcompare */\r
+ offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */\r
+ (getiterfunc)set_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ set_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ (initproc)set_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ set_new, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
+\r
+/* frozenset object ********************************************************/\r
+\r
+\r
+static PyMethodDef frozenset_methods[] = {\r
+ {"__contains__",(PyCFunction)set_direct_contains, METH_O | METH_COEXIST,\r
+ contains_doc},\r
+ {"copy", (PyCFunction)frozenset_copy, METH_NOARGS,\r
+ copy_doc},\r
+ {"difference", (PyCFunction)set_difference_multi, METH_VARARGS,\r
+ difference_doc},\r
+ {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS,\r
+ intersection_doc},\r
+ {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O,\r
+ isdisjoint_doc},\r
+ {"issubset", (PyCFunction)set_issubset, METH_O,\r
+ issubset_doc},\r
+ {"issuperset", (PyCFunction)set_issuperset, METH_O,\r
+ issuperset_doc},\r
+ {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS,\r
+ reduce_doc},\r
+ {"__sizeof__", (PyCFunction)set_sizeof, METH_NOARGS,\r
+ sizeof_doc},\r
+ {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O,\r
+ symmetric_difference_doc},\r
+ {"union", (PyCFunction)set_union, METH_VARARGS,\r
+ union_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyNumberMethods frozenset_as_number = {\r
+ 0, /*nb_add*/\r
+ (binaryfunc)set_sub, /*nb_subtract*/\r
+ 0, /*nb_multiply*/\r
+ 0, /*nb_divide*/\r
+ 0, /*nb_remainder*/\r
+ 0, /*nb_divmod*/\r
+ 0, /*nb_power*/\r
+ 0, /*nb_negative*/\r
+ 0, /*nb_positive*/\r
+ 0, /*nb_absolute*/\r
+ 0, /*nb_nonzero*/\r
+ 0, /*nb_invert*/\r
+ 0, /*nb_lshift*/\r
+ 0, /*nb_rshift*/\r
+ (binaryfunc)set_and, /*nb_and*/\r
+ (binaryfunc)set_xor, /*nb_xor*/\r
+ (binaryfunc)set_or, /*nb_or*/\r
+};\r
+\r
+PyDoc_STRVAR(frozenset_doc,\r
+"frozenset() -> empty frozenset object\n\\r
+frozenset(iterable) -> frozenset object\n\\r
+\n\\r
+Build an immutable unordered collection of unique elements.");\r
+\r
+PyTypeObject PyFrozenSet_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "frozenset", /* tp_name */\r
+ sizeof(PySetObject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)set_dealloc, /* tp_dealloc */\r
+ (printfunc)set_tp_print, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ set_nocmp, /* tp_compare */\r
+ (reprfunc)set_repr, /* tp_repr */\r
+ &frozenset_as_number, /* tp_as_number */\r
+ &set_as_sequence, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ frozenset_hash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES |\r
+ Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ frozenset_doc, /* tp_doc */\r
+ (traverseproc)set_traverse, /* tp_traverse */\r
+ (inquiry)set_clear_internal, /* tp_clear */\r
+ (richcmpfunc)set_richcompare, /* tp_richcompare */\r
+ offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */\r
+ (getiterfunc)set_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ frozenset_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ frozenset_new, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
+\r
+\r
+/***** C API functions *************************************************/\r
+\r
+PyObject *\r
+PySet_New(PyObject *iterable)\r
+{\r
+ return make_new_set(&PySet_Type, iterable);\r
+}\r
+\r
+PyObject *\r
+PyFrozenSet_New(PyObject *iterable)\r
+{\r
+ return make_new_set(&PyFrozenSet_Type, iterable);\r
+}\r
+\r
+Py_ssize_t\r
+PySet_Size(PyObject *anyset)\r
+{\r
+ if (!PyAnySet_Check(anyset)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return PySet_GET_SIZE(anyset);\r
+}\r
+\r
+int\r
+PySet_Clear(PyObject *set)\r
+{\r
+ if (!PySet_Check(set)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return set_clear_internal((PySetObject *)set);\r
+}\r
+\r
+int\r
+PySet_Contains(PyObject *anyset, PyObject *key)\r
+{\r
+ if (!PyAnySet_Check(anyset)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return set_contains_key((PySetObject *)anyset, key);\r
+}\r
+\r
+int\r
+PySet_Discard(PyObject *set, PyObject *key)\r
+{\r
+ if (!PySet_Check(set)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return set_discard_key((PySetObject *)set, key);\r
+}\r
+\r
+int\r
+PySet_Add(PyObject *anyset, PyObject *key)\r
+{\r
+ if (!PySet_Check(anyset) &&\r
+ (!PyFrozenSet_Check(anyset) || Py_REFCNT(anyset) != 1)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return set_add_key((PySetObject *)anyset, key);\r
+}\r
+\r
+int\r
+_PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **key)\r
+{\r
+ setentry *entry_ptr;\r
+\r
+ if (!PyAnySet_Check(set)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ if (set_next((PySetObject *)set, pos, &entry_ptr) == 0)\r
+ return 0;\r
+ *key = entry_ptr->key;\r
+ return 1;\r
+}\r
+\r
+int\r
+_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash)\r
+{\r
+ setentry *entry;\r
+\r
+ if (!PyAnySet_Check(set)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ if (set_next((PySetObject *)set, pos, &entry) == 0)\r
+ return 0;\r
+ *key = entry->key;\r
+ *hash = entry->hash;\r
+ return 1;\r
+}\r
+\r
+PyObject *\r
+PySet_Pop(PyObject *set)\r
+{\r
+ if (!PySet_Check(set)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return set_pop((PySetObject *)set);\r
+}\r
+\r
+int\r
+_PySet_Update(PyObject *set, PyObject *iterable)\r
+{\r
+ if (!PySet_Check(set)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ return set_update_internal((PySetObject *)set, iterable);\r
+}\r
+\r
+#ifdef Py_DEBUG\r
+\r
+/* Test code to be called with any three element set.\r
+ Returns True and original set is restored. */\r
+\r
+#define assertRaises(call_return_value, exception) \\r
+ do { \\r
+ assert(call_return_value); \\r
+ assert(PyErr_ExceptionMatches(exception)); \\r
+ PyErr_Clear(); \\r
+ } while(0)\r
+\r
+static PyObject *\r
+test_c_api(PySetObject *so)\r
+{\r
+ Py_ssize_t count;\r
+ char *s;\r
+ Py_ssize_t i;\r
+ PyObject *elem=NULL, *dup=NULL, *t, *f, *dup2, *x;\r
+ PyObject *ob = (PyObject *)so;\r
+ PyObject *str;\r
+\r
+ /* Verify preconditions */\r
+ assert(PyAnySet_Check(ob));\r
+ assert(PyAnySet_CheckExact(ob));\r
+ assert(!PyFrozenSet_CheckExact(ob));\r
+\r
+ /* so.clear(); so |= set("abc"); */\r
+ str = PyString_FromString("abc");\r
+ if (str == NULL)\r
+ return NULL;\r
+ set_clear_internal(so);\r
+ if (set_update_internal(so, str) == -1) {\r
+ Py_DECREF(str);\r
+ return NULL;\r
+ }\r
+ Py_DECREF(str);\r
+\r
+ /* Exercise type/size checks */\r
+ assert(PySet_Size(ob) == 3);\r
+ assert(PySet_GET_SIZE(ob) == 3);\r
+\r
+ /* Raise TypeError for non-iterable constructor arguments */\r
+ assertRaises(PySet_New(Py_None) == NULL, PyExc_TypeError);\r
+ assertRaises(PyFrozenSet_New(Py_None) == NULL, PyExc_TypeError);\r
+\r
+ /* Raise TypeError for unhashable key */\r
+ dup = PySet_New(ob);\r
+ assertRaises(PySet_Discard(ob, dup) == -1, PyExc_TypeError);\r
+ assertRaises(PySet_Contains(ob, dup) == -1, PyExc_TypeError);\r
+ assertRaises(PySet_Add(ob, dup) == -1, PyExc_TypeError);\r
+\r
+ /* Exercise successful pop, contains, add, and discard */\r
+ elem = PySet_Pop(ob);\r
+ assert(PySet_Contains(ob, elem) == 0);\r
+ assert(PySet_GET_SIZE(ob) == 2);\r
+ assert(PySet_Add(ob, elem) == 0);\r
+ assert(PySet_Contains(ob, elem) == 1);\r
+ assert(PySet_GET_SIZE(ob) == 3);\r
+ assert(PySet_Discard(ob, elem) == 1);\r
+ assert(PySet_GET_SIZE(ob) == 2);\r
+ assert(PySet_Discard(ob, elem) == 0);\r
+ assert(PySet_GET_SIZE(ob) == 2);\r
+\r
+ /* Exercise clear */\r
+ dup2 = PySet_New(dup);\r
+ assert(PySet_Clear(dup2) == 0);\r
+ assert(PySet_Size(dup2) == 0);\r
+ Py_DECREF(dup2);\r
+\r
+ /* Raise SystemError on clear or update of frozen set */\r
+ f = PyFrozenSet_New(dup);\r
+ assertRaises(PySet_Clear(f) == -1, PyExc_SystemError);\r
+ assertRaises(_PySet_Update(f, dup) == -1, PyExc_SystemError);\r
+ assert(PySet_Add(f, elem) == 0);\r
+ Py_INCREF(f);\r
+ assertRaises(PySet_Add(f, elem) == -1, PyExc_SystemError);\r
+ Py_DECREF(f);\r
+ Py_DECREF(f);\r
+\r
+ /* Exercise direct iteration */\r
+ i = 0, count = 0;\r
+ while (_PySet_Next((PyObject *)dup, &i, &x)) {\r
+ s = PyString_AsString(x);\r
+ assert(s && (s[0] == 'a' || s[0] == 'b' || s[0] == 'c'));\r
+ count++;\r
+ }\r
+ assert(count == 3);\r
+\r
+ /* Exercise updates */\r
+ dup2 = PySet_New(NULL);\r
+ assert(_PySet_Update(dup2, dup) == 0);\r
+ assert(PySet_Size(dup2) == 3);\r
+ assert(_PySet_Update(dup2, dup) == 0);\r
+ assert(PySet_Size(dup2) == 3);\r
+ Py_DECREF(dup2);\r
+\r
+ /* Raise SystemError when self argument is not a set or frozenset. */\r
+ t = PyTuple_New(0);\r
+ assertRaises(PySet_Size(t) == -1, PyExc_SystemError);\r
+ assertRaises(PySet_Contains(t, elem) == -1, PyExc_SystemError);\r
+ Py_DECREF(t);\r
+\r
+ /* Raise SystemError when self argument is not a set. */\r
+ f = PyFrozenSet_New(dup);\r
+ assert(PySet_Size(f) == 3);\r
+ assert(PyFrozenSet_CheckExact(f));\r
+ assertRaises(PySet_Discard(f, elem) == -1, PyExc_SystemError);\r
+ assertRaises(PySet_Pop(f) == NULL, PyExc_SystemError);\r
+ Py_DECREF(f);\r
+\r
+ /* Raise KeyError when popping from an empty set */\r
+ assert(PyNumber_InPlaceSubtract(ob, ob) == ob);\r
+ Py_DECREF(ob);\r
+ assert(PySet_GET_SIZE(ob) == 0);\r
+ assertRaises(PySet_Pop(ob) == NULL, PyExc_KeyError);\r
+\r
+ /* Restore the set from the copy using the PyNumber API */\r
+ assert(PyNumber_InPlaceOr(ob, dup) == ob);\r
+ Py_DECREF(ob);\r
+\r
+ /* Verify constructors accept NULL arguments */\r
+ f = PySet_New(NULL);\r
+ assert(f != NULL);\r
+ assert(PySet_GET_SIZE(f) == 0);\r
+ Py_DECREF(f);\r
+ f = PyFrozenSet_New(NULL);\r
+ assert(f != NULL);\r
+ assert(PyFrozenSet_CheckExact(f));\r
+ assert(PySet_GET_SIZE(f) == 0);\r
+ Py_DECREF(f);\r
+\r
+ Py_DECREF(elem);\r
+ Py_DECREF(dup);\r
+ Py_RETURN_TRUE;\r
+}\r
+\r
+#undef assertRaises\r
+\r
+#endif\r
--- /dev/null
+/*\r
+Written by Jim Hugunin and Chris Chase.\r
+\r
+This includes both the singular ellipsis object and slice objects.\r
+\r
+Guido, feel free to do whatever you want in the way of copyrights\r
+for this file.\r
+*/\r
+\r
+/*\r
+Py_Ellipsis encodes the '...' rubber index token. It is similar to\r
+the Py_NoneStruct in that there is no way to create other objects of\r
+this type and there is exactly one in existence.\r
+*/\r
+\r
+#include "Python.h"\r
+#include "structmember.h"\r
+\r
+static PyObject *\r
+ellipsis_repr(PyObject *op)\r
+{\r
+ return PyString_FromString("Ellipsis");\r
+}\r
+\r
+PyTypeObject PyEllipsis_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "ellipsis", /* tp_name */\r
+ 0, /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ 0, /*never called*/ /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ ellipsis_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT, /* tp_flags */\r
+};\r
+\r
+PyObject _Py_EllipsisObject = {\r
+ _PyObject_EXTRA_INIT\r
+ 1, &PyEllipsis_Type\r
+};\r
+\r
+\r
+/* Slice object implementation\r
+\r
+ start, stop, and step are python objects with None indicating no\r
+ index is present.\r
+*/\r
+\r
+PyObject *\r
+PySlice_New(PyObject *start, PyObject *stop, PyObject *step)\r
+{\r
+ PySliceObject *obj = PyObject_New(PySliceObject, &PySlice_Type);\r
+\r
+ if (obj == NULL)\r
+ return NULL;\r
+\r
+ if (step == NULL) step = Py_None;\r
+ Py_INCREF(step);\r
+ if (start == NULL) start = Py_None;\r
+ Py_INCREF(start);\r
+ if (stop == NULL) stop = Py_None;\r
+ Py_INCREF(stop);\r
+\r
+ obj->step = step;\r
+ obj->start = start;\r
+ obj->stop = stop;\r
+\r
+ return (PyObject *) obj;\r
+}\r
+\r
+PyObject *\r
+_PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)\r
+{\r
+ PyObject *start, *end, *slice;\r
+ start = PyInt_FromSsize_t(istart);\r
+ if (!start)\r
+ return NULL;\r
+ end = PyInt_FromSsize_t(istop);\r
+ if (!end) {\r
+ Py_DECREF(start);\r
+ return NULL;\r
+ }\r
+\r
+ slice = PySlice_New(start, end, NULL);\r
+ Py_DECREF(start);\r
+ Py_DECREF(end);\r
+ return slice;\r
+}\r
+\r
+int\r
+PySlice_GetIndices(PySliceObject *r, Py_ssize_t length,\r
+ Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)\r
+{\r
+ /* XXX support long ints */\r
+ if (r->step == Py_None) {\r
+ *step = 1;\r
+ } else {\r
+ if (!PyInt_Check(r->step) && !PyLong_Check(r->step)) return -1;\r
+ *step = PyInt_AsSsize_t(r->step);\r
+ }\r
+ if (r->start == Py_None) {\r
+ *start = *step < 0 ? length-1 : 0;\r
+ } else {\r
+ if (!PyInt_Check(r->start) && !PyLong_Check(r->step)) return -1;\r
+ *start = PyInt_AsSsize_t(r->start);\r
+ if (*start < 0) *start += length;\r
+ }\r
+ if (r->stop == Py_None) {\r
+ *stop = *step < 0 ? -1 : length;\r
+ } else {\r
+ if (!PyInt_Check(r->stop) && !PyLong_Check(r->step)) return -1;\r
+ *stop = PyInt_AsSsize_t(r->stop);\r
+ if (*stop < 0) *stop += length;\r
+ }\r
+ if (*stop > length) return -1;\r
+ if (*start >= length) return -1;\r
+ if (*step == 0) return -1;\r
+ return 0;\r
+}\r
+\r
+int\r
+PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,\r
+ Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength)\r
+{\r
+ /* this is harder to get right than you might think */\r
+\r
+ Py_ssize_t defstart, defstop;\r
+\r
+ if (r->step == Py_None) {\r
+ *step = 1;\r
+ }\r
+ else {\r
+ if (!_PyEval_SliceIndex(r->step, step)) return -1;\r
+ if (*step == 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "slice step cannot be zero");\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ defstart = *step < 0 ? length-1 : 0;\r
+ defstop = *step < 0 ? -1 : length;\r
+\r
+ if (r->start == Py_None) {\r
+ *start = defstart;\r
+ }\r
+ else {\r
+ if (!_PyEval_SliceIndex(r->start, start)) return -1;\r
+ if (*start < 0) *start += length;\r
+ if (*start < 0) *start = (*step < 0) ? -1 : 0;\r
+ if (*start >= length)\r
+ *start = (*step < 0) ? length - 1 : length;\r
+ }\r
+\r
+ if (r->stop == Py_None) {\r
+ *stop = defstop;\r
+ }\r
+ else {\r
+ if (!_PyEval_SliceIndex(r->stop, stop)) return -1;\r
+ if (*stop < 0) *stop += length;\r
+ if (*stop < 0) *stop = (*step < 0) ? -1 : 0;\r
+ if (*stop >= length)\r
+ *stop = (*step < 0) ? length - 1 : length;\r
+ }\r
+\r
+ if ((*step < 0 && *stop >= *start)\r
+ || (*step > 0 && *start >= *stop)) {\r
+ *slicelength = 0;\r
+ }\r
+ else if (*step < 0) {\r
+ *slicelength = (*stop-*start+1)/(*step)+1;\r
+ }\r
+ else {\r
+ *slicelength = (*stop-*start-1)/(*step)+1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)\r
+{\r
+ PyObject *start, *stop, *step;\r
+\r
+ start = stop = step = NULL;\r
+\r
+ if (!_PyArg_NoKeywords("slice()", kw))\r
+ return NULL;\r
+\r
+ if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))\r
+ return NULL;\r
+\r
+ /* This swapping of stop and start is to maintain similarity with\r
+ range(). */\r
+ if (stop == NULL) {\r
+ stop = start;\r
+ start = NULL;\r
+ }\r
+ return PySlice_New(start, stop, step);\r
+}\r
+\r
+PyDoc_STRVAR(slice_doc,\r
+"slice(stop)\n\\r
+slice(start, stop[, step])\n\\r
+\n\\r
+Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");\r
+\r
+static void\r
+slice_dealloc(PySliceObject *r)\r
+{\r
+ Py_DECREF(r->step);\r
+ Py_DECREF(r->start);\r
+ Py_DECREF(r->stop);\r
+ PyObject_Del(r);\r
+}\r
+\r
+static PyObject *\r
+slice_repr(PySliceObject *r)\r
+{\r
+ PyObject *s, *comma;\r
+\r
+ s = PyString_FromString("slice(");\r
+ comma = PyString_FromString(", ");\r
+ PyString_ConcatAndDel(&s, PyObject_Repr(r->start));\r
+ PyString_Concat(&s, comma);\r
+ PyString_ConcatAndDel(&s, PyObject_Repr(r->stop));\r
+ PyString_Concat(&s, comma);\r
+ PyString_ConcatAndDel(&s, PyObject_Repr(r->step));\r
+ PyString_ConcatAndDel(&s, PyString_FromString(")"));\r
+ Py_DECREF(comma);\r
+ return s;\r
+}\r
+\r
+static PyMemberDef slice_members[] = {\r
+ {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},\r
+ {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},\r
+ {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},\r
+ {0}\r
+};\r
+\r
+static PyObject*\r
+slice_indices(PySliceObject* self, PyObject* len)\r
+{\r
+ Py_ssize_t ilen, start, stop, step, slicelength;\r
+\r
+ ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);\r
+\r
+ if (ilen == -1 && PyErr_Occurred()) {\r
+ return NULL;\r
+ }\r
+\r
+ if (PySlice_GetIndicesEx(self, ilen, &start, &stop,\r
+ &step, &slicelength) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ return Py_BuildValue("(nnn)", start, stop, step);\r
+}\r
+\r
+PyDoc_STRVAR(slice_indices_doc,\r
+"S.indices(len) -> (start, stop, stride)\n\\r
+\n\\r
+Assuming a sequence of length len, calculate the start and stop\n\\r
+indices, and the stride length of the extended slice described by\n\\r
+S. Out of bounds indices are clipped in a manner consistent with the\n\\r
+handling of normal slices.");\r
+\r
+static PyObject *\r
+slice_reduce(PySliceObject* self)\r
+{\r
+ return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);\r
+}\r
+\r
+PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");\r
+\r
+static PyMethodDef slice_methods[] = {\r
+ {"indices", (PyCFunction)slice_indices,\r
+ METH_O, slice_indices_doc},\r
+ {"__reduce__", (PyCFunction)slice_reduce,\r
+ METH_NOARGS, reduce_doc},\r
+ {NULL, NULL}\r
+};\r
+\r
+static int\r
+slice_compare(PySliceObject *v, PySliceObject *w)\r
+{\r
+ int result = 0;\r
+\r
+ if (v == w)\r
+ return 0;\r
+\r
+ if (PyObject_Cmp(v->start, w->start, &result) < 0)\r
+ return -2;\r
+ if (result != 0)\r
+ return result;\r
+ if (PyObject_Cmp(v->stop, w->stop, &result) < 0)\r
+ return -2;\r
+ if (result != 0)\r
+ return result;\r
+ if (PyObject_Cmp(v->step, w->step, &result) < 0)\r
+ return -2;\r
+ return result;\r
+}\r
+\r
+static long\r
+slice_hash(PySliceObject *v)\r
+{\r
+ PyErr_SetString(PyExc_TypeError, "unhashable type");\r
+ return -1L;\r
+}\r
+\r
+PyTypeObject PySlice_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "slice", /* Name of this type */\r
+ sizeof(PySliceObject), /* Basic object size */\r
+ 0, /* Item size for varobject */\r
+ (destructor)slice_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ (cmpfunc)slice_compare, /* tp_compare */\r
+ (reprfunc)slice_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)slice_hash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT, /* tp_flags */\r
+ slice_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ slice_methods, /* tp_methods */\r
+ slice_members, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ slice_new, /* tp_new */\r
+};\r
--- /dev/null
+bits shared by the stringobject and unicodeobject implementations (and\r
+possibly other modules, in a not too distant future).\r
+\r
+the stuff in here is included into relevant places; see the individual\r
+source files for details.\r
+\r
+--------------------------------------------------------------------\r
+the following defines used by the different modules:\r
+\r
+STRINGLIB_CHAR\r
+\r
+ the type used to hold a character (char or Py_UNICODE)\r
+\r
+STRINGLIB_EMPTY\r
+\r
+ a PyObject representing the empty string, only to be used if\r
+ STRINGLIB_MUTABLE is 0\r
+\r
+Py_ssize_t STRINGLIB_LEN(PyObject*)\r
+\r
+ returns the length of the given string object (which must be of the\r
+ right type)\r
+\r
+PyObject* STRINGLIB_NEW(STRINGLIB_CHAR*, Py_ssize_t)\r
+\r
+ creates a new string object\r
+\r
+STRINGLIB_CHAR* STRINGLIB_STR(PyObject*)\r
+\r
+ returns the pointer to the character data for the given string\r
+ object (which must be of the right type)\r
+\r
+int STRINGLIB_CHECK_EXACT(PyObject *)\r
+\r
+ returns true if the object is an instance of our type, not a subclass\r
+\r
+STRINGLIB_MUTABLE\r
+\r
+ must be 0 or 1 to tell the cpp macros in stringlib code if the object\r
+ being operated on is mutable or not\r
--- /dev/null
+/* stringlib: count implementation */\r
+\r
+#ifndef STRINGLIB_COUNT_H\r
+#define STRINGLIB_COUNT_H\r
+\r
+#ifndef STRINGLIB_FASTSEARCH_H\r
+#error must include "stringlib/fastsearch.h" before including this module\r
+#endif\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+stringlib_count(const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ Py_ssize_t count;\r
+\r
+ if (str_len < 0)\r
+ return 0; /* start > len(str) */\r
+ if (sub_len == 0)\r
+ return (str_len < maxcount) ? str_len + 1 : maxcount;\r
+\r
+ count = fastsearch(str, str_len, sub, sub_len, maxcount, FAST_COUNT);\r
+\r
+ if (count < 0)\r
+ return 0; /* no match */\r
+\r
+ return count;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/* NOTE: this API is -ONLY- for use with single byte character strings. */\r
+/* Do not use it with Unicode. */\r
+\r
+#include "bytes_methods.h"\r
+\r
+static PyObject*\r
+stringlib_isspace(PyObject *self)\r
+{\r
+ return _Py_bytes_isspace(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+}\r
+\r
+static PyObject*\r
+stringlib_isalpha(PyObject *self)\r
+{\r
+ return _Py_bytes_isalpha(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+}\r
+\r
+static PyObject*\r
+stringlib_isalnum(PyObject *self)\r
+{\r
+ return _Py_bytes_isalnum(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+}\r
+\r
+static PyObject*\r
+stringlib_isdigit(PyObject *self)\r
+{\r
+ return _Py_bytes_isdigit(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+}\r
+\r
+static PyObject*\r
+stringlib_islower(PyObject *self)\r
+{\r
+ return _Py_bytes_islower(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+}\r
+\r
+static PyObject*\r
+stringlib_isupper(PyObject *self)\r
+{\r
+ return _Py_bytes_isupper(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+}\r
+\r
+static PyObject*\r
+stringlib_istitle(PyObject *self)\r
+{\r
+ return _Py_bytes_istitle(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+}\r
+\r
+\r
+/* functions that return a new object partially translated by ctype funcs: */\r
+\r
+static PyObject*\r
+stringlib_lower(PyObject *self)\r
+{\r
+ PyObject* newobj;\r
+ newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));\r
+ if (!newobj)\r
+ return NULL;\r
+ _Py_bytes_lower(STRINGLIB_STR(newobj), STRINGLIB_STR(self),\r
+ STRINGLIB_LEN(self));\r
+ return newobj;\r
+}\r
+\r
+static PyObject*\r
+stringlib_upper(PyObject *self)\r
+{\r
+ PyObject* newobj;\r
+ newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));\r
+ if (!newobj)\r
+ return NULL;\r
+ _Py_bytes_upper(STRINGLIB_STR(newobj), STRINGLIB_STR(self),\r
+ STRINGLIB_LEN(self));\r
+ return newobj;\r
+}\r
+\r
+static PyObject*\r
+stringlib_title(PyObject *self)\r
+{\r
+ PyObject* newobj;\r
+ newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));\r
+ if (!newobj)\r
+ return NULL;\r
+ _Py_bytes_title(STRINGLIB_STR(newobj), STRINGLIB_STR(self),\r
+ STRINGLIB_LEN(self));\r
+ return newobj;\r
+}\r
+\r
+static PyObject*\r
+stringlib_capitalize(PyObject *self)\r
+{\r
+ PyObject* newobj;\r
+ newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));\r
+ if (!newobj)\r
+ return NULL;\r
+ _Py_bytes_capitalize(STRINGLIB_STR(newobj), STRINGLIB_STR(self),\r
+ STRINGLIB_LEN(self));\r
+ return newobj;\r
+}\r
+\r
+static PyObject*\r
+stringlib_swapcase(PyObject *self)\r
+{\r
+ PyObject* newobj;\r
+ newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));\r
+ if (!newobj)\r
+ return NULL;\r
+ _Py_bytes_swapcase(STRINGLIB_STR(newobj), STRINGLIB_STR(self),\r
+ STRINGLIB_LEN(self));\r
+ return newobj;\r
+}\r
--- /dev/null
+/* stringlib: fastsearch implementation */\r
+\r
+#ifndef STRINGLIB_FASTSEARCH_H\r
+#define STRINGLIB_FASTSEARCH_H\r
+\r
+/* fast search/count implementation, based on a mix between boyer-\r
+ moore and horspool, with a few more bells and whistles on the top.\r
+ for some more background, see: http://effbot.org/zone/stringlib.htm */\r
+\r
+/* note: fastsearch may access s[n], which isn't a problem when using\r
+ Python's ordinary string types, but may cause problems if you're\r
+ using this code in other contexts. also, the count mode returns -1\r
+ if there cannot possible be a match in the target string, and 0 if\r
+ it has actually checked for matches, but didn't find any. callers\r
+ beware! */\r
+\r
+#define FAST_COUNT 0\r
+#define FAST_SEARCH 1\r
+#define FAST_RSEARCH 2\r
+\r
+#if LONG_BIT >= 128\r
+#define STRINGLIB_BLOOM_WIDTH 128\r
+#elif LONG_BIT >= 64\r
+#define STRINGLIB_BLOOM_WIDTH 64\r
+#elif LONG_BIT >= 32\r
+#define STRINGLIB_BLOOM_WIDTH 32\r
+#else\r
+#error "LONG_BIT is smaller than 32"\r
+#endif\r
+\r
+#define STRINGLIB_BLOOM_ADD(mask, ch) \\r
+ ((mask |= (1UL << ((ch) & (STRINGLIB_BLOOM_WIDTH -1)))))\r
+#define STRINGLIB_BLOOM(mask, ch) \\r
+ ((mask & (1UL << ((ch) & (STRINGLIB_BLOOM_WIDTH -1)))))\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+fastsearch(const STRINGLIB_CHAR* s, Py_ssize_t n,\r
+ const STRINGLIB_CHAR* p, Py_ssize_t m,\r
+ Py_ssize_t maxcount, int mode)\r
+{\r
+ unsigned long mask;\r
+ Py_ssize_t skip, count = 0;\r
+ Py_ssize_t i, j, mlast, w;\r
+\r
+ w = n - m;\r
+\r
+ if (w < 0 || (mode == FAST_COUNT && maxcount == 0))\r
+ return -1;\r
+\r
+ /* look for special cases */\r
+ if (m <= 1) {\r
+ if (m <= 0)\r
+ return -1;\r
+ /* use special case for 1-character strings */\r
+ if (mode == FAST_COUNT) {\r
+ for (i = 0; i < n; i++)\r
+ if (s[i] == p[0]) {\r
+ count++;\r
+ if (count == maxcount)\r
+ return maxcount;\r
+ }\r
+ return count;\r
+ } else if (mode == FAST_SEARCH) {\r
+ for (i = 0; i < n; i++)\r
+ if (s[i] == p[0])\r
+ return i;\r
+ } else { /* FAST_RSEARCH */\r
+ for (i = n - 1; i > -1; i--)\r
+ if (s[i] == p[0])\r
+ return i;\r
+ }\r
+ return -1;\r
+ }\r
+\r
+ mlast = m - 1;\r
+ skip = mlast - 1;\r
+ mask = 0;\r
+\r
+ if (mode != FAST_RSEARCH) {\r
+\r
+ /* create compressed boyer-moore delta 1 table */\r
+\r
+ /* process pattern[:-1] */\r
+ for (i = 0; i < mlast; i++) {\r
+ STRINGLIB_BLOOM_ADD(mask, p[i]);\r
+ if (p[i] == p[mlast])\r
+ skip = mlast - i - 1;\r
+ }\r
+ /* process pattern[-1] outside the loop */\r
+ STRINGLIB_BLOOM_ADD(mask, p[mlast]);\r
+\r
+ for (i = 0; i <= w; i++) {\r
+ /* note: using mlast in the skip path slows things down on x86 */\r
+ if (s[i+m-1] == p[m-1]) {\r
+ /* candidate match */\r
+ for (j = 0; j < mlast; j++)\r
+ if (s[i+j] != p[j])\r
+ break;\r
+ if (j == mlast) {\r
+ /* got a match! */\r
+ if (mode != FAST_COUNT)\r
+ return i;\r
+ count++;\r
+ if (count == maxcount)\r
+ return maxcount;\r
+ i = i + mlast;\r
+ continue;\r
+ }\r
+ /* miss: check if next character is part of pattern */\r
+ if (!STRINGLIB_BLOOM(mask, s[i+m]))\r
+ i = i + m;\r
+ else\r
+ i = i + skip;\r
+ } else {\r
+ /* skip: check if next character is part of pattern */\r
+ if (!STRINGLIB_BLOOM(mask, s[i+m]))\r
+ i = i + m;\r
+ }\r
+ }\r
+ } else { /* FAST_RSEARCH */\r
+\r
+ /* create compressed boyer-moore delta 1 table */\r
+\r
+ /* process pattern[0] outside the loop */\r
+ STRINGLIB_BLOOM_ADD(mask, p[0]);\r
+ /* process pattern[:0:-1] */\r
+ for (i = mlast; i > 0; i--) {\r
+ STRINGLIB_BLOOM_ADD(mask, p[i]);\r
+ if (p[i] == p[0])\r
+ skip = i - 1;\r
+ }\r
+\r
+ for (i = w; i >= 0; i--) {\r
+ if (s[i] == p[0]) {\r
+ /* candidate match */\r
+ for (j = mlast; j > 0; j--)\r
+ if (s[i+j] != p[j])\r
+ break;\r
+ if (j == 0)\r
+ /* got a match! */\r
+ return i;\r
+ /* miss: check if previous character is part of pattern */\r
+ if (i > 0 && !STRINGLIB_BLOOM(mask, s[i-1]))\r
+ i = i - m;\r
+ else\r
+ i = i - skip;\r
+ } else {\r
+ /* skip: check if previous character is part of pattern */\r
+ if (i > 0 && !STRINGLIB_BLOOM(mask, s[i-1]))\r
+ i = i - m;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (mode != FAST_COUNT)\r
+ return -1;\r
+ return count;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/* stringlib: find/index implementation */\r
+\r
+#ifndef STRINGLIB_FIND_H\r
+#define STRINGLIB_FIND_H\r
+\r
+#ifndef STRINGLIB_FASTSEARCH_H\r
+#error must include "stringlib/fastsearch.h" before including this module\r
+#endif\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+stringlib_find(const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,\r
+ Py_ssize_t offset)\r
+{\r
+ Py_ssize_t pos;\r
+\r
+ if (str_len < 0)\r
+ return -1;\r
+ if (sub_len == 0)\r
+ return offset;\r
+\r
+ pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_SEARCH);\r
+\r
+ if (pos >= 0)\r
+ pos += offset;\r
+\r
+ return pos;\r
+}\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+stringlib_rfind(const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,\r
+ Py_ssize_t offset)\r
+{\r
+ Py_ssize_t pos;\r
+\r
+ if (str_len < 0)\r
+ return -1;\r
+ if (sub_len == 0)\r
+ return str_len + offset;\r
+\r
+ pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_RSEARCH);\r
+\r
+ if (pos >= 0)\r
+ pos += offset;\r
+\r
+ return pos;\r
+}\r
+\r
+/* helper macro to fixup start/end slice values */\r
+#define ADJUST_INDICES(start, end, len) \\r
+ if (end > len) \\r
+ end = len; \\r
+ else if (end < 0) { \\r
+ end += len; \\r
+ if (end < 0) \\r
+ end = 0; \\r
+ } \\r
+ if (start < 0) { \\r
+ start += len; \\r
+ if (start < 0) \\r
+ start = 0; \\r
+ }\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+stringlib_find_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,\r
+ Py_ssize_t start, Py_ssize_t end)\r
+{\r
+ ADJUST_INDICES(start, end, str_len);\r
+ return stringlib_find(str + start, end - start, sub, sub_len, start);\r
+}\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+stringlib_rfind_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,\r
+ Py_ssize_t start, Py_ssize_t end)\r
+{\r
+ ADJUST_INDICES(start, end, str_len);\r
+ return stringlib_rfind(str + start, end - start, sub, sub_len, start);\r
+}\r
+\r
+#ifdef STRINGLIB_WANT_CONTAINS_OBJ\r
+\r
+Py_LOCAL_INLINE(int)\r
+stringlib_contains_obj(PyObject* str, PyObject* sub)\r
+{\r
+ return stringlib_find(\r
+ STRINGLIB_STR(str), STRINGLIB_LEN(str),\r
+ STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0\r
+ ) != -1;\r
+}\r
+\r
+#endif /* STRINGLIB_WANT_CONTAINS_OBJ */\r
+\r
+/*\r
+This function is a helper for the "find" family (find, rfind, index,\r
+rindex) and for count, startswith and endswith, because they all have\r
+the same behaviour for the arguments.\r
+\r
+It does not touch the variables received until it knows everything \r
+is ok.\r
+*/\r
+\r
+#define FORMAT_BUFFER_SIZE 50\r
+\r
+Py_LOCAL_INLINE(int)\r
+stringlib_parse_args_finds(const char * function_name, PyObject *args,\r
+ PyObject **subobj,\r
+ Py_ssize_t *start, Py_ssize_t *end)\r
+{\r
+ PyObject *tmp_subobj;\r
+ Py_ssize_t tmp_start = 0;\r
+ Py_ssize_t tmp_end = PY_SSIZE_T_MAX;\r
+ PyObject *obj_start=Py_None, *obj_end=Py_None;\r
+ char format[FORMAT_BUFFER_SIZE] = "O|OO:";\r
+ size_t len = strlen(format);\r
+\r
+ strncpy(format + len, function_name, FORMAT_BUFFER_SIZE - len - 1);\r
+ format[FORMAT_BUFFER_SIZE - 1] = '\0';\r
+\r
+ if (!PyArg_ParseTuple(args, format, &tmp_subobj, &obj_start, &obj_end))\r
+ return 0;\r
+\r
+ /* To support None in "start" and "end" arguments, meaning\r
+ the same as if they were not passed.\r
+ */\r
+ if (obj_start != Py_None)\r
+ if (!_PyEval_SliceIndex(obj_start, &tmp_start))\r
+ return 0;\r
+ if (obj_end != Py_None)\r
+ if (!_PyEval_SliceIndex(obj_end, &tmp_end))\r
+ return 0;\r
+\r
+ *start = tmp_start;\r
+ *end = tmp_end;\r
+ *subobj = tmp_subobj;\r
+ return 1;\r
+}\r
+\r
+#undef FORMAT_BUFFER_SIZE\r
+\r
+#if STRINGLIB_IS_UNICODE\r
+\r
+/*\r
+Wraps stringlib_parse_args_finds() and additionally ensures that the\r
+first argument is a unicode object.\r
+\r
+Note that we receive a pointer to the pointer of the substring object,\r
+so when we create that object in this function we don't DECREF it,\r
+because it continues living in the caller functions (those functions, \r
+after finishing using the substring, must DECREF it).\r
+*/\r
+\r
+Py_LOCAL_INLINE(int)\r
+stringlib_parse_args_finds_unicode(const char * function_name, PyObject *args,\r
+ PyUnicodeObject **substring,\r
+ Py_ssize_t *start, Py_ssize_t *end)\r
+{\r
+ PyObject *tmp_substring;\r
+\r
+ if(stringlib_parse_args_finds(function_name, args, &tmp_substring,\r
+ start, end)) {\r
+ tmp_substring = PyUnicode_FromObject(tmp_substring);\r
+ if (!tmp_substring)\r
+ return 0;\r
+ *substring = (PyUnicodeObject *)tmp_substring;\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+#endif /* STRINGLIB_IS_UNICODE */\r
+\r
+#endif /* STRINGLIB_FIND_H */\r
--- /dev/null
+/* implements the string, long, and float formatters. that is,\r
+ string.__format__, etc. */\r
+\r
+#include <locale.h>\r
+\r
+/* Before including this, you must include either:\r
+ stringlib/unicodedefs.h\r
+ stringlib/stringdefs.h\r
+\r
+ Also, you should define the names:\r
+ FORMAT_STRING\r
+ FORMAT_LONG\r
+ FORMAT_FLOAT\r
+ FORMAT_COMPLEX\r
+ to be whatever you want the public names of these functions to\r
+ be. These are the only non-static functions defined here.\r
+*/\r
+\r
+/* Raises an exception about an unknown presentation type for this\r
+ * type. */\r
+\r
+static void\r
+unknown_presentation_type(STRINGLIB_CHAR presentation_type,\r
+ const char* type_name)\r
+{\r
+#if STRINGLIB_IS_UNICODE\r
+ /* If STRINGLIB_CHAR is Py_UNICODE, %c might be out-of-range,\r
+ hence the two cases. If it is char, gcc complains that the\r
+ condition below is always true, hence the ifdef. */\r
+ if (presentation_type > 32 && presentation_type < 128)\r
+#endif\r
+ PyErr_Format(PyExc_ValueError,\r
+ "Unknown format code '%c' "\r
+ "for object of type '%.200s'",\r
+ (char)presentation_type,\r
+ type_name);\r
+#if STRINGLIB_IS_UNICODE\r
+ else\r
+ PyErr_Format(PyExc_ValueError,\r
+ "Unknown format code '\\x%x' "\r
+ "for object of type '%.200s'",\r
+ (unsigned int)presentation_type,\r
+ type_name);\r
+#endif\r
+}\r
+\r
+static void\r
+invalid_comma_type(STRINGLIB_CHAR presentation_type)\r
+{\r
+#if STRINGLIB_IS_UNICODE\r
+ /* See comment in unknown_presentation_type */\r
+ if (presentation_type > 32 && presentation_type < 128)\r
+#endif\r
+ PyErr_Format(PyExc_ValueError,\r
+ "Cannot specify ',' with '%c'.",\r
+ (char)presentation_type);\r
+#if STRINGLIB_IS_UNICODE\r
+ else\r
+ PyErr_Format(PyExc_ValueError,\r
+ "Cannot specify ',' with '\\x%x'.",\r
+ (unsigned int)presentation_type);\r
+#endif\r
+}\r
+\r
+/*\r
+ get_integer consumes 0 or more decimal digit characters from an\r
+ input string, updates *result with the corresponding positive\r
+ integer, and returns the number of digits consumed.\r
+\r
+ returns -1 on error.\r
+*/\r
+static int\r
+get_integer(STRINGLIB_CHAR **ptr, STRINGLIB_CHAR *end,\r
+ Py_ssize_t *result)\r
+{\r
+ Py_ssize_t accumulator, digitval;\r
+ int numdigits;\r
+ accumulator = numdigits = 0;\r
+ for (;;(*ptr)++, numdigits++) {\r
+ if (*ptr >= end)\r
+ break;\r
+ digitval = STRINGLIB_TODECIMAL(**ptr);\r
+ if (digitval < 0)\r
+ break;\r
+ /*\r
+ Detect possible overflow before it happens:\r
+\r
+ accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if\r
+ accumulator > (PY_SSIZE_T_MAX - digitval) / 10.\r
+ */\r
+ if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "Too many decimal digits in format string");\r
+ return -1;\r
+ }\r
+ accumulator = accumulator * 10 + digitval;\r
+ }\r
+ *result = accumulator;\r
+ return numdigits;\r
+}\r
+\r
+/************************************************************************/\r
+/*********** standard format specifier parsing **************************/\r
+/************************************************************************/\r
+\r
+/* returns true if this character is a specifier alignment token */\r
+Py_LOCAL_INLINE(int)\r
+is_alignment_token(STRINGLIB_CHAR c)\r
+{\r
+ switch (c) {\r
+ case '<': case '>': case '=': case '^':\r
+ return 1;\r
+ default:\r
+ return 0;\r
+ }\r
+}\r
+\r
+/* returns true if this character is a sign element */\r
+Py_LOCAL_INLINE(int)\r
+is_sign_element(STRINGLIB_CHAR c)\r
+{\r
+ switch (c) {\r
+ case ' ': case '+': case '-':\r
+ return 1;\r
+ default:\r
+ return 0;\r
+ }\r
+}\r
+\r
+\r
+typedef struct {\r
+ STRINGLIB_CHAR fill_char;\r
+ STRINGLIB_CHAR align;\r
+ int alternate;\r
+ STRINGLIB_CHAR sign;\r
+ Py_ssize_t width;\r
+ int thousands_separators;\r
+ Py_ssize_t precision;\r
+ STRINGLIB_CHAR type;\r
+} InternalFormatSpec;\r
+\r
+\r
+#if 0\r
+/* Occassionally useful for debugging. Should normally be commented out. */\r
+static void\r
+DEBUG_PRINT_FORMAT_SPEC(InternalFormatSpec *format)\r
+{\r
+ printf("internal format spec: fill_char %d\n", format->fill_char);\r
+ printf("internal format spec: align %d\n", format->align);\r
+ printf("internal format spec: alternate %d\n", format->alternate);\r
+ printf("internal format spec: sign %d\n", format->sign);\r
+ printf("internal format spec: width %zd\n", format->width);\r
+ printf("internal format spec: thousands_separators %d\n",\r
+ format->thousands_separators);\r
+ printf("internal format spec: precision %zd\n", format->precision);\r
+ printf("internal format spec: type %c\n", format->type);\r
+ printf("\n");\r
+}\r
+#endif\r
+\r
+\r
+/*\r
+ ptr points to the start of the format_spec, end points just past its end.\r
+ fills in format with the parsed information.\r
+ returns 1 on success, 0 on failure.\r
+ if failure, sets the exception\r
+*/\r
+static int\r
+parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,\r
+ Py_ssize_t format_spec_len,\r
+ InternalFormatSpec *format,\r
+ char default_type,\r
+ char default_align)\r
+{\r
+ STRINGLIB_CHAR *ptr = format_spec;\r
+ STRINGLIB_CHAR *end = format_spec + format_spec_len;\r
+\r
+ /* end-ptr is used throughout this code to specify the length of\r
+ the input string */\r
+\r
+ Py_ssize_t consumed;\r
+ int align_specified = 0;\r
+ int fill_char_specified = 0;\r
+\r
+ format->fill_char = ' ';\r
+ format->align = default_align;\r
+ format->alternate = 0;\r
+ format->sign = '\0';\r
+ format->width = -1;\r
+ format->thousands_separators = 0;\r
+ format->precision = -1;\r
+ format->type = default_type;\r
+\r
+ /* If the second char is an alignment token,\r
+ then parse the fill char */\r
+ if (end-ptr >= 2 && is_alignment_token(ptr[1])) {\r
+ format->align = ptr[1];\r
+ format->fill_char = ptr[0];\r
+ fill_char_specified = 1;\r
+ align_specified = 1;\r
+ ptr += 2;\r
+ }\r
+ else if (end-ptr >= 1 && is_alignment_token(ptr[0])) {\r
+ format->align = ptr[0];\r
+ align_specified = 1;\r
+ ++ptr;\r
+ }\r
+\r
+ /* Parse the various sign options */\r
+ if (end-ptr >= 1 && is_sign_element(ptr[0])) {\r
+ format->sign = ptr[0];\r
+ ++ptr;\r
+ }\r
+\r
+ /* If the next character is #, we're in alternate mode. This only\r
+ applies to integers. */\r
+ if (end-ptr >= 1 && ptr[0] == '#') {\r
+ format->alternate = 1;\r
+ ++ptr;\r
+ }\r
+\r
+ /* The special case for 0-padding (backwards compat) */\r
+ if (!fill_char_specified && end-ptr >= 1 && ptr[0] == '0') {\r
+ format->fill_char = '0';\r
+ if (!align_specified) {\r
+ format->align = '=';\r
+ }\r
+ ++ptr;\r
+ }\r
+\r
+ consumed = get_integer(&ptr, end, &format->width);\r
+ if (consumed == -1)\r
+ /* Overflow error. Exception already set. */\r
+ return 0;\r
+\r
+ /* If consumed is 0, we didn't consume any characters for the\r
+ width. In that case, reset the width to -1, because\r
+ get_integer() will have set it to zero. -1 is how we record\r
+ that the width wasn't specified. */\r
+ if (consumed == 0)\r
+ format->width = -1;\r
+\r
+ /* Comma signifies add thousands separators */\r
+ if (end-ptr && ptr[0] == ',') {\r
+ format->thousands_separators = 1;\r
+ ++ptr;\r
+ }\r
+\r
+ /* Parse field precision */\r
+ if (end-ptr && ptr[0] == '.') {\r
+ ++ptr;\r
+\r
+ consumed = get_integer(&ptr, end, &format->precision);\r
+ if (consumed == -1)\r
+ /* Overflow error. Exception already set. */\r
+ return 0;\r
+\r
+ /* Not having a precision after a dot is an error. */\r
+ if (consumed == 0) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "Format specifier missing precision");\r
+ return 0;\r
+ }\r
+\r
+ }\r
+\r
+ /* Finally, parse the type field. */\r
+\r
+ if (end-ptr > 1) {\r
+ /* More than one char remain, invalid conversion spec. */\r
+ PyErr_Format(PyExc_ValueError, "Invalid conversion specification");\r
+ return 0;\r
+ }\r
+\r
+ if (end-ptr == 1) {\r
+ format->type = ptr[0];\r
+ ++ptr;\r
+ }\r
+\r
+ /* Do as much validating as we can, just by looking at the format\r
+ specifier. Do not take into account what type of formatting\r
+ we're doing (int, float, string). */\r
+\r
+ if (format->thousands_separators) {\r
+ switch (format->type) {\r
+ case 'd':\r
+ case 'e':\r
+ case 'f':\r
+ case 'g':\r
+ case 'E':\r
+ case 'G':\r
+ case '%':\r
+ case 'F':\r
+ case '\0':\r
+ /* These are allowed. See PEP 378.*/\r
+ break;\r
+ default:\r
+ invalid_comma_type(format->type);\r
+ return 0;\r
+ }\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+/* Calculate the padding needed. */\r
+static void\r
+calc_padding(Py_ssize_t nchars, Py_ssize_t width, STRINGLIB_CHAR align,\r
+ Py_ssize_t *n_lpadding, Py_ssize_t *n_rpadding,\r
+ Py_ssize_t *n_total)\r
+{\r
+ if (width >= 0) {\r
+ if (nchars > width)\r
+ *n_total = nchars;\r
+ else\r
+ *n_total = width;\r
+ }\r
+ else {\r
+ /* not specified, use all of the chars and no more */\r
+ *n_total = nchars;\r
+ }\r
+\r
+ /* Figure out how much leading space we need, based on the\r
+ aligning */\r
+ if (align == '>')\r
+ *n_lpadding = *n_total - nchars;\r
+ else if (align == '^')\r
+ *n_lpadding = (*n_total - nchars) / 2;\r
+ else if (align == '<' || align == '=')\r
+ *n_lpadding = 0;\r
+ else {\r
+ /* We should never have an unspecified alignment. */\r
+ *n_lpadding = 0;\r
+ assert(0);\r
+ }\r
+\r
+ *n_rpadding = *n_total - nchars - *n_lpadding;\r
+}\r
+\r
+/* Do the padding, and return a pointer to where the caller-supplied\r
+ content goes. */\r
+static STRINGLIB_CHAR *\r
+fill_padding(STRINGLIB_CHAR *p, Py_ssize_t nchars, STRINGLIB_CHAR fill_char,\r
+ Py_ssize_t n_lpadding, Py_ssize_t n_rpadding)\r
+{\r
+ /* Pad on left. */\r
+ if (n_lpadding)\r
+ STRINGLIB_FILL(p, fill_char, n_lpadding);\r
+\r
+ /* Pad on right. */\r
+ if (n_rpadding)\r
+ STRINGLIB_FILL(p + nchars + n_lpadding, fill_char, n_rpadding);\r
+\r
+ /* Pointer to the user content. */\r
+ return p + n_lpadding;\r
+}\r
+\r
+#if defined FORMAT_FLOAT || defined FORMAT_LONG || defined FORMAT_COMPLEX\r
+/************************************************************************/\r
+/*********** common routines for numeric formatting *********************/\r
+/************************************************************************/\r
+\r
+/* Locale type codes. */\r
+#define LT_CURRENT_LOCALE 0\r
+#define LT_DEFAULT_LOCALE 1\r
+#define LT_NO_LOCALE 2\r
+\r
+/* Locale info needed for formatting integers and the part of floats\r
+ before and including the decimal. Note that locales only support\r
+ 8-bit chars, not unicode. */\r
+typedef struct {\r
+ char *decimal_point;\r
+ char *thousands_sep;\r
+ char *grouping;\r
+} LocaleInfo;\r
+\r
+/* describes the layout for an integer, see the comment in\r
+ calc_number_widths() for details */\r
+typedef struct {\r
+ Py_ssize_t n_lpadding;\r
+ Py_ssize_t n_prefix;\r
+ Py_ssize_t n_spadding;\r
+ Py_ssize_t n_rpadding;\r
+ char sign;\r
+ Py_ssize_t n_sign; /* number of digits needed for sign (0/1) */\r
+ Py_ssize_t n_grouped_digits; /* Space taken up by the digits, including\r
+ any grouping chars. */\r
+ Py_ssize_t n_decimal; /* 0 if only an integer */\r
+ Py_ssize_t n_remainder; /* Digits in decimal and/or exponent part,\r
+ excluding the decimal itself, if\r
+ present. */\r
+\r
+ /* These 2 are not the widths of fields, but are needed by\r
+ STRINGLIB_GROUPING. */\r
+ Py_ssize_t n_digits; /* The number of digits before a decimal\r
+ or exponent. */\r
+ Py_ssize_t n_min_width; /* The min_width we used when we computed\r
+ the n_grouped_digits width. */\r
+} NumberFieldWidths;\r
+\r
+\r
+/* Given a number of the form:\r
+ digits[remainder]\r
+ where ptr points to the start and end points to the end, find where\r
+ the integer part ends. This could be a decimal, an exponent, both,\r
+ or neither.\r
+ If a decimal point is present, set *has_decimal and increment\r
+ remainder beyond it.\r
+ Results are undefined (but shouldn't crash) for improperly\r
+ formatted strings.\r
+*/\r
+static void\r
+parse_number(STRINGLIB_CHAR *ptr, Py_ssize_t len,\r
+ Py_ssize_t *n_remainder, int *has_decimal)\r
+{\r
+ STRINGLIB_CHAR *end = ptr + len;\r
+ STRINGLIB_CHAR *remainder;\r
+\r
+ while (ptr<end && isdigit(*ptr))\r
+ ++ptr;\r
+ remainder = ptr;\r
+\r
+ /* Does remainder start with a decimal point? */\r
+ *has_decimal = ptr<end && *remainder == '.';\r
+\r
+ /* Skip the decimal point. */\r
+ if (*has_decimal)\r
+ remainder++;\r
+\r
+ *n_remainder = end - remainder;\r
+}\r
+\r
+/* not all fields of format are used. for example, precision is\r
+ unused. should this take discrete params in order to be more clear\r
+ about what it does? or is passing a single format parameter easier\r
+ and more efficient enough to justify a little obfuscation? */\r
+static Py_ssize_t\r
+calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,\r
+ STRINGLIB_CHAR sign_char, STRINGLIB_CHAR *number,\r
+ Py_ssize_t n_number, Py_ssize_t n_remainder,\r
+ int has_decimal, const LocaleInfo *locale,\r
+ const InternalFormatSpec *format)\r
+{\r
+ Py_ssize_t n_non_digit_non_padding;\r
+ Py_ssize_t n_padding;\r
+\r
+ spec->n_digits = n_number - n_remainder - (has_decimal?1:0);\r
+ spec->n_lpadding = 0;\r
+ spec->n_prefix = n_prefix;\r
+ spec->n_decimal = has_decimal ? strlen(locale->decimal_point) : 0;\r
+ spec->n_remainder = n_remainder;\r
+ spec->n_spadding = 0;\r
+ spec->n_rpadding = 0;\r
+ spec->sign = '\0';\r
+ spec->n_sign = 0;\r
+\r
+ /* the output will look like:\r
+ | |\r
+ | <lpadding> <sign> <prefix> <spadding> <grouped_digits> <decimal> <remainder> <rpadding> |\r
+ | |\r
+\r
+ sign is computed from format->sign and the actual\r
+ sign of the number\r
+\r
+ prefix is given (it's for the '0x' prefix)\r
+\r
+ digits is already known\r
+\r
+ the total width is either given, or computed from the\r
+ actual digits\r
+\r
+ only one of lpadding, spadding, and rpadding can be non-zero,\r
+ and it's calculated from the width and other fields\r
+ */\r
+\r
+ /* compute the various parts we're going to write */\r
+ switch (format->sign) {\r
+ case '+':\r
+ /* always put a + or - */\r
+ spec->n_sign = 1;\r
+ spec->sign = (sign_char == '-' ? '-' : '+');\r
+ break;\r
+ case ' ':\r
+ spec->n_sign = 1;\r
+ spec->sign = (sign_char == '-' ? '-' : ' ');\r
+ break;\r
+ default:\r
+ /* Not specified, or the default (-) */\r
+ if (sign_char == '-') {\r
+ spec->n_sign = 1;\r
+ spec->sign = '-';\r
+ }\r
+ }\r
+\r
+ /* The number of chars used for non-digits and non-padding. */\r
+ n_non_digit_non_padding = spec->n_sign + spec->n_prefix + spec->n_decimal +\r
+ spec->n_remainder;\r
+\r
+ /* min_width can go negative, that's okay. format->width == -1 means\r
+ we don't care. */\r
+ if (format->fill_char == '0' && format->align == '=')\r
+ spec->n_min_width = format->width - n_non_digit_non_padding;\r
+ else\r
+ spec->n_min_width = 0;\r
+\r
+ if (spec->n_digits == 0)\r
+ /* This case only occurs when using 'c' formatting, we need\r
+ to special case it because the grouping code always wants\r
+ to have at least one character. */\r
+ spec->n_grouped_digits = 0;\r
+ else\r
+ spec->n_grouped_digits = STRINGLIB_GROUPING(NULL, 0, NULL,\r
+ spec->n_digits,\r
+ spec->n_min_width,\r
+ locale->grouping,\r
+ locale->thousands_sep);\r
+\r
+ /* Given the desired width and the total of digit and non-digit\r
+ space we consume, see if we need any padding. format->width can\r
+ be negative (meaning no padding), but this code still works in\r
+ that case. */\r
+ n_padding = format->width -\r
+ (n_non_digit_non_padding + spec->n_grouped_digits);\r
+ if (n_padding > 0) {\r
+ /* Some padding is needed. Determine if it's left, space, or right. */\r
+ switch (format->align) {\r
+ case '<':\r
+ spec->n_rpadding = n_padding;\r
+ break;\r
+ case '^':\r
+ spec->n_lpadding = n_padding / 2;\r
+ spec->n_rpadding = n_padding - spec->n_lpadding;\r
+ break;\r
+ case '=':\r
+ spec->n_spadding = n_padding;\r
+ break;\r
+ case '>':\r
+ spec->n_lpadding = n_padding;\r
+ break;\r
+ default:\r
+ /* Shouldn't get here, but treat it as '>' */\r
+ spec->n_lpadding = n_padding;\r
+ assert(0);\r
+ break;\r
+ }\r
+ }\r
+ return spec->n_lpadding + spec->n_sign + spec->n_prefix +\r
+ spec->n_spadding + spec->n_grouped_digits + spec->n_decimal +\r
+ spec->n_remainder + spec->n_rpadding;\r
+}\r
+\r
+/* Fill in the digit parts of a numbers's string representation,\r
+ as determined in calc_number_widths().\r
+ No error checking, since we know the buffer is the correct size. */\r
+static void\r
+fill_number(STRINGLIB_CHAR *buf, const NumberFieldWidths *spec,\r
+ STRINGLIB_CHAR *digits, Py_ssize_t n_digits,\r
+ STRINGLIB_CHAR *prefix, STRINGLIB_CHAR fill_char,\r
+ LocaleInfo *locale, int toupper)\r
+{\r
+ /* Used to keep track of digits, decimal, and remainder. */\r
+ STRINGLIB_CHAR *p = digits;\r
+\r
+#ifndef NDEBUG\r
+ Py_ssize_t r;\r
+#endif\r
+\r
+ if (spec->n_lpadding) {\r
+ STRINGLIB_FILL(buf, fill_char, spec->n_lpadding);\r
+ buf += spec->n_lpadding;\r
+ }\r
+ if (spec->n_sign == 1) {\r
+ *buf++ = spec->sign;\r
+ }\r
+ if (spec->n_prefix) {\r
+ memmove(buf,\r
+ prefix,\r
+ spec->n_prefix * sizeof(STRINGLIB_CHAR));\r
+ if (toupper) {\r
+ Py_ssize_t t;\r
+ for (t = 0; t < spec->n_prefix; ++t)\r
+ buf[t] = STRINGLIB_TOUPPER(buf[t]);\r
+ }\r
+ buf += spec->n_prefix;\r
+ }\r
+ if (spec->n_spadding) {\r
+ STRINGLIB_FILL(buf, fill_char, spec->n_spadding);\r
+ buf += spec->n_spadding;\r
+ }\r
+\r
+ /* Only for type 'c' special case, it has no digits. */\r
+ if (spec->n_digits != 0) {\r
+ /* Fill the digits with InsertThousandsGrouping. */\r
+#ifndef NDEBUG\r
+ r =\r
+#endif\r
+ STRINGLIB_GROUPING(buf, spec->n_grouped_digits, digits,\r
+ spec->n_digits, spec->n_min_width,\r
+ locale->grouping, locale->thousands_sep);\r
+#ifndef NDEBUG\r
+ assert(r == spec->n_grouped_digits);\r
+#endif\r
+ p += spec->n_digits;\r
+ }\r
+ if (toupper) {\r
+ Py_ssize_t t;\r
+ for (t = 0; t < spec->n_grouped_digits; ++t)\r
+ buf[t] = STRINGLIB_TOUPPER(buf[t]);\r
+ }\r
+ buf += spec->n_grouped_digits;\r
+\r
+ if (spec->n_decimal) {\r
+ Py_ssize_t t;\r
+ for (t = 0; t < spec->n_decimal; ++t)\r
+ buf[t] = locale->decimal_point[t];\r
+ buf += spec->n_decimal;\r
+ p += 1;\r
+ }\r
+\r
+ if (spec->n_remainder) {\r
+ memcpy(buf, p, spec->n_remainder * sizeof(STRINGLIB_CHAR));\r
+ buf += spec->n_remainder;\r
+ p += spec->n_remainder;\r
+ }\r
+\r
+ if (spec->n_rpadding) {\r
+ STRINGLIB_FILL(buf, fill_char, spec->n_rpadding);\r
+ buf += spec->n_rpadding;\r
+ }\r
+}\r
+\r
+static char no_grouping[1] = {CHAR_MAX};\r
+\r
+/* Find the decimal point character(s?), thousands_separator(s?), and\r
+ grouping description, either for the current locale if type is\r
+ LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE, or\r
+ none if LT_NO_LOCALE. */\r
+static void\r
+get_locale_info(int type, LocaleInfo *locale_info)\r
+{\r
+ switch (type) {\r
+ case LT_CURRENT_LOCALE: {\r
+ struct lconv *locale_data = localeconv();\r
+ locale_info->decimal_point = locale_data->decimal_point;\r
+ locale_info->thousands_sep = locale_data->thousands_sep;\r
+ locale_info->grouping = locale_data->grouping;\r
+ break;\r
+ }\r
+ case LT_DEFAULT_LOCALE:\r
+ locale_info->decimal_point = ".";\r
+ locale_info->thousands_sep = ",";\r
+ locale_info->grouping = "\3"; /* Group every 3 characters. The\r
+ (implicit) trailing 0 means repeat\r
+ infinitely. */\r
+ break;\r
+ case LT_NO_LOCALE:\r
+ locale_info->decimal_point = ".";\r
+ locale_info->thousands_sep = "";\r
+ locale_info->grouping = no_grouping;\r
+ break;\r
+ default:\r
+ assert(0);\r
+ }\r
+}\r
+\r
+#endif /* FORMAT_FLOAT || FORMAT_LONG || FORMAT_COMPLEX */\r
+\r
+/************************************************************************/\r
+/*********** string formatting ******************************************/\r
+/************************************************************************/\r
+\r
+static PyObject *\r
+format_string_internal(PyObject *value, const InternalFormatSpec *format)\r
+{\r
+ Py_ssize_t lpad;\r
+ Py_ssize_t rpad;\r
+ Py_ssize_t total;\r
+ STRINGLIB_CHAR *p;\r
+ Py_ssize_t len = STRINGLIB_LEN(value);\r
+ PyObject *result = NULL;\r
+\r
+ /* sign is not allowed on strings */\r
+ if (format->sign != '\0') {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Sign not allowed in string format specifier");\r
+ goto done;\r
+ }\r
+\r
+ /* alternate is not allowed on strings */\r
+ if (format->alternate) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Alternate form (#) not allowed in string format "\r
+ "specifier");\r
+ goto done;\r
+ }\r
+\r
+ /* '=' alignment not allowed on strings */\r
+ if (format->align == '=') {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "'=' alignment not allowed "\r
+ "in string format specifier");\r
+ goto done;\r
+ }\r
+\r
+ /* if precision is specified, output no more that format.precision\r
+ characters */\r
+ if (format->precision >= 0 && len >= format->precision) {\r
+ len = format->precision;\r
+ }\r
+\r
+ calc_padding(len, format->width, format->align, &lpad, &rpad, &total);\r
+\r
+ /* allocate the resulting string */\r
+ result = STRINGLIB_NEW(NULL, total);\r
+ if (result == NULL)\r
+ goto done;\r
+\r
+ /* Write into that space. First the padding. */\r
+ p = fill_padding(STRINGLIB_STR(result), len,\r
+ format->fill_char, lpad, rpad);\r
+\r
+ /* Then the source string. */\r
+ memcpy(p, STRINGLIB_STR(value), len * sizeof(STRINGLIB_CHAR));\r
+\r
+done:\r
+ return result;\r
+}\r
+\r
+\r
+/************************************************************************/\r
+/*********** long formatting ********************************************/\r
+/************************************************************************/\r
+\r
+#if defined FORMAT_LONG || defined FORMAT_INT\r
+typedef PyObject*\r
+(*IntOrLongToString)(PyObject *value, int base);\r
+\r
+static PyObject *\r
+format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,\r
+ IntOrLongToString tostring)\r
+{\r
+ PyObject *result = NULL;\r
+ PyObject *tmp = NULL;\r
+ STRINGLIB_CHAR *pnumeric_chars;\r
+ STRINGLIB_CHAR numeric_char;\r
+ STRINGLIB_CHAR sign_char = '\0';\r
+ Py_ssize_t n_digits; /* count of digits need from the computed\r
+ string */\r
+ Py_ssize_t n_remainder = 0; /* Used only for 'c' formatting, which\r
+ produces non-digits */\r
+ Py_ssize_t n_prefix = 0; /* Count of prefix chars, (e.g., '0x') */\r
+ Py_ssize_t n_total;\r
+ STRINGLIB_CHAR *prefix = NULL;\r
+ NumberFieldWidths spec;\r
+ long x;\r
+\r
+ /* Locale settings, either from the actual locale or\r
+ from a hard-code pseudo-locale */\r
+ LocaleInfo locale;\r
+\r
+ /* no precision allowed on integers */\r
+ if (format->precision != -1) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Precision not allowed in integer format specifier");\r
+ goto done;\r
+ }\r
+\r
+ /* special case for character formatting */\r
+ if (format->type == 'c') {\r
+ /* error to specify a sign */\r
+ if (format->sign != '\0') {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Sign not allowed with integer"\r
+ " format specifier 'c'");\r
+ goto done;\r
+ }\r
+\r
+ /* Error to specify a comma. */\r
+ if (format->thousands_separators) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Thousands separators not allowed with integer"\r
+ " format specifier 'c'");\r
+ goto done;\r
+ }\r
+\r
+ /* taken from unicodeobject.c formatchar() */\r
+ /* Integer input truncated to a character */\r
+/* XXX: won't work for int */\r
+ x = PyLong_AsLong(value);\r
+ if (x == -1 && PyErr_Occurred())\r
+ goto done;\r
+#ifdef Py_UNICODE_WIDE\r
+ if (x < 0 || x > 0x10ffff) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "%c arg not in range(0x110000) "\r
+ "(wide Python build)");\r
+ goto done;\r
+ }\r
+#else\r
+ if (x < 0 || x > 0xffff) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "%c arg not in range(0x10000) "\r
+ "(narrow Python build)");\r
+ goto done;\r
+ }\r
+#endif\r
+ numeric_char = (STRINGLIB_CHAR)x;\r
+ pnumeric_chars = &numeric_char;\r
+ n_digits = 1;\r
+\r
+ /* As a sort-of hack, we tell calc_number_widths that we only\r
+ have "remainder" characters. calc_number_widths thinks\r
+ these are characters that don't get formatted, only copied\r
+ into the output string. We do this for 'c' formatting,\r
+ because the characters are likely to be non-digits. */\r
+ n_remainder = 1;\r
+ }\r
+ else {\r
+ int base;\r
+ int leading_chars_to_skip = 0; /* Number of characters added by\r
+ PyNumber_ToBase that we want to\r
+ skip over. */\r
+\r
+ /* Compute the base and how many characters will be added by\r
+ PyNumber_ToBase */\r
+ switch (format->type) {\r
+ case 'b':\r
+ base = 2;\r
+ leading_chars_to_skip = 2; /* 0b */\r
+ break;\r
+ case 'o':\r
+ base = 8;\r
+ leading_chars_to_skip = 2; /* 0o */\r
+ break;\r
+ case 'x':\r
+ case 'X':\r
+ base = 16;\r
+ leading_chars_to_skip = 2; /* 0x */\r
+ break;\r
+ default: /* shouldn't be needed, but stops a compiler warning */\r
+ case 'd':\r
+ case 'n':\r
+ base = 10;\r
+ break;\r
+ }\r
+\r
+ /* The number of prefix chars is the same as the leading\r
+ chars to skip */\r
+ if (format->alternate)\r
+ n_prefix = leading_chars_to_skip;\r
+\r
+ /* Do the hard part, converting to a string in a given base */\r
+ tmp = tostring(value, base);\r
+ if (tmp == NULL)\r
+ goto done;\r
+\r
+ pnumeric_chars = STRINGLIB_STR(tmp);\r
+ n_digits = STRINGLIB_LEN(tmp);\r
+\r
+ prefix = pnumeric_chars;\r
+\r
+ /* Remember not to modify what pnumeric_chars points to. it\r
+ might be interned. Only modify it after we copy it into a\r
+ newly allocated output buffer. */\r
+\r
+ /* Is a sign character present in the output? If so, remember it\r
+ and skip it */\r
+ if (pnumeric_chars[0] == '-') {\r
+ sign_char = pnumeric_chars[0];\r
+ ++prefix;\r
+ ++leading_chars_to_skip;\r
+ }\r
+\r
+ /* Skip over the leading chars (0x, 0b, etc.) */\r
+ n_digits -= leading_chars_to_skip;\r
+ pnumeric_chars += leading_chars_to_skip;\r
+ }\r
+\r
+ /* Determine the grouping, separator, and decimal point, if any. */\r
+ get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :\r
+ (format->thousands_separators ?\r
+ LT_DEFAULT_LOCALE :\r
+ LT_NO_LOCALE),\r
+ &locale);\r
+\r
+ /* Calculate how much memory we'll need. */\r
+ n_total = calc_number_widths(&spec, n_prefix, sign_char, pnumeric_chars,\r
+ n_digits, n_remainder, 0, &locale, format);\r
+\r
+ /* Allocate the memory. */\r
+ result = STRINGLIB_NEW(NULL, n_total);\r
+ if (!result)\r
+ goto done;\r
+\r
+ /* Populate the memory. */\r
+ fill_number(STRINGLIB_STR(result), &spec, pnumeric_chars, n_digits,\r
+ prefix, format->fill_char, &locale, format->type == 'X');\r
+\r
+done:\r
+ Py_XDECREF(tmp);\r
+ return result;\r
+}\r
+#endif /* defined FORMAT_LONG || defined FORMAT_INT */\r
+\r
+/************************************************************************/\r
+/*********** float formatting *******************************************/\r
+/************************************************************************/\r
+\r
+#ifdef FORMAT_FLOAT\r
+#if STRINGLIB_IS_UNICODE\r
+static void\r
+strtounicode(Py_UNICODE *buffer, const char *charbuffer, Py_ssize_t len)\r
+{\r
+ Py_ssize_t i;\r
+ for (i = 0; i < len; ++i)\r
+ buffer[i] = (Py_UNICODE)charbuffer[i];\r
+}\r
+#endif\r
+\r
+/* much of this is taken from unicodeobject.c */\r
+static PyObject *\r
+format_float_internal(PyObject *value,\r
+ const InternalFormatSpec *format)\r
+{\r
+ char *buf = NULL; /* buffer returned from PyOS_double_to_string */\r
+ Py_ssize_t n_digits;\r
+ Py_ssize_t n_remainder;\r
+ Py_ssize_t n_total;\r
+ int has_decimal;\r
+ double val;\r
+ Py_ssize_t precision;\r
+ Py_ssize_t default_precision = 6;\r
+ STRINGLIB_CHAR type = format->type;\r
+ int add_pct = 0;\r
+ STRINGLIB_CHAR *p;\r
+ NumberFieldWidths spec;\r
+ int flags = 0;\r
+ PyObject *result = NULL;\r
+ STRINGLIB_CHAR sign_char = '\0';\r
+ int float_type; /* Used to see if we have a nan, inf, or regular float. */\r
+\r
+#if STRINGLIB_IS_UNICODE\r
+ Py_UNICODE *unicode_tmp = NULL;\r
+#endif\r
+\r
+ /* Locale settings, either from the actual locale or\r
+ from a hard-code pseudo-locale */\r
+ LocaleInfo locale;\r
+\r
+ if (format->precision > INT_MAX) {\r
+ PyErr_SetString(PyExc_ValueError, "precision too big");\r
+ goto done;\r
+ }\r
+ precision = (int)format->precision;\r
+\r
+ /* Alternate is not allowed on floats. */\r
+ if (format->alternate) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Alternate form (#) not allowed in float format "\r
+ "specifier");\r
+ goto done;\r
+ }\r
+\r
+ if (type == '\0') {\r
+ /* Omitted type specifier. This is like 'g' but with at least one\r
+ digit after the decimal point, and different default precision.*/\r
+ type = 'g';\r
+ default_precision = PyFloat_STR_PRECISION;\r
+ flags |= Py_DTSF_ADD_DOT_0;\r
+ }\r
+\r
+ if (type == 'n')\r
+ /* 'n' is the same as 'g', except for the locale used to\r
+ format the result. We take care of that later. */\r
+ type = 'g';\r
+\r
+ val = PyFloat_AsDouble(value);\r
+ if (val == -1.0 && PyErr_Occurred())\r
+ goto done;\r
+\r
+ if (type == '%') {\r
+ type = 'f';\r
+ val *= 100;\r
+ add_pct = 1;\r
+ }\r
+\r
+ if (precision < 0)\r
+ precision = default_precision;\r
+\r
+ /* Cast "type", because if we're in unicode we need to pass a\r
+ 8-bit char. This is safe, because we've restricted what "type"\r
+ can be. */\r
+ buf = PyOS_double_to_string(val, (char)type, precision, flags,\r
+ &float_type);\r
+ if (buf == NULL)\r
+ goto done;\r
+ n_digits = strlen(buf);\r
+\r
+ if (add_pct) {\r
+ /* We know that buf has a trailing zero (since we just called\r
+ strlen() on it), and we don't use that fact any more. So we\r
+ can just write over the trailing zero. */\r
+ buf[n_digits] = '%';\r
+ n_digits += 1;\r
+ }\r
+\r
+ /* Since there is no unicode version of PyOS_double_to_string,\r
+ just use the 8 bit version and then convert to unicode. */\r
+#if STRINGLIB_IS_UNICODE\r
+ unicode_tmp = (Py_UNICODE*)PyMem_Malloc((n_digits)*sizeof(Py_UNICODE));\r
+ if (unicode_tmp == NULL) {\r
+ PyErr_NoMemory();\r
+ goto done;\r
+ }\r
+ strtounicode(unicode_tmp, buf, n_digits);\r
+ p = unicode_tmp;\r
+#else\r
+ p = buf;\r
+#endif\r
+\r
+ /* Is a sign character present in the output? If so, remember it\r
+ and skip it */\r
+ if (*p == '-') {\r
+ sign_char = *p;\r
+ ++p;\r
+ --n_digits;\r
+ }\r
+\r
+ /* Determine if we have any "remainder" (after the digits, might include\r
+ decimal or exponent or both (or neither)) */\r
+ parse_number(p, n_digits, &n_remainder, &has_decimal);\r
+\r
+ /* Determine the grouping, separator, and decimal point, if any. */\r
+ get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :\r
+ (format->thousands_separators ?\r
+ LT_DEFAULT_LOCALE :\r
+ LT_NO_LOCALE),\r
+ &locale);\r
+\r
+ /* Calculate how much memory we'll need. */\r
+ n_total = calc_number_widths(&spec, 0, sign_char, p, n_digits,\r
+ n_remainder, has_decimal, &locale, format);\r
+\r
+ /* Allocate the memory. */\r
+ result = STRINGLIB_NEW(NULL, n_total);\r
+ if (result == NULL)\r
+ goto done;\r
+\r
+ /* Populate the memory. */\r
+ fill_number(STRINGLIB_STR(result), &spec, p, n_digits, NULL,\r
+ format->fill_char, &locale, 0);\r
+\r
+done:\r
+ PyMem_Free(buf);\r
+#if STRINGLIB_IS_UNICODE\r
+ PyMem_Free(unicode_tmp);\r
+#endif\r
+ return result;\r
+}\r
+#endif /* FORMAT_FLOAT */\r
+\r
+/************************************************************************/\r
+/*********** complex formatting *****************************************/\r
+/************************************************************************/\r
+\r
+#ifdef FORMAT_COMPLEX\r
+\r
+static PyObject *\r
+format_complex_internal(PyObject *value,\r
+ const InternalFormatSpec *format)\r
+{\r
+ double re;\r
+ double im;\r
+ char *re_buf = NULL; /* buffer returned from PyOS_double_to_string */\r
+ char *im_buf = NULL; /* buffer returned from PyOS_double_to_string */\r
+\r
+ InternalFormatSpec tmp_format = *format;\r
+ Py_ssize_t n_re_digits;\r
+ Py_ssize_t n_im_digits;\r
+ Py_ssize_t n_re_remainder;\r
+ Py_ssize_t n_im_remainder;\r
+ Py_ssize_t n_re_total;\r
+ Py_ssize_t n_im_total;\r
+ int re_has_decimal;\r
+ int im_has_decimal;\r
+ Py_ssize_t precision;\r
+ Py_ssize_t default_precision = 6;\r
+ STRINGLIB_CHAR type = format->type;\r
+ STRINGLIB_CHAR *p_re;\r
+ STRINGLIB_CHAR *p_im;\r
+ NumberFieldWidths re_spec;\r
+ NumberFieldWidths im_spec;\r
+ int flags = 0;\r
+ PyObject *result = NULL;\r
+ STRINGLIB_CHAR *p;\r
+ STRINGLIB_CHAR re_sign_char = '\0';\r
+ STRINGLIB_CHAR im_sign_char = '\0';\r
+ int re_float_type; /* Used to see if we have a nan, inf, or regular float. */\r
+ int im_float_type;\r
+ int add_parens = 0;\r
+ int skip_re = 0;\r
+ Py_ssize_t lpad;\r
+ Py_ssize_t rpad;\r
+ Py_ssize_t total;\r
+\r
+#if STRINGLIB_IS_UNICODE\r
+ Py_UNICODE *re_unicode_tmp = NULL;\r
+ Py_UNICODE *im_unicode_tmp = NULL;\r
+#endif\r
+\r
+ /* Locale settings, either from the actual locale or\r
+ from a hard-code pseudo-locale */\r
+ LocaleInfo locale;\r
+\r
+ if (format->precision > INT_MAX) {\r
+ PyErr_SetString(PyExc_ValueError, "precision too big");\r
+ goto done;\r
+ }\r
+ precision = (int)format->precision;\r
+\r
+ /* Alternate is not allowed on complex. */\r
+ if (format->alternate) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Alternate form (#) not allowed in complex format "\r
+ "specifier");\r
+ goto done;\r
+ }\r
+\r
+ /* Neither is zero pading. */\r
+ if (format->fill_char == '0') {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Zero padding is not allowed in complex format "\r
+ "specifier");\r
+ goto done;\r
+ }\r
+\r
+ /* Neither is '=' alignment . */\r
+ if (format->align == '=') {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "'=' alignment flag is not allowed in complex format "\r
+ "specifier");\r
+ goto done;\r
+ }\r
+\r
+ re = PyComplex_RealAsDouble(value);\r
+ if (re == -1.0 && PyErr_Occurred())\r
+ goto done;\r
+ im = PyComplex_ImagAsDouble(value);\r
+ if (im == -1.0 && PyErr_Occurred())\r
+ goto done;\r
+\r
+ if (type == '\0') {\r
+ /* Omitted type specifier. Should be like str(self). */\r
+ type = 'g';\r
+ default_precision = PyFloat_STR_PRECISION;\r
+ if (re == 0.0 && copysign(1.0, re) == 1.0)\r
+ skip_re = 1;\r
+ else\r
+ add_parens = 1;\r
+ }\r
+\r
+ if (type == 'n')\r
+ /* 'n' is the same as 'g', except for the locale used to\r
+ format the result. We take care of that later. */\r
+ type = 'g';\r
+\r
+ if (precision < 0)\r
+ precision = default_precision;\r
+\r
+ /* Cast "type", because if we're in unicode we need to pass a\r
+ 8-bit char. This is safe, because we've restricted what "type"\r
+ can be. */\r
+ re_buf = PyOS_double_to_string(re, (char)type, precision, flags,\r
+ &re_float_type);\r
+ if (re_buf == NULL)\r
+ goto done;\r
+ im_buf = PyOS_double_to_string(im, (char)type, precision, flags,\r
+ &im_float_type);\r
+ if (im_buf == NULL)\r
+ goto done;\r
+\r
+ n_re_digits = strlen(re_buf);\r
+ n_im_digits = strlen(im_buf);\r
+\r
+ /* Since there is no unicode version of PyOS_double_to_string,\r
+ just use the 8 bit version and then convert to unicode. */\r
+#if STRINGLIB_IS_UNICODE\r
+ re_unicode_tmp = (Py_UNICODE*)PyMem_Malloc((n_re_digits)*sizeof(Py_UNICODE));\r
+ if (re_unicode_tmp == NULL) {\r
+ PyErr_NoMemory();\r
+ goto done;\r
+ }\r
+ strtounicode(re_unicode_tmp, re_buf, n_re_digits);\r
+ p_re = re_unicode_tmp;\r
+\r
+ im_unicode_tmp = (Py_UNICODE*)PyMem_Malloc((n_im_digits)*sizeof(Py_UNICODE));\r
+ if (im_unicode_tmp == NULL) {\r
+ PyErr_NoMemory();\r
+ goto done;\r
+ }\r
+ strtounicode(im_unicode_tmp, im_buf, n_im_digits);\r
+ p_im = im_unicode_tmp;\r
+#else\r
+ p_re = re_buf;\r
+ p_im = im_buf;\r
+#endif\r
+\r
+ /* Is a sign character present in the output? If so, remember it\r
+ and skip it */\r
+ if (*p_re == '-') {\r
+ re_sign_char = *p_re;\r
+ ++p_re;\r
+ --n_re_digits;\r
+ }\r
+ if (*p_im == '-') {\r
+ im_sign_char = *p_im;\r
+ ++p_im;\r
+ --n_im_digits;\r
+ }\r
+\r
+ /* Determine if we have any "remainder" (after the digits, might include\r
+ decimal or exponent or both (or neither)) */\r
+ parse_number(p_re, n_re_digits, &n_re_remainder, &re_has_decimal);\r
+ parse_number(p_im, n_im_digits, &n_im_remainder, &im_has_decimal);\r
+\r
+ /* Determine the grouping, separator, and decimal point, if any. */\r
+ get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :\r
+ (format->thousands_separators ?\r
+ LT_DEFAULT_LOCALE :\r
+ LT_NO_LOCALE),\r
+ &locale);\r
+\r
+ /* Turn off any padding. We'll do it later after we've composed\r
+ the numbers without padding. */\r
+ tmp_format.fill_char = '\0';\r
+ tmp_format.align = '<';\r
+ tmp_format.width = -1;\r
+\r
+ /* Calculate how much memory we'll need. */\r
+ n_re_total = calc_number_widths(&re_spec, 0, re_sign_char, p_re,\r
+ n_re_digits, n_re_remainder,\r
+ re_has_decimal, &locale, &tmp_format);\r
+\r
+ /* Same formatting, but always include a sign, unless the real part is\r
+ * going to be omitted, in which case we use whatever sign convention was\r
+ * requested by the original format. */\r
+ if (!skip_re)\r
+ tmp_format.sign = '+';\r
+ n_im_total = calc_number_widths(&im_spec, 0, im_sign_char, p_im,\r
+ n_im_digits, n_im_remainder,\r
+ im_has_decimal, &locale, &tmp_format);\r
+\r
+ if (skip_re)\r
+ n_re_total = 0;\r
+\r
+ /* Add 1 for the 'j', and optionally 2 for parens. */\r
+ calc_padding(n_re_total + n_im_total + 1 + add_parens * 2,\r
+ format->width, format->align, &lpad, &rpad, &total);\r
+\r
+ result = STRINGLIB_NEW(NULL, total);\r
+ if (result == NULL)\r
+ goto done;\r
+\r
+ /* Populate the memory. First, the padding. */\r
+ p = fill_padding(STRINGLIB_STR(result),\r
+ n_re_total + n_im_total + 1 + add_parens * 2,\r
+ format->fill_char, lpad, rpad);\r
+\r
+ if (add_parens)\r
+ *p++ = '(';\r
+\r
+ if (!skip_re) {\r
+ fill_number(p, &re_spec, p_re, n_re_digits, NULL, 0, &locale, 0);\r
+ p += n_re_total;\r
+ }\r
+ fill_number(p, &im_spec, p_im, n_im_digits, NULL, 0, &locale, 0);\r
+ p += n_im_total;\r
+ *p++ = 'j';\r
+\r
+ if (add_parens)\r
+ *p++ = ')';\r
+\r
+done:\r
+ PyMem_Free(re_buf);\r
+ PyMem_Free(im_buf);\r
+#if STRINGLIB_IS_UNICODE\r
+ PyMem_Free(re_unicode_tmp);\r
+ PyMem_Free(im_unicode_tmp);\r
+#endif\r
+ return result;\r
+}\r
+#endif /* FORMAT_COMPLEX */\r
+\r
+/************************************************************************/\r
+/*********** built in formatters ****************************************/\r
+/************************************************************************/\r
+PyObject *\r
+FORMAT_STRING(PyObject *obj,\r
+ STRINGLIB_CHAR *format_spec,\r
+ Py_ssize_t format_spec_len)\r
+{\r
+ InternalFormatSpec format;\r
+ PyObject *result = NULL;\r
+\r
+ /* check for the special case of zero length format spec, make\r
+ it equivalent to str(obj) */\r
+ if (format_spec_len == 0) {\r
+ result = STRINGLIB_TOSTR(obj);\r
+ goto done;\r
+ }\r
+\r
+ /* parse the format_spec */\r
+ if (!parse_internal_render_format_spec(format_spec, format_spec_len,\r
+ &format, 's', '<'))\r
+ goto done;\r
+\r
+ /* type conversion? */\r
+ switch (format.type) {\r
+ case 's':\r
+ /* no type conversion needed, already a string. do the formatting */\r
+ result = format_string_internal(obj, &format);\r
+ break;\r
+ default:\r
+ /* unknown */\r
+ unknown_presentation_type(format.type, obj->ob_type->tp_name);\r
+ goto done;\r
+ }\r
+\r
+done:\r
+ return result;\r
+}\r
+\r
+#if defined FORMAT_LONG || defined FORMAT_INT\r
+static PyObject*\r
+format_int_or_long(PyObject* obj,\r
+ STRINGLIB_CHAR *format_spec,\r
+ Py_ssize_t format_spec_len,\r
+ IntOrLongToString tostring)\r
+{\r
+ PyObject *result = NULL;\r
+ PyObject *tmp = NULL;\r
+ InternalFormatSpec format;\r
+\r
+ /* check for the special case of zero length format spec, make\r
+ it equivalent to str(obj) */\r
+ if (format_spec_len == 0) {\r
+ result = STRINGLIB_TOSTR(obj);\r
+ goto done;\r
+ }\r
+\r
+ /* parse the format_spec */\r
+ if (!parse_internal_render_format_spec(format_spec,\r
+ format_spec_len,\r
+ &format, 'd', '>'))\r
+ goto done;\r
+\r
+ /* type conversion? */\r
+ switch (format.type) {\r
+ case 'b':\r
+ case 'c':\r
+ case 'd':\r
+ case 'o':\r
+ case 'x':\r
+ case 'X':\r
+ case 'n':\r
+ /* no type conversion needed, already an int (or long). do\r
+ the formatting */\r
+ result = format_int_or_long_internal(obj, &format, tostring);\r
+ break;\r
+\r
+ case 'e':\r
+ case 'E':\r
+ case 'f':\r
+ case 'F':\r
+ case 'g':\r
+ case 'G':\r
+ case '%':\r
+ /* convert to float */\r
+ tmp = PyNumber_Float(obj);\r
+ if (tmp == NULL)\r
+ goto done;\r
+ result = format_float_internal(tmp, &format);\r
+ break;\r
+\r
+ default:\r
+ /* unknown */\r
+ unknown_presentation_type(format.type, obj->ob_type->tp_name);\r
+ goto done;\r
+ }\r
+\r
+done:\r
+ Py_XDECREF(tmp);\r
+ return result;\r
+}\r
+#endif /* FORMAT_LONG || defined FORMAT_INT */\r
+\r
+#ifdef FORMAT_LONG\r
+/* Need to define long_format as a function that will convert a long\r
+ to a string. In 3.0, _PyLong_Format has the correct signature. In\r
+ 2.x, we need to fudge a few parameters */\r
+#if PY_VERSION_HEX >= 0x03000000\r
+#define long_format _PyLong_Format\r
+#else\r
+static PyObject*\r
+long_format(PyObject* value, int base)\r
+{\r
+ /* Convert to base, don't add trailing 'L', and use the new octal\r
+ format. We already know this is a long object */\r
+ assert(PyLong_Check(value));\r
+ /* convert to base, don't add 'L', and use the new octal format */\r
+ return _PyLong_Format(value, base, 0, 1);\r
+}\r
+#endif\r
+\r
+PyObject *\r
+FORMAT_LONG(PyObject *obj,\r
+ STRINGLIB_CHAR *format_spec,\r
+ Py_ssize_t format_spec_len)\r
+{\r
+ return format_int_or_long(obj, format_spec, format_spec_len,\r
+ long_format);\r
+}\r
+#endif /* FORMAT_LONG */\r
+\r
+#ifdef FORMAT_INT\r
+/* this is only used for 2.x, not 3.0 */\r
+static PyObject*\r
+int_format(PyObject* value, int base)\r
+{\r
+ /* Convert to base, and use the new octal format. We already\r
+ know this is an int object */\r
+ assert(PyInt_Check(value));\r
+ return _PyInt_Format((PyIntObject*)value, base, 1);\r
+}\r
+\r
+PyObject *\r
+FORMAT_INT(PyObject *obj,\r
+ STRINGLIB_CHAR *format_spec,\r
+ Py_ssize_t format_spec_len)\r
+{\r
+ return format_int_or_long(obj, format_spec, format_spec_len,\r
+ int_format);\r
+}\r
+#endif /* FORMAT_INT */\r
+\r
+#ifdef FORMAT_FLOAT\r
+PyObject *\r
+FORMAT_FLOAT(PyObject *obj,\r
+ STRINGLIB_CHAR *format_spec,\r
+ Py_ssize_t format_spec_len)\r
+{\r
+ PyObject *result = NULL;\r
+ InternalFormatSpec format;\r
+\r
+ /* check for the special case of zero length format spec, make\r
+ it equivalent to str(obj) */\r
+ if (format_spec_len == 0) {\r
+ result = STRINGLIB_TOSTR(obj);\r
+ goto done;\r
+ }\r
+\r
+ /* parse the format_spec */\r
+ if (!parse_internal_render_format_spec(format_spec,\r
+ format_spec_len,\r
+ &format, '\0', '>'))\r
+ goto done;\r
+\r
+ /* type conversion? */\r
+ switch (format.type) {\r
+ case '\0': /* No format code: like 'g', but with at least one decimal. */\r
+ case 'e':\r
+ case 'E':\r
+ case 'f':\r
+ case 'F':\r
+ case 'g':\r
+ case 'G':\r
+ case 'n':\r
+ case '%':\r
+ /* no conversion, already a float. do the formatting */\r
+ result = format_float_internal(obj, &format);\r
+ break;\r
+\r
+ default:\r
+ /* unknown */\r
+ unknown_presentation_type(format.type, obj->ob_type->tp_name);\r
+ goto done;\r
+ }\r
+\r
+done:\r
+ return result;\r
+}\r
+#endif /* FORMAT_FLOAT */\r
+\r
+#ifdef FORMAT_COMPLEX\r
+PyObject *\r
+FORMAT_COMPLEX(PyObject *obj,\r
+ STRINGLIB_CHAR *format_spec,\r
+ Py_ssize_t format_spec_len)\r
+{\r
+ PyObject *result = NULL;\r
+ InternalFormatSpec format;\r
+\r
+ /* check for the special case of zero length format spec, make\r
+ it equivalent to str(obj) */\r
+ if (format_spec_len == 0) {\r
+ result = STRINGLIB_TOSTR(obj);\r
+ goto done;\r
+ }\r
+\r
+ /* parse the format_spec */\r
+ if (!parse_internal_render_format_spec(format_spec,\r
+ format_spec_len,\r
+ &format, '\0', '>'))\r
+ goto done;\r
+\r
+ /* type conversion? */\r
+ switch (format.type) {\r
+ case '\0': /* No format code: like 'g', but with at least one decimal. */\r
+ case 'e':\r
+ case 'E':\r
+ case 'f':\r
+ case 'F':\r
+ case 'g':\r
+ case 'G':\r
+ case 'n':\r
+ /* no conversion, already a complex. do the formatting */\r
+ result = format_complex_internal(obj, &format);\r
+ break;\r
+\r
+ default:\r
+ /* unknown */\r
+ unknown_presentation_type(format.type, obj->ob_type->tp_name);\r
+ goto done;\r
+ }\r
+\r
+done:\r
+ return result;\r
+}\r
+#endif /* FORMAT_COMPLEX */\r
--- /dev/null
+/* stringlib: partition implementation */\r
+\r
+#ifndef STRINGLIB_PARTITION_H\r
+#define STRINGLIB_PARTITION_H\r
+\r
+#ifndef STRINGLIB_FASTSEARCH_H\r
+#error must include "stringlib/fastsearch.h" before including this module\r
+#endif\r
+\r
+Py_LOCAL_INLINE(PyObject*)\r
+stringlib_partition(PyObject* str_obj,\r
+ const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ PyObject* sep_obj,\r
+ const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)\r
+{\r
+ PyObject* out;\r
+ Py_ssize_t pos;\r
+\r
+ if (sep_len == 0) {\r
+ PyErr_SetString(PyExc_ValueError, "empty separator");\r
+ return NULL;\r
+ }\r
+\r
+ out = PyTuple_New(3);\r
+ if (!out)\r
+ return NULL;\r
+\r
+ pos = fastsearch(str, str_len, sep, sep_len, -1, FAST_SEARCH);\r
+\r
+ if (pos < 0) {\r
+#if STRINGLIB_MUTABLE\r
+ PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, str_len));\r
+ PyTuple_SET_ITEM(out, 1, STRINGLIB_NEW(NULL, 0));\r
+ PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(NULL, 0));\r
+#else\r
+ Py_INCREF(str_obj);\r
+ PyTuple_SET_ITEM(out, 0, (PyObject*) str_obj);\r
+ Py_INCREF(STRINGLIB_EMPTY);\r
+ PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY);\r
+ Py_INCREF(STRINGLIB_EMPTY);\r
+ PyTuple_SET_ITEM(out, 2, (PyObject*) STRINGLIB_EMPTY);\r
+#endif\r
+ return out;\r
+ }\r
+\r
+ PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, pos));\r
+ Py_INCREF(sep_obj);\r
+ PyTuple_SET_ITEM(out, 1, sep_obj);\r
+ pos += sep_len;\r
+ PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str + pos, str_len - pos));\r
+\r
+ if (PyErr_Occurred()) {\r
+ Py_DECREF(out);\r
+ return NULL;\r
+ }\r
+\r
+ return out;\r
+}\r
+\r
+Py_LOCAL_INLINE(PyObject*)\r
+stringlib_rpartition(PyObject* str_obj,\r
+ const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ PyObject* sep_obj,\r
+ const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)\r
+{\r
+ PyObject* out;\r
+ Py_ssize_t pos;\r
+\r
+ if (sep_len == 0) {\r
+ PyErr_SetString(PyExc_ValueError, "empty separator");\r
+ return NULL;\r
+ }\r
+\r
+ out = PyTuple_New(3);\r
+ if (!out)\r
+ return NULL;\r
+\r
+ pos = fastsearch(str, str_len, sep, sep_len, -1, FAST_RSEARCH);\r
+\r
+ if (pos < 0) {\r
+#if STRINGLIB_MUTABLE\r
+ PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(NULL, 0));\r
+ PyTuple_SET_ITEM(out, 1, STRINGLIB_NEW(NULL, 0));\r
+ PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str, str_len));\r
+#else\r
+ Py_INCREF(STRINGLIB_EMPTY);\r
+ PyTuple_SET_ITEM(out, 0, (PyObject*) STRINGLIB_EMPTY);\r
+ Py_INCREF(STRINGLIB_EMPTY);\r
+ PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY);\r
+ Py_INCREF(str_obj);\r
+ PyTuple_SET_ITEM(out, 2, (PyObject*) str_obj);\r
+#endif\r
+ return out;\r
+ }\r
+\r
+ PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, pos));\r
+ Py_INCREF(sep_obj);\r
+ PyTuple_SET_ITEM(out, 1, sep_obj);\r
+ pos += sep_len;\r
+ PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str + pos, str_len - pos));\r
+\r
+ if (PyErr_Occurred()) {\r
+ Py_DECREF(out);\r
+ return NULL;\r
+ }\r
+\r
+ return out;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/* stringlib: split implementation */\r
+\r
+#ifndef STRINGLIB_SPLIT_H\r
+#define STRINGLIB_SPLIT_H\r
+\r
+#ifndef STRINGLIB_FASTSEARCH_H\r
+#error must include "stringlib/fastsearch.h" before including this module\r
+#endif\r
+\r
+/* Overallocate the initial list to reduce the number of reallocs for small\r
+ split sizes. Eg, "A A A A A A A A A A".split() (10 elements) has three\r
+ resizes, to sizes 4, 8, then 16. Most observed string splits are for human\r
+ text (roughly 11 words per line) and field delimited data (usually 1-10\r
+ fields). For large strings the split algorithms are bandwidth limited\r
+ so increasing the preallocation likely will not improve things.*/\r
+\r
+#define MAX_PREALLOC 12\r
+\r
+/* 5 splits gives 6 elements */\r
+#define PREALLOC_SIZE(maxsplit) \\r
+ (maxsplit >= MAX_PREALLOC ? MAX_PREALLOC : maxsplit+1)\r
+\r
+#define SPLIT_APPEND(data, left, right) \\r
+ sub = STRINGLIB_NEW((data) + (left), \\r
+ (right) - (left)); \\r
+ if (sub == NULL) \\r
+ goto onError; \\r
+ if (PyList_Append(list, sub)) { \\r
+ Py_DECREF(sub); \\r
+ goto onError; \\r
+ } \\r
+ else \\r
+ Py_DECREF(sub);\r
+\r
+#define SPLIT_ADD(data, left, right) { \\r
+ sub = STRINGLIB_NEW((data) + (left), \\r
+ (right) - (left)); \\r
+ if (sub == NULL) \\r
+ goto onError; \\r
+ if (count < MAX_PREALLOC) { \\r
+ PyList_SET_ITEM(list, count, sub); \\r
+ } else { \\r
+ if (PyList_Append(list, sub)) { \\r
+ Py_DECREF(sub); \\r
+ goto onError; \\r
+ } \\r
+ else \\r
+ Py_DECREF(sub); \\r
+ } \\r
+ count++; }\r
+\r
+\r
+/* Always force the list to the expected size. */\r
+#define FIX_PREALLOC_SIZE(list) Py_SIZE(list) = count\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+stringlib_split_whitespace(PyObject* str_obj,\r
+ const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ Py_ssize_t i, j, count=0;\r
+ PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));\r
+ PyObject *sub;\r
+\r
+ if (list == NULL)\r
+ return NULL;\r
+\r
+ i = j = 0;\r
+ while (maxcount-- > 0) {\r
+ while (i < str_len && STRINGLIB_ISSPACE(str[i]))\r
+ i++;\r
+ if (i == str_len) break;\r
+ j = i; i++;\r
+ while (i < str_len && !STRINGLIB_ISSPACE(str[i]))\r
+ i++;\r
+#ifndef STRINGLIB_MUTABLE\r
+ if (j == 0 && i == str_len && STRINGLIB_CHECK_EXACT(str_obj)) {\r
+ /* No whitespace in str_obj, so just use it as list[0] */\r
+ Py_INCREF(str_obj);\r
+ PyList_SET_ITEM(list, 0, (PyObject *)str_obj);\r
+ count++;\r
+ break;\r
+ }\r
+#endif\r
+ SPLIT_ADD(str, j, i);\r
+ }\r
+\r
+ if (i < str_len) {\r
+ /* Only occurs when maxcount was reached */\r
+ /* Skip any remaining whitespace and copy to end of string */\r
+ while (i < str_len && STRINGLIB_ISSPACE(str[i]))\r
+ i++;\r
+ if (i != str_len)\r
+ SPLIT_ADD(str, i, str_len);\r
+ }\r
+ FIX_PREALLOC_SIZE(list);\r
+ return list;\r
+\r
+ onError:\r
+ Py_DECREF(list);\r
+ return NULL;\r
+}\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+stringlib_split_char(PyObject* str_obj,\r
+ const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ const STRINGLIB_CHAR ch,\r
+ Py_ssize_t maxcount)\r
+{\r
+ Py_ssize_t i, j, count=0;\r
+ PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));\r
+ PyObject *sub;\r
+\r
+ if (list == NULL)\r
+ return NULL;\r
+\r
+ i = j = 0;\r
+ while ((j < str_len) && (maxcount-- > 0)) {\r
+ for(; j < str_len; j++) {\r
+ /* I found that using memchr makes no difference */\r
+ if (str[j] == ch) {\r
+ SPLIT_ADD(str, i, j);\r
+ i = j = j + 1;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+#ifndef STRINGLIB_MUTABLE\r
+ if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) {\r
+ /* ch not in str_obj, so just use str_obj as list[0] */\r
+ Py_INCREF(str_obj);\r
+ PyList_SET_ITEM(list, 0, (PyObject *)str_obj);\r
+ count++;\r
+ } else\r
+#endif\r
+ if (i <= str_len) {\r
+ SPLIT_ADD(str, i, str_len);\r
+ }\r
+ FIX_PREALLOC_SIZE(list);\r
+ return list;\r
+\r
+ onError:\r
+ Py_DECREF(list);\r
+ return NULL;\r
+}\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+stringlib_split(PyObject* str_obj,\r
+ const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ const STRINGLIB_CHAR* sep, Py_ssize_t sep_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ Py_ssize_t i, j, pos, count=0;\r
+ PyObject *list, *sub;\r
+\r
+ if (sep_len == 0) {\r
+ PyErr_SetString(PyExc_ValueError, "empty separator");\r
+ return NULL;\r
+ }\r
+ else if (sep_len == 1)\r
+ return stringlib_split_char(str_obj, str, str_len, sep[0], maxcount);\r
+\r
+ list = PyList_New(PREALLOC_SIZE(maxcount));\r
+ if (list == NULL)\r
+ return NULL;\r
+\r
+ i = j = 0;\r
+ while (maxcount-- > 0) {\r
+ pos = fastsearch(str+i, str_len-i, sep, sep_len, -1, FAST_SEARCH);\r
+ if (pos < 0)\r
+ break;\r
+ j = i + pos;\r
+ SPLIT_ADD(str, i, j);\r
+ i = j + sep_len;\r
+ }\r
+#ifndef STRINGLIB_MUTABLE\r
+ if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) {\r
+ /* No match in str_obj, so just use it as list[0] */\r
+ Py_INCREF(str_obj);\r
+ PyList_SET_ITEM(list, 0, (PyObject *)str_obj);\r
+ count++;\r
+ } else\r
+#endif\r
+ {\r
+ SPLIT_ADD(str, i, str_len);\r
+ }\r
+ FIX_PREALLOC_SIZE(list);\r
+ return list;\r
+\r
+ onError:\r
+ Py_DECREF(list);\r
+ return NULL;\r
+}\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+stringlib_rsplit_whitespace(PyObject* str_obj,\r
+ const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ Py_ssize_t i, j, count=0;\r
+ PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));\r
+ PyObject *sub;\r
+\r
+ if (list == NULL)\r
+ return NULL;\r
+\r
+ i = j = str_len - 1;\r
+ while (maxcount-- > 0) {\r
+ while (i >= 0 && STRINGLIB_ISSPACE(str[i]))\r
+ i--;\r
+ if (i < 0) break;\r
+ j = i; i--;\r
+ while (i >= 0 && !STRINGLIB_ISSPACE(str[i]))\r
+ i--;\r
+#ifndef STRINGLIB_MUTABLE\r
+ if (j == str_len - 1 && i < 0 && STRINGLIB_CHECK_EXACT(str_obj)) {\r
+ /* No whitespace in str_obj, so just use it as list[0] */\r
+ Py_INCREF(str_obj);\r
+ PyList_SET_ITEM(list, 0, (PyObject *)str_obj);\r
+ count++;\r
+ break;\r
+ }\r
+#endif\r
+ SPLIT_ADD(str, i + 1, j + 1);\r
+ }\r
+\r
+ if (i >= 0) {\r
+ /* Only occurs when maxcount was reached */\r
+ /* Skip any remaining whitespace and copy to beginning of string */\r
+ while (i >= 0 && STRINGLIB_ISSPACE(str[i]))\r
+ i--;\r
+ if (i >= 0)\r
+ SPLIT_ADD(str, 0, i + 1);\r
+ }\r
+ FIX_PREALLOC_SIZE(list);\r
+ if (PyList_Reverse(list) < 0)\r
+ goto onError;\r
+ return list;\r
+\r
+ onError:\r
+ Py_DECREF(list);\r
+ return NULL;\r
+}\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+stringlib_rsplit_char(PyObject* str_obj,\r
+ const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ const STRINGLIB_CHAR ch,\r
+ Py_ssize_t maxcount)\r
+{\r
+ Py_ssize_t i, j, count=0;\r
+ PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));\r
+ PyObject *sub;\r
+\r
+ if (list == NULL)\r
+ return NULL;\r
+\r
+ i = j = str_len - 1;\r
+ while ((i >= 0) && (maxcount-- > 0)) {\r
+ for(; i >= 0; i--) {\r
+ if (str[i] == ch) {\r
+ SPLIT_ADD(str, i + 1, j + 1);\r
+ j = i = i - 1;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+#ifndef STRINGLIB_MUTABLE\r
+ if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) {\r
+ /* ch not in str_obj, so just use str_obj as list[0] */\r
+ Py_INCREF(str_obj);\r
+ PyList_SET_ITEM(list, 0, (PyObject *)str_obj);\r
+ count++;\r
+ } else\r
+#endif\r
+ if (j >= -1) {\r
+ SPLIT_ADD(str, 0, j + 1);\r
+ }\r
+ FIX_PREALLOC_SIZE(list);\r
+ if (PyList_Reverse(list) < 0)\r
+ goto onError;\r
+ return list;\r
+\r
+ onError:\r
+ Py_DECREF(list);\r
+ return NULL;\r
+}\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+stringlib_rsplit(PyObject* str_obj,\r
+ const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ const STRINGLIB_CHAR* sep, Py_ssize_t sep_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ Py_ssize_t j, pos, count=0;\r
+ PyObject *list, *sub;\r
+\r
+ if (sep_len == 0) {\r
+ PyErr_SetString(PyExc_ValueError, "empty separator");\r
+ return NULL;\r
+ }\r
+ else if (sep_len == 1)\r
+ return stringlib_rsplit_char(str_obj, str, str_len, sep[0], maxcount);\r
+\r
+ list = PyList_New(PREALLOC_SIZE(maxcount));\r
+ if (list == NULL)\r
+ return NULL;\r
+\r
+ j = str_len;\r
+ while (maxcount-- > 0) {\r
+ pos = fastsearch(str, j, sep, sep_len, -1, FAST_RSEARCH);\r
+ if (pos < 0)\r
+ break;\r
+ SPLIT_ADD(str, pos + sep_len, j);\r
+ j = pos;\r
+ }\r
+#ifndef STRINGLIB_MUTABLE\r
+ if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) {\r
+ /* No match in str_obj, so just use it as list[0] */\r
+ Py_INCREF(str_obj);\r
+ PyList_SET_ITEM(list, 0, (PyObject *)str_obj);\r
+ count++;\r
+ } else\r
+#endif\r
+ {\r
+ SPLIT_ADD(str, 0, j);\r
+ }\r
+ FIX_PREALLOC_SIZE(list);\r
+ if (PyList_Reverse(list) < 0)\r
+ goto onError;\r
+ return list;\r
+\r
+ onError:\r
+ Py_DECREF(list);\r
+ return NULL;\r
+}\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+stringlib_splitlines(PyObject* str_obj,\r
+ const STRINGLIB_CHAR* str, Py_ssize_t str_len,\r
+ int keepends)\r
+{\r
+ /* This does not use the preallocated list because splitlines is\r
+ usually run with hundreds of newlines. The overhead of\r
+ switching between PyList_SET_ITEM and append causes about a\r
+ 2-3% slowdown for that common case. A smarter implementation\r
+ could move the if check out, so the SET_ITEMs are done first\r
+ and the appends only done when the prealloc buffer is full.\r
+ That's too much work for little gain.*/\r
+\r
+ register Py_ssize_t i;\r
+ register Py_ssize_t j;\r
+ PyObject *list = PyList_New(0);\r
+ PyObject *sub;\r
+\r
+ if (list == NULL)\r
+ return NULL;\r
+\r
+ for (i = j = 0; i < str_len; ) {\r
+ Py_ssize_t eol;\r
+\r
+ /* Find a line and append it */\r
+ while (i < str_len && !STRINGLIB_ISLINEBREAK(str[i]))\r
+ i++;\r
+\r
+ /* Skip the line break reading CRLF as one line break */\r
+ eol = i;\r
+ if (i < str_len) {\r
+ if (str[i] == '\r' && i + 1 < str_len && str[i+1] == '\n')\r
+ i += 2;\r
+ else\r
+ i++;\r
+ if (keepends)\r
+ eol = i;\r
+ }\r
+#ifndef STRINGLIB_MUTABLE\r
+ if (j == 0 && eol == str_len && STRINGLIB_CHECK_EXACT(str_obj)) {\r
+ /* No linebreak in str_obj, so just use it as list[0] */\r
+ if (PyList_Append(list, str_obj))\r
+ goto onError;\r
+ break;\r
+ }\r
+#endif\r
+ SPLIT_APPEND(str, j, eol);\r
+ j = i;\r
+ }\r
+ return list;\r
+\r
+ onError:\r
+ Py_DECREF(list);\r
+ return NULL;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ string_format.h -- implementation of string.format().\r
+\r
+ It uses the Objects/stringlib conventions, so that it can be\r
+ compiled for both unicode and string objects.\r
+*/\r
+\r
+\r
+/* Defines for Python 2.6 compatibility */\r
+#if PY_VERSION_HEX < 0x03000000\r
+#define PyLong_FromSsize_t _PyLong_FromSsize_t\r
+#endif\r
+\r
+/* Defines for more efficiently reallocating the string buffer */\r
+#define INITIAL_SIZE_INCREMENT 100\r
+#define SIZE_MULTIPLIER 2\r
+#define MAX_SIZE_INCREMENT 3200\r
+\r
+\r
+/************************************************************************/\r
+/*********** Global data structures and forward declarations *********/\r
+/************************************************************************/\r
+\r
+/*\r
+ A SubString consists of the characters between two string or\r
+ unicode pointers.\r
+*/\r
+typedef struct {\r
+ STRINGLIB_CHAR *ptr;\r
+ STRINGLIB_CHAR *end;\r
+} SubString;\r
+\r
+\r
+typedef enum {\r
+ ANS_INIT,\r
+ ANS_AUTO,\r
+ ANS_MANUAL\r
+} AutoNumberState; /* Keep track if we're auto-numbering fields */\r
+\r
+/* Keeps track of our auto-numbering state, and which number field we're on */\r
+typedef struct {\r
+ AutoNumberState an_state;\r
+ int an_field_number;\r
+} AutoNumber;\r
+\r
+\r
+/* forward declaration for recursion */\r
+static PyObject *\r
+build_string(SubString *input, PyObject *args, PyObject *kwargs,\r
+ int recursion_depth, AutoNumber *auto_number);\r
+\r
+\r
+\r
+/************************************************************************/\r
+/************************** Utility functions ************************/\r
+/************************************************************************/\r
+\r
+static void\r
+AutoNumber_Init(AutoNumber *auto_number)\r
+{\r
+ auto_number->an_state = ANS_INIT;\r
+ auto_number->an_field_number = 0;\r
+}\r
+\r
+/* fill in a SubString from a pointer and length */\r
+Py_LOCAL_INLINE(void)\r
+SubString_init(SubString *str, STRINGLIB_CHAR *p, Py_ssize_t len)\r
+{\r
+ str->ptr = p;\r
+ if (p == NULL)\r
+ str->end = NULL;\r
+ else\r
+ str->end = str->ptr + len;\r
+}\r
+\r
+/* return a new string. if str->ptr is NULL, return None */\r
+Py_LOCAL_INLINE(PyObject *)\r
+SubString_new_object(SubString *str)\r
+{\r
+ if (str->ptr == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ return STRINGLIB_NEW(str->ptr, str->end - str->ptr);\r
+}\r
+\r
+/* return a new string. if str->ptr is NULL, return None */\r
+Py_LOCAL_INLINE(PyObject *)\r
+SubString_new_object_or_empty(SubString *str)\r
+{\r
+ if (str->ptr == NULL) {\r
+ return STRINGLIB_NEW(NULL, 0);\r
+ }\r
+ return STRINGLIB_NEW(str->ptr, str->end - str->ptr);\r
+}\r
+\r
+/* Return 1 if an error has been detected switching between automatic\r
+ field numbering and manual field specification, else return 0. Set\r
+ ValueError on error. */\r
+static int\r
+autonumber_state_error(AutoNumberState state, int field_name_is_empty)\r
+{\r
+ if (state == ANS_MANUAL) {\r
+ if (field_name_is_empty) {\r
+ PyErr_SetString(PyExc_ValueError, "cannot switch from "\r
+ "manual field specification to "\r
+ "automatic field numbering");\r
+ return 1;\r
+ }\r
+ }\r
+ else {\r
+ if (!field_name_is_empty) {\r
+ PyErr_SetString(PyExc_ValueError, "cannot switch from "\r
+ "automatic field numbering to "\r
+ "manual field specification");\r
+ return 1;\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+\r
+/************************************************************************/\r
+/*********** Output string management functions ****************/\r
+/************************************************************************/\r
+\r
+typedef struct {\r
+ STRINGLIB_CHAR *ptr;\r
+ STRINGLIB_CHAR *end;\r
+ PyObject *obj;\r
+ Py_ssize_t size_increment;\r
+} OutputString;\r
+\r
+/* initialize an OutputString object, reserving size characters */\r
+static int\r
+output_initialize(OutputString *output, Py_ssize_t size)\r
+{\r
+ output->obj = STRINGLIB_NEW(NULL, size);\r
+ if (output->obj == NULL)\r
+ return 0;\r
+\r
+ output->ptr = STRINGLIB_STR(output->obj);\r
+ output->end = STRINGLIB_LEN(output->obj) + output->ptr;\r
+ output->size_increment = INITIAL_SIZE_INCREMENT;\r
+\r
+ return 1;\r
+}\r
+\r
+/*\r
+ output_extend reallocates the output string buffer.\r
+ It returns a status: 0 for a failed reallocation,\r
+ 1 for success.\r
+*/\r
+\r
+static int\r
+output_extend(OutputString *output, Py_ssize_t count)\r
+{\r
+ STRINGLIB_CHAR *startptr = STRINGLIB_STR(output->obj);\r
+ Py_ssize_t curlen = output->ptr - startptr;\r
+ Py_ssize_t maxlen = curlen + count + output->size_increment;\r
+\r
+ if (STRINGLIB_RESIZE(&output->obj, maxlen) < 0)\r
+ return 0;\r
+ startptr = STRINGLIB_STR(output->obj);\r
+ output->ptr = startptr + curlen;\r
+ output->end = startptr + maxlen;\r
+ if (output->size_increment < MAX_SIZE_INCREMENT)\r
+ output->size_increment *= SIZE_MULTIPLIER;\r
+ return 1;\r
+}\r
+\r
+/*\r
+ output_data dumps characters into our output string\r
+ buffer.\r
+\r
+ In some cases, it has to reallocate the string.\r
+\r
+ It returns a status: 0 for a failed reallocation,\r
+ 1 for success.\r
+*/\r
+static int\r
+output_data(OutputString *output, const STRINGLIB_CHAR *s, Py_ssize_t count)\r
+{\r
+ if ((count > output->end - output->ptr) && !output_extend(output, count))\r
+ return 0;\r
+ memcpy(output->ptr, s, count * sizeof(STRINGLIB_CHAR));\r
+ output->ptr += count;\r
+ return 1;\r
+}\r
+\r
+/************************************************************************/\r
+/*********** Format string parsing -- integers and identifiers *********/\r
+/************************************************************************/\r
+\r
+static Py_ssize_t\r
+get_integer(const SubString *str)\r
+{\r
+ Py_ssize_t accumulator = 0;\r
+ Py_ssize_t digitval;\r
+ STRINGLIB_CHAR *p;\r
+\r
+ /* empty string is an error */\r
+ if (str->ptr >= str->end)\r
+ return -1;\r
+\r
+ for (p = str->ptr; p < str->end; p++) {\r
+ digitval = STRINGLIB_TODECIMAL(*p);\r
+ if (digitval < 0)\r
+ return -1;\r
+ /*\r
+ Detect possible overflow before it happens:\r
+\r
+ accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if\r
+ accumulator > (PY_SSIZE_T_MAX - digitval) / 10.\r
+ */\r
+ if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "Too many decimal digits in format string");\r
+ return -1;\r
+ }\r
+ accumulator = accumulator * 10 + digitval;\r
+ }\r
+ return accumulator;\r
+}\r
+\r
+/************************************************************************/\r
+/******** Functions to get field objects and specification strings ******/\r
+/************************************************************************/\r
+\r
+/* do the equivalent of obj.name */\r
+static PyObject *\r
+getattr(PyObject *obj, SubString *name)\r
+{\r
+ PyObject *newobj;\r
+ PyObject *str = SubString_new_object(name);\r
+ if (str == NULL)\r
+ return NULL;\r
+ newobj = PyObject_GetAttr(obj, str);\r
+ Py_DECREF(str);\r
+ return newobj;\r
+}\r
+\r
+/* do the equivalent of obj[idx], where obj is a sequence */\r
+static PyObject *\r
+getitem_sequence(PyObject *obj, Py_ssize_t idx)\r
+{\r
+ return PySequence_GetItem(obj, idx);\r
+}\r
+\r
+/* do the equivalent of obj[idx], where obj is not a sequence */\r
+static PyObject *\r
+getitem_idx(PyObject *obj, Py_ssize_t idx)\r
+{\r
+ PyObject *newobj;\r
+ PyObject *idx_obj = PyLong_FromSsize_t(idx);\r
+ if (idx_obj == NULL)\r
+ return NULL;\r
+ newobj = PyObject_GetItem(obj, idx_obj);\r
+ Py_DECREF(idx_obj);\r
+ return newobj;\r
+}\r
+\r
+/* do the equivalent of obj[name] */\r
+static PyObject *\r
+getitem_str(PyObject *obj, SubString *name)\r
+{\r
+ PyObject *newobj;\r
+ PyObject *str = SubString_new_object(name);\r
+ if (str == NULL)\r
+ return NULL;\r
+ newobj = PyObject_GetItem(obj, str);\r
+ Py_DECREF(str);\r
+ return newobj;\r
+}\r
+\r
+typedef struct {\r
+ /* the entire string we're parsing. we assume that someone else\r
+ is managing its lifetime, and that it will exist for the\r
+ lifetime of the iterator. can be empty */\r
+ SubString str;\r
+\r
+ /* pointer to where we are inside field_name */\r
+ STRINGLIB_CHAR *ptr;\r
+} FieldNameIterator;\r
+\r
+\r
+static int\r
+FieldNameIterator_init(FieldNameIterator *self, STRINGLIB_CHAR *ptr,\r
+ Py_ssize_t len)\r
+{\r
+ SubString_init(&self->str, ptr, len);\r
+ self->ptr = self->str.ptr;\r
+ return 1;\r
+}\r
+\r
+static int\r
+_FieldNameIterator_attr(FieldNameIterator *self, SubString *name)\r
+{\r
+ STRINGLIB_CHAR c;\r
+\r
+ name->ptr = self->ptr;\r
+\r
+ /* return everything until '.' or '[' */\r
+ while (self->ptr < self->str.end) {\r
+ switch (c = *self->ptr++) {\r
+ case '[':\r
+ case '.':\r
+ /* backup so that we this character will be seen next time */\r
+ self->ptr--;\r
+ break;\r
+ default:\r
+ continue;\r
+ }\r
+ break;\r
+ }\r
+ /* end of string is okay */\r
+ name->end = self->ptr;\r
+ return 1;\r
+}\r
+\r
+static int\r
+_FieldNameIterator_item(FieldNameIterator *self, SubString *name)\r
+{\r
+ int bracket_seen = 0;\r
+ STRINGLIB_CHAR c;\r
+\r
+ name->ptr = self->ptr;\r
+\r
+ /* return everything until ']' */\r
+ while (self->ptr < self->str.end) {\r
+ switch (c = *self->ptr++) {\r
+ case ']':\r
+ bracket_seen = 1;\r
+ break;\r
+ default:\r
+ continue;\r
+ }\r
+ break;\r
+ }\r
+ /* make sure we ended with a ']' */\r
+ if (!bracket_seen) {\r
+ PyErr_SetString(PyExc_ValueError, "Missing ']' in format string");\r
+ return 0;\r
+ }\r
+\r
+ /* end of string is okay */\r
+ /* don't include the ']' */\r
+ name->end = self->ptr-1;\r
+ return 1;\r
+}\r
+\r
+/* returns 0 on error, 1 on non-error termination, and 2 if it returns a value */\r
+static int\r
+FieldNameIterator_next(FieldNameIterator *self, int *is_attribute,\r
+ Py_ssize_t *name_idx, SubString *name)\r
+{\r
+ /* check at end of input */\r
+ if (self->ptr >= self->str.end)\r
+ return 1;\r
+\r
+ switch (*self->ptr++) {\r
+ case '.':\r
+ *is_attribute = 1;\r
+ if (_FieldNameIterator_attr(self, name) == 0)\r
+ return 0;\r
+ *name_idx = -1;\r
+ break;\r
+ case '[':\r
+ *is_attribute = 0;\r
+ if (_FieldNameIterator_item(self, name) == 0)\r
+ return 0;\r
+ *name_idx = get_integer(name);\r
+ if (*name_idx == -1 && PyErr_Occurred())\r
+ return 0;\r
+ break;\r
+ default:\r
+ /* Invalid character follows ']' */\r
+ PyErr_SetString(PyExc_ValueError, "Only '.' or '[' may "\r
+ "follow ']' in format field specifier");\r
+ return 0;\r
+ }\r
+\r
+ /* empty string is an error */\r
+ if (name->ptr == name->end) {\r
+ PyErr_SetString(PyExc_ValueError, "Empty attribute in format string");\r
+ return 0;\r
+ }\r
+\r
+ return 2;\r
+}\r
+\r
+\r
+/* input: field_name\r
+ output: 'first' points to the part before the first '[' or '.'\r
+ 'first_idx' is -1 if 'first' is not an integer, otherwise\r
+ it's the value of first converted to an integer\r
+ 'rest' is an iterator to return the rest\r
+*/\r
+static int\r
+field_name_split(STRINGLIB_CHAR *ptr, Py_ssize_t len, SubString *first,\r
+ Py_ssize_t *first_idx, FieldNameIterator *rest,\r
+ AutoNumber *auto_number)\r
+{\r
+ STRINGLIB_CHAR c;\r
+ STRINGLIB_CHAR *p = ptr;\r
+ STRINGLIB_CHAR *end = ptr + len;\r
+ int field_name_is_empty;\r
+ int using_numeric_index;\r
+\r
+ /* find the part up until the first '.' or '[' */\r
+ while (p < end) {\r
+ switch (c = *p++) {\r
+ case '[':\r
+ case '.':\r
+ /* backup so that we this character is available to the\r
+ "rest" iterator */\r
+ p--;\r
+ break;\r
+ default:\r
+ continue;\r
+ }\r
+ break;\r
+ }\r
+\r
+ /* set up the return values */\r
+ SubString_init(first, ptr, p - ptr);\r
+ FieldNameIterator_init(rest, p, end - p);\r
+\r
+ /* see if "first" is an integer, in which case it's used as an index */\r
+ *first_idx = get_integer(first);\r
+ if (*first_idx == -1 && PyErr_Occurred())\r
+ return 0;\r
+\r
+ field_name_is_empty = first->ptr >= first->end;\r
+\r
+ /* If the field name is omitted or if we have a numeric index\r
+ specified, then we're doing numeric indexing into args. */\r
+ using_numeric_index = field_name_is_empty || *first_idx != -1;\r
+\r
+ /* We always get here exactly one time for each field we're\r
+ processing. And we get here in field order (counting by left\r
+ braces). So this is the perfect place to handle automatic field\r
+ numbering if the field name is omitted. */\r
+\r
+ /* Check if we need to do the auto-numbering. It's not needed if\r
+ we're called from string.Format routines, because it's handled\r
+ in that class by itself. */\r
+ if (auto_number) {\r
+ /* Initialize our auto numbering state if this is the first\r
+ time we're either auto-numbering or manually numbering. */\r
+ if (auto_number->an_state == ANS_INIT && using_numeric_index)\r
+ auto_number->an_state = field_name_is_empty ?\r
+ ANS_AUTO : ANS_MANUAL;\r
+\r
+ /* Make sure our state is consistent with what we're doing\r
+ this time through. Only check if we're using a numeric\r
+ index. */\r
+ if (using_numeric_index)\r
+ if (autonumber_state_error(auto_number->an_state,\r
+ field_name_is_empty))\r
+ return 0;\r
+ /* Zero length field means we want to do auto-numbering of the\r
+ fields. */\r
+ if (field_name_is_empty)\r
+ *first_idx = (auto_number->an_field_number)++;\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+\r
+/*\r
+ get_field_object returns the object inside {}, before the\r
+ format_spec. It handles getindex and getattr lookups and consumes\r
+ the entire input string.\r
+*/\r
+static PyObject *\r
+get_field_object(SubString *input, PyObject *args, PyObject *kwargs,\r
+ AutoNumber *auto_number)\r
+{\r
+ PyObject *obj = NULL;\r
+ int ok;\r
+ int is_attribute;\r
+ SubString name;\r
+ SubString first;\r
+ Py_ssize_t index;\r
+ FieldNameIterator rest;\r
+\r
+ if (!field_name_split(input->ptr, input->end - input->ptr, &first,\r
+ &index, &rest, auto_number)) {\r
+ goto error;\r
+ }\r
+\r
+ if (index == -1) {\r
+ /* look up in kwargs */\r
+ PyObject *key = SubString_new_object(&first);\r
+ if (key == NULL)\r
+ goto error;\r
+ if ((kwargs == NULL) || (obj = PyDict_GetItem(kwargs, key)) == NULL) {\r
+ PyErr_SetObject(PyExc_KeyError, key);\r
+ Py_DECREF(key);\r
+ goto error;\r
+ }\r
+ Py_DECREF(key);\r
+ Py_INCREF(obj);\r
+ }\r
+ else {\r
+ /* look up in args */\r
+ obj = PySequence_GetItem(args, index);\r
+ if (obj == NULL)\r
+ goto error;\r
+ }\r
+\r
+ /* iterate over the rest of the field_name */\r
+ while ((ok = FieldNameIterator_next(&rest, &is_attribute, &index,\r
+ &name)) == 2) {\r
+ PyObject *tmp;\r
+\r
+ if (is_attribute)\r
+ /* getattr lookup "." */\r
+ tmp = getattr(obj, &name);\r
+ else\r
+ /* getitem lookup "[]" */\r
+ if (index == -1)\r
+ tmp = getitem_str(obj, &name);\r
+ else\r
+ if (PySequence_Check(obj))\r
+ tmp = getitem_sequence(obj, index);\r
+ else\r
+ /* not a sequence */\r
+ tmp = getitem_idx(obj, index);\r
+ if (tmp == NULL)\r
+ goto error;\r
+\r
+ /* assign to obj */\r
+ Py_DECREF(obj);\r
+ obj = tmp;\r
+ }\r
+ /* end of iterator, this is the non-error case */\r
+ if (ok == 1)\r
+ return obj;\r
+error:\r
+ Py_XDECREF(obj);\r
+ return NULL;\r
+}\r
+\r
+/************************************************************************/\r
+/***************** Field rendering functions **************************/\r
+/************************************************************************/\r
+\r
+/*\r
+ render_field() is the main function in this section. It takes the\r
+ field object and field specification string generated by\r
+ get_field_and_spec, and renders the field into the output string.\r
+\r
+ render_field calls fieldobj.__format__(format_spec) method, and\r
+ appends to the output.\r
+*/\r
+static int\r
+render_field(PyObject *fieldobj, SubString *format_spec, OutputString *output)\r
+{\r
+ int ok = 0;\r
+ PyObject *result = NULL;\r
+ PyObject *format_spec_object = NULL;\r
+ PyObject *(*formatter)(PyObject *, STRINGLIB_CHAR *, Py_ssize_t) = NULL;\r
+ STRINGLIB_CHAR* format_spec_start = format_spec->ptr ?\r
+ format_spec->ptr : NULL;\r
+ Py_ssize_t format_spec_len = format_spec->ptr ?\r
+ format_spec->end - format_spec->ptr : 0;\r
+\r
+ /* If we know the type exactly, skip the lookup of __format__ and just\r
+ call the formatter directly. */\r
+#if STRINGLIB_IS_UNICODE\r
+ if (PyUnicode_CheckExact(fieldobj))\r
+ formatter = _PyUnicode_FormatAdvanced;\r
+ /* Unfortunately, there's a problem with checking for int, long,\r
+ and float here. If we're being included as unicode, their\r
+ formatters expect string format_spec args. For now, just skip\r
+ this optimization for unicode. This could be fixed, but it's a\r
+ hassle. */\r
+#else\r
+ if (PyString_CheckExact(fieldobj))\r
+ formatter = _PyBytes_FormatAdvanced;\r
+ else if (PyInt_CheckExact(fieldobj))\r
+ formatter =_PyInt_FormatAdvanced;\r
+ else if (PyLong_CheckExact(fieldobj))\r
+ formatter =_PyLong_FormatAdvanced;\r
+ else if (PyFloat_CheckExact(fieldobj))\r
+ formatter = _PyFloat_FormatAdvanced;\r
+#endif\r
+\r
+ if (formatter) {\r
+ /* we know exactly which formatter will be called when __format__ is\r
+ looked up, so call it directly, instead. */\r
+ result = formatter(fieldobj, format_spec_start, format_spec_len);\r
+ }\r
+ else {\r
+ /* We need to create an object out of the pointers we have, because\r
+ __format__ takes a string/unicode object for format_spec. */\r
+ format_spec_object = STRINGLIB_NEW(format_spec_start,\r
+ format_spec_len);\r
+ if (format_spec_object == NULL)\r
+ goto done;\r
+\r
+ result = PyObject_Format(fieldobj, format_spec_object);\r
+ }\r
+ if (result == NULL)\r
+ goto done;\r
+\r
+#if PY_VERSION_HEX >= 0x03000000\r
+ assert(PyUnicode_Check(result));\r
+#else\r
+ assert(PyString_Check(result) || PyUnicode_Check(result));\r
+\r
+ /* Convert result to our type. We could be str, and result could\r
+ be unicode */\r
+ {\r
+ PyObject *tmp = STRINGLIB_TOSTR(result);\r
+ if (tmp == NULL)\r
+ goto done;\r
+ Py_DECREF(result);\r
+ result = tmp;\r
+ }\r
+#endif\r
+\r
+ ok = output_data(output,\r
+ STRINGLIB_STR(result), STRINGLIB_LEN(result));\r
+done:\r
+ Py_XDECREF(format_spec_object);\r
+ Py_XDECREF(result);\r
+ return ok;\r
+}\r
+\r
+static int\r
+parse_field(SubString *str, SubString *field_name, SubString *format_spec,\r
+ STRINGLIB_CHAR *conversion)\r
+{\r
+ /* Note this function works if the field name is zero length,\r
+ which is good. Zero length field names are handled later, in\r
+ field_name_split. */\r
+\r
+ STRINGLIB_CHAR c = 0;\r
+\r
+ /* initialize these, as they may be empty */\r
+ *conversion = '\0';\r
+ SubString_init(format_spec, NULL, 0);\r
+\r
+ /* Search for the field name. it's terminated by the end of\r
+ the string, or a ':' or '!' */\r
+ field_name->ptr = str->ptr;\r
+ while (str->ptr < str->end) {\r
+ switch (c = *(str->ptr++)) {\r
+ case ':':\r
+ case '!':\r
+ break;\r
+ default:\r
+ continue;\r
+ }\r
+ break;\r
+ }\r
+\r
+ if (c == '!' || c == ':') {\r
+ /* we have a format specifier and/or a conversion */\r
+ /* don't include the last character */\r
+ field_name->end = str->ptr-1;\r
+\r
+ /* the format specifier is the rest of the string */\r
+ format_spec->ptr = str->ptr;\r
+ format_spec->end = str->end;\r
+\r
+ /* see if there's a conversion specifier */\r
+ if (c == '!') {\r
+ /* there must be another character present */\r
+ if (format_spec->ptr >= format_spec->end) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "end of format while looking for conversion "\r
+ "specifier");\r
+ return 0;\r
+ }\r
+ *conversion = *(format_spec->ptr++);\r
+\r
+ /* if there is another character, it must be a colon */\r
+ if (format_spec->ptr < format_spec->end) {\r
+ c = *(format_spec->ptr++);\r
+ if (c != ':') {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "expected ':' after format specifier");\r
+ return 0;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ /* end of string, there's no format_spec or conversion */\r
+ field_name->end = str->ptr;\r
+\r
+ return 1;\r
+}\r
+\r
+/************************************************************************/\r
+/******* Output string allocation and escape-to-markup processing ******/\r
+/************************************************************************/\r
+\r
+/* MarkupIterator breaks the string into pieces of either literal\r
+ text, or things inside {} that need to be marked up. it is\r
+ designed to make it easy to wrap a Python iterator around it, for\r
+ use with the Formatter class */\r
+\r
+typedef struct {\r
+ SubString str;\r
+} MarkupIterator;\r
+\r
+static int\r
+MarkupIterator_init(MarkupIterator *self, STRINGLIB_CHAR *ptr, Py_ssize_t len)\r
+{\r
+ SubString_init(&self->str, ptr, len);\r
+ return 1;\r
+}\r
+\r
+/* returns 0 on error, 1 on non-error termination, and 2 if it got a\r
+ string (or something to be expanded) */\r
+static int\r
+MarkupIterator_next(MarkupIterator *self, SubString *literal,\r
+ int *field_present, SubString *field_name,\r
+ SubString *format_spec, STRINGLIB_CHAR *conversion,\r
+ int *format_spec_needs_expanding)\r
+{\r
+ int at_end;\r
+ STRINGLIB_CHAR c = 0;\r
+ STRINGLIB_CHAR *start;\r
+ int count;\r
+ Py_ssize_t len;\r
+ int markup_follows = 0;\r
+\r
+ /* initialize all of the output variables */\r
+ SubString_init(literal, NULL, 0);\r
+ SubString_init(field_name, NULL, 0);\r
+ SubString_init(format_spec, NULL, 0);\r
+ *conversion = '\0';\r
+ *format_spec_needs_expanding = 0;\r
+ *field_present = 0;\r
+\r
+ /* No more input, end of iterator. This is the normal exit\r
+ path. */\r
+ if (self->str.ptr >= self->str.end)\r
+ return 1;\r
+\r
+ start = self->str.ptr;\r
+\r
+ /* First read any literal text. Read until the end of string, an\r
+ escaped '{' or '}', or an unescaped '{'. In order to never\r
+ allocate memory and so I can just pass pointers around, if\r
+ there's an escaped '{' or '}' then we'll return the literal\r
+ including the brace, but no format object. The next time\r
+ through, we'll return the rest of the literal, skipping past\r
+ the second consecutive brace. */\r
+ while (self->str.ptr < self->str.end) {\r
+ switch (c = *(self->str.ptr++)) {\r
+ case '{':\r
+ case '}':\r
+ markup_follows = 1;\r
+ break;\r
+ default:\r
+ continue;\r
+ }\r
+ break;\r
+ }\r
+\r
+ at_end = self->str.ptr >= self->str.end;\r
+ len = self->str.ptr - start;\r
+\r
+ if ((c == '}') && (at_end || (c != *self->str.ptr))) {\r
+ PyErr_SetString(PyExc_ValueError, "Single '}' encountered "\r
+ "in format string");\r
+ return 0;\r
+ }\r
+ if (at_end && c == '{') {\r
+ PyErr_SetString(PyExc_ValueError, "Single '{' encountered "\r
+ "in format string");\r
+ return 0;\r
+ }\r
+ if (!at_end) {\r
+ if (c == *self->str.ptr) {\r
+ /* escaped } or {, skip it in the input. there is no\r
+ markup object following us, just this literal text */\r
+ self->str.ptr++;\r
+ markup_follows = 0;\r
+ }\r
+ else\r
+ len--;\r
+ }\r
+\r
+ /* record the literal text */\r
+ literal->ptr = start;\r
+ literal->end = start + len;\r
+\r
+ if (!markup_follows)\r
+ return 2;\r
+\r
+ /* this is markup, find the end of the string by counting nested\r
+ braces. note that this prohibits escaped braces, so that\r
+ format_specs cannot have braces in them. */\r
+ *field_present = 1;\r
+ count = 1;\r
+\r
+ start = self->str.ptr;\r
+\r
+ /* we know we can't have a zero length string, so don't worry\r
+ about that case */\r
+ while (self->str.ptr < self->str.end) {\r
+ switch (c = *(self->str.ptr++)) {\r
+ case '{':\r
+ /* the format spec needs to be recursively expanded.\r
+ this is an optimization, and not strictly needed */\r
+ *format_spec_needs_expanding = 1;\r
+ count++;\r
+ break;\r
+ case '}':\r
+ count--;\r
+ if (count <= 0) {\r
+ /* we're done. parse and get out */\r
+ SubString s;\r
+\r
+ SubString_init(&s, start, self->str.ptr - 1 - start);\r
+ if (parse_field(&s, field_name, format_spec, conversion) == 0)\r
+ return 0;\r
+\r
+ /* success */\r
+ return 2;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* end of string while searching for matching '}' */\r
+ PyErr_SetString(PyExc_ValueError, "unmatched '{' in format");\r
+ return 0;\r
+}\r
+\r
+\r
+/* do the !r or !s conversion on obj */\r
+static PyObject *\r
+do_conversion(PyObject *obj, STRINGLIB_CHAR conversion)\r
+{\r
+ /* XXX in pre-3.0, do we need to convert this to unicode, since it\r
+ might have returned a string? */\r
+ switch (conversion) {\r
+ case 'r':\r
+ return PyObject_Repr(obj);\r
+ case 's':\r
+ return STRINGLIB_TOSTR(obj);\r
+ default:\r
+ if (conversion > 32 && conversion < 127) {\r
+ /* It's the ASCII subrange; casting to char is safe\r
+ (assuming the execution character set is an ASCII\r
+ superset). */\r
+ PyErr_Format(PyExc_ValueError,\r
+ "Unknown conversion specifier %c",\r
+ (char)conversion);\r
+ } else\r
+ PyErr_Format(PyExc_ValueError,\r
+ "Unknown conversion specifier \\x%x",\r
+ (unsigned int)conversion);\r
+ return NULL;\r
+ }\r
+}\r
+\r
+/* given:\r
+\r
+ {field_name!conversion:format_spec}\r
+\r
+ compute the result and write it to output.\r
+ format_spec_needs_expanding is an optimization. if it's false,\r
+ just output the string directly, otherwise recursively expand the\r
+ format_spec string.\r
+\r
+ field_name is allowed to be zero length, in which case we\r
+ are doing auto field numbering.\r
+*/\r
+\r
+static int\r
+output_markup(SubString *field_name, SubString *format_spec,\r
+ int format_spec_needs_expanding, STRINGLIB_CHAR conversion,\r
+ OutputString *output, PyObject *args, PyObject *kwargs,\r
+ int recursion_depth, AutoNumber *auto_number)\r
+{\r
+ PyObject *tmp = NULL;\r
+ PyObject *fieldobj = NULL;\r
+ SubString expanded_format_spec;\r
+ SubString *actual_format_spec;\r
+ int result = 0;\r
+\r
+ /* convert field_name to an object */\r
+ fieldobj = get_field_object(field_name, args, kwargs, auto_number);\r
+ if (fieldobj == NULL)\r
+ goto done;\r
+\r
+ if (conversion != '\0') {\r
+ tmp = do_conversion(fieldobj, conversion);\r
+ if (tmp == NULL)\r
+ goto done;\r
+\r
+ /* do the assignment, transferring ownership: fieldobj = tmp */\r
+ Py_DECREF(fieldobj);\r
+ fieldobj = tmp;\r
+ tmp = NULL;\r
+ }\r
+\r
+ /* if needed, recurively compute the format_spec */\r
+ if (format_spec_needs_expanding) {\r
+ tmp = build_string(format_spec, args, kwargs, recursion_depth-1,\r
+ auto_number);\r
+ if (tmp == NULL)\r
+ goto done;\r
+\r
+ /* note that in the case we're expanding the format string,\r
+ tmp must be kept around until after the call to\r
+ render_field. */\r
+ SubString_init(&expanded_format_spec,\r
+ STRINGLIB_STR(tmp), STRINGLIB_LEN(tmp));\r
+ actual_format_spec = &expanded_format_spec;\r
+ }\r
+ else\r
+ actual_format_spec = format_spec;\r
+\r
+ if (render_field(fieldobj, actual_format_spec, output) == 0)\r
+ goto done;\r
+\r
+ result = 1;\r
+\r
+done:\r
+ Py_XDECREF(fieldobj);\r
+ Py_XDECREF(tmp);\r
+\r
+ return result;\r
+}\r
+\r
+/*\r
+ do_markup is the top-level loop for the format() method. It\r
+ searches through the format string for escapes to markup codes, and\r
+ calls other functions to move non-markup text to the output,\r
+ and to perform the markup to the output.\r
+*/\r
+static int\r
+do_markup(SubString *input, PyObject *args, PyObject *kwargs,\r
+ OutputString *output, int recursion_depth, AutoNumber *auto_number)\r
+{\r
+ MarkupIterator iter;\r
+ int format_spec_needs_expanding;\r
+ int result;\r
+ int field_present;\r
+ SubString literal;\r
+ SubString field_name;\r
+ SubString format_spec;\r
+ STRINGLIB_CHAR conversion;\r
+\r
+ MarkupIterator_init(&iter, input->ptr, input->end - input->ptr);\r
+ while ((result = MarkupIterator_next(&iter, &literal, &field_present,\r
+ &field_name, &format_spec,\r
+ &conversion,\r
+ &format_spec_needs_expanding)) == 2) {\r
+ if (!output_data(output, literal.ptr, literal.end - literal.ptr))\r
+ return 0;\r
+ if (field_present)\r
+ if (!output_markup(&field_name, &format_spec,\r
+ format_spec_needs_expanding, conversion, output,\r
+ args, kwargs, recursion_depth, auto_number))\r
+ return 0;\r
+ }\r
+ return result;\r
+}\r
+\r
+\r
+/*\r
+ build_string allocates the output string and then\r
+ calls do_markup to do the heavy lifting.\r
+*/\r
+static PyObject *\r
+build_string(SubString *input, PyObject *args, PyObject *kwargs,\r
+ int recursion_depth, AutoNumber *auto_number)\r
+{\r
+ OutputString output;\r
+ PyObject *result = NULL;\r
+ Py_ssize_t count;\r
+\r
+ output.obj = NULL; /* needed so cleanup code always works */\r
+\r
+ /* check the recursion level */\r
+ if (recursion_depth <= 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Max string recursion exceeded");\r
+ goto done;\r
+ }\r
+\r
+ /* initial size is the length of the format string, plus the size\r
+ increment. seems like a reasonable default */\r
+ if (!output_initialize(&output,\r
+ input->end - input->ptr +\r
+ INITIAL_SIZE_INCREMENT))\r
+ goto done;\r
+\r
+ if (!do_markup(input, args, kwargs, &output, recursion_depth,\r
+ auto_number)) {\r
+ goto done;\r
+ }\r
+\r
+ count = output.ptr - STRINGLIB_STR(output.obj);\r
+ if (STRINGLIB_RESIZE(&output.obj, count) < 0) {\r
+ goto done;\r
+ }\r
+\r
+ /* transfer ownership to result */\r
+ result = output.obj;\r
+ output.obj = NULL;\r
+\r
+done:\r
+ Py_XDECREF(output.obj);\r
+ return result;\r
+}\r
+\r
+/************************************************************************/\r
+/*********** main routine ***********************************************/\r
+/************************************************************************/\r
+\r
+/* this is the main entry point */\r
+static PyObject *\r
+do_string_format(PyObject *self, PyObject *args, PyObject *kwargs)\r
+{\r
+ SubString input;\r
+\r
+ /* PEP 3101 says only 2 levels, so that\r
+ "{0:{1}}".format('abc', 's') # works\r
+ "{0:{1:{2}}}".format('abc', 's', '') # fails\r
+ */\r
+ int recursion_depth = 2;\r
+\r
+ AutoNumber auto_number;\r
+\r
+ AutoNumber_Init(&auto_number);\r
+ SubString_init(&input, STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+ return build_string(&input, args, kwargs, recursion_depth, &auto_number);\r
+}\r
+\r
+\r
+\r
+/************************************************************************/\r
+/*********** formatteriterator ******************************************/\r
+/************************************************************************/\r
+\r
+/* This is used to implement string.Formatter.vparse(). It exists so\r
+ Formatter can share code with the built in unicode.format() method.\r
+ It's really just a wrapper around MarkupIterator that is callable\r
+ from Python. */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+\r
+ STRINGLIB_OBJECT *str;\r
+\r
+ MarkupIterator it_markup;\r
+} formatteriterobject;\r
+\r
+static void\r
+formatteriter_dealloc(formatteriterobject *it)\r
+{\r
+ Py_XDECREF(it->str);\r
+ PyObject_FREE(it);\r
+}\r
+\r
+/* returns a tuple:\r
+ (literal, field_name, format_spec, conversion)\r
+\r
+ literal is any literal text to output. might be zero length\r
+ field_name is the string before the ':'. might be None\r
+ format_spec is the string after the ':'. mibht be None\r
+ conversion is either None, or the string after the '!'\r
+*/\r
+static PyObject *\r
+formatteriter_next(formatteriterobject *it)\r
+{\r
+ SubString literal;\r
+ SubString field_name;\r
+ SubString format_spec;\r
+ STRINGLIB_CHAR conversion;\r
+ int format_spec_needs_expanding;\r
+ int field_present;\r
+ int result = MarkupIterator_next(&it->it_markup, &literal, &field_present,\r
+ &field_name, &format_spec, &conversion,\r
+ &format_spec_needs_expanding);\r
+\r
+ /* all of the SubString objects point into it->str, so no\r
+ memory management needs to be done on them */\r
+ assert(0 <= result && result <= 2);\r
+ if (result == 0 || result == 1)\r
+ /* if 0, error has already been set, if 1, iterator is empty */\r
+ return NULL;\r
+ else {\r
+ PyObject *literal_str = NULL;\r
+ PyObject *field_name_str = NULL;\r
+ PyObject *format_spec_str = NULL;\r
+ PyObject *conversion_str = NULL;\r
+ PyObject *tuple = NULL;\r
+\r
+ literal_str = SubString_new_object(&literal);\r
+ if (literal_str == NULL)\r
+ goto done;\r
+\r
+ field_name_str = SubString_new_object(&field_name);\r
+ if (field_name_str == NULL)\r
+ goto done;\r
+\r
+ /* if field_name is non-zero length, return a string for\r
+ format_spec (even if zero length), else return None */\r
+ format_spec_str = (field_present ?\r
+ SubString_new_object_or_empty :\r
+ SubString_new_object)(&format_spec);\r
+ if (format_spec_str == NULL)\r
+ goto done;\r
+\r
+ /* if the conversion is not specified, return a None,\r
+ otherwise create a one length string with the conversion\r
+ character */\r
+ if (conversion == '\0') {\r
+ conversion_str = Py_None;\r
+ Py_INCREF(conversion_str);\r
+ }\r
+ else\r
+ conversion_str = STRINGLIB_NEW(&conversion, 1);\r
+ if (conversion_str == NULL)\r
+ goto done;\r
+\r
+ tuple = PyTuple_Pack(4, literal_str, field_name_str, format_spec_str,\r
+ conversion_str);\r
+ done:\r
+ Py_XDECREF(literal_str);\r
+ Py_XDECREF(field_name_str);\r
+ Py_XDECREF(format_spec_str);\r
+ Py_XDECREF(conversion_str);\r
+ return tuple;\r
+ }\r
+}\r
+\r
+static PyMethodDef formatteriter_methods[] = {\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyTypeObject PyFormatterIter_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "formatteriterator", /* tp_name */\r
+ sizeof(formatteriterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)formatteriter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)formatteriter_next, /* tp_iternext */\r
+ formatteriter_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+/* unicode_formatter_parser is used to implement\r
+ string.Formatter.vformat. it parses a string and returns tuples\r
+ describing the parsed elements. It's a wrapper around\r
+ stringlib/string_format.h's MarkupIterator */\r
+static PyObject *\r
+formatter_parser(STRINGLIB_OBJECT *self)\r
+{\r
+ formatteriterobject *it;\r
+\r
+ it = PyObject_New(formatteriterobject, &PyFormatterIter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+\r
+ /* take ownership, give the object to the iterator */\r
+ Py_INCREF(self);\r
+ it->str = self;\r
+\r
+ /* initialize the contained MarkupIterator */\r
+ MarkupIterator_init(&it->it_markup,\r
+ STRINGLIB_STR(self),\r
+ STRINGLIB_LEN(self));\r
+\r
+ return (PyObject *)it;\r
+}\r
+\r
+\r
+/************************************************************************/\r
+/*********** fieldnameiterator ******************************************/\r
+/************************************************************************/\r
+\r
+\r
+/* This is used to implement string.Formatter.vparse(). It parses the\r
+ field name into attribute and item values. It's a Python-callable\r
+ wrapper around FieldNameIterator */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+\r
+ STRINGLIB_OBJECT *str;\r
+\r
+ FieldNameIterator it_field;\r
+} fieldnameiterobject;\r
+\r
+static void\r
+fieldnameiter_dealloc(fieldnameiterobject *it)\r
+{\r
+ Py_XDECREF(it->str);\r
+ PyObject_FREE(it);\r
+}\r
+\r
+/* returns a tuple:\r
+ (is_attr, value)\r
+ is_attr is true if we used attribute syntax (e.g., '.foo')\r
+ false if we used index syntax (e.g., '[foo]')\r
+ value is an integer or string\r
+*/\r
+static PyObject *\r
+fieldnameiter_next(fieldnameiterobject *it)\r
+{\r
+ int result;\r
+ int is_attr;\r
+ Py_ssize_t idx;\r
+ SubString name;\r
+\r
+ result = FieldNameIterator_next(&it->it_field, &is_attr,\r
+ &idx, &name);\r
+ if (result == 0 || result == 1)\r
+ /* if 0, error has already been set, if 1, iterator is empty */\r
+ return NULL;\r
+ else {\r
+ PyObject* result = NULL;\r
+ PyObject* is_attr_obj = NULL;\r
+ PyObject* obj = NULL;\r
+\r
+ is_attr_obj = PyBool_FromLong(is_attr);\r
+ if (is_attr_obj == NULL)\r
+ goto done;\r
+\r
+ /* either an integer or a string */\r
+ if (idx != -1)\r
+ obj = PyLong_FromSsize_t(idx);\r
+ else\r
+ obj = SubString_new_object(&name);\r
+ if (obj == NULL)\r
+ goto done;\r
+\r
+ /* return a tuple of values */\r
+ result = PyTuple_Pack(2, is_attr_obj, obj);\r
+\r
+ done:\r
+ Py_XDECREF(is_attr_obj);\r
+ Py_XDECREF(obj);\r
+ return result;\r
+ }\r
+}\r
+\r
+static PyMethodDef fieldnameiter_methods[] = {\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyTypeObject PyFieldNameIter_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "fieldnameiterator", /* tp_name */\r
+ sizeof(fieldnameiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)fieldnameiter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)fieldnameiter_next, /* tp_iternext */\r
+ fieldnameiter_methods, /* tp_methods */\r
+ 0};\r
+\r
+/* unicode_formatter_field_name_split is used to implement\r
+ string.Formatter.vformat. it takes an PEP 3101 "field name", and\r
+ returns a tuple of (first, rest): "first", the part before the\r
+ first '.' or '['; and "rest", an iterator for the rest of the field\r
+ name. it's a wrapper around stringlib/string_format.h's\r
+ field_name_split. The iterator it returns is a\r
+ FieldNameIterator */\r
+static PyObject *\r
+formatter_field_name_split(STRINGLIB_OBJECT *self)\r
+{\r
+ SubString first;\r
+ Py_ssize_t first_idx;\r
+ fieldnameiterobject *it;\r
+\r
+ PyObject *first_obj = NULL;\r
+ PyObject *result = NULL;\r
+\r
+ it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+\r
+ /* take ownership, give the object to the iterator. this is\r
+ just to keep the field_name alive */\r
+ Py_INCREF(self);\r
+ it->str = self;\r
+\r
+ /* Pass in auto_number = NULL. We'll return an empty string for\r
+ first_obj in that case. */\r
+ if (!field_name_split(STRINGLIB_STR(self),\r
+ STRINGLIB_LEN(self),\r
+ &first, &first_idx, &it->it_field, NULL))\r
+ goto done;\r
+\r
+ /* first becomes an integer, if possible; else a string */\r
+ if (first_idx != -1)\r
+ first_obj = PyLong_FromSsize_t(first_idx);\r
+ else\r
+ /* convert "first" into a string object */\r
+ first_obj = SubString_new_object(&first);\r
+ if (first_obj == NULL)\r
+ goto done;\r
+\r
+ /* return a tuple of values */\r
+ result = PyTuple_Pack(2, first_obj, it);\r
+\r
+done:\r
+ Py_XDECREF(it);\r
+ Py_XDECREF(first_obj);\r
+ return result;\r
+}\r
--- /dev/null
+#ifndef STRINGLIB_STRINGDEFS_H\r
+#define STRINGLIB_STRINGDEFS_H\r
+\r
+/* this is sort of a hack. there's at least one place (formatting\r
+ floats) where some stringlib code takes a different path if it's\r
+ compiled as unicode. */\r
+#define STRINGLIB_IS_UNICODE 0\r
+\r
+#define STRINGLIB_OBJECT PyStringObject\r
+#define STRINGLIB_CHAR char\r
+#define STRINGLIB_TYPE_NAME "string"\r
+#define STRINGLIB_PARSE_CODE "S"\r
+#define STRINGLIB_EMPTY nullstring\r
+#define STRINGLIB_ISSPACE Py_ISSPACE\r
+#define STRINGLIB_ISLINEBREAK(x) ((x == '\n') || (x == '\r'))\r
+#define STRINGLIB_ISDECIMAL(x) ((x >= '0') && (x <= '9'))\r
+#define STRINGLIB_TODECIMAL(x) (STRINGLIB_ISDECIMAL(x) ? (x - '0') : -1)\r
+#define STRINGLIB_TOUPPER Py_TOUPPER\r
+#define STRINGLIB_TOLOWER Py_TOLOWER\r
+#define STRINGLIB_FILL memset\r
+#define STRINGLIB_STR PyString_AS_STRING\r
+#define STRINGLIB_LEN PyString_GET_SIZE\r
+#define STRINGLIB_NEW PyString_FromStringAndSize\r
+#define STRINGLIB_RESIZE _PyString_Resize\r
+#define STRINGLIB_CHECK PyString_Check\r
+#define STRINGLIB_CHECK_EXACT PyString_CheckExact\r
+#define STRINGLIB_TOSTR PyObject_Str\r
+#define STRINGLIB_GROUPING _PyString_InsertThousandsGrouping\r
+#define STRINGLIB_GROUPING_LOCALE _PyString_InsertThousandsGroupingLocale\r
+\r
+#define STRINGLIB_WANT_CONTAINS_OBJ 1\r
+\r
+#endif /* !STRINGLIB_STRINGDEFS_H */\r
--- /dev/null
+/* NOTE: this API is -ONLY- for use with single byte character strings. */\r
+/* Do not use it with Unicode. */\r
+\r
+/* the more complicated methods. parts of these should be pulled out into the\r
+ shared code in bytes_methods.c to cut down on duplicate code bloat. */\r
+\r
+PyDoc_STRVAR(expandtabs__doc__,\r
+"B.expandtabs([tabsize]) -> copy of B\n\\r
+\n\\r
+Return a copy of B where all tab characters are expanded using spaces.\n\\r
+If tabsize is not given, a tab size of 8 characters is assumed.");\r
+\r
+static PyObject*\r
+stringlib_expandtabs(PyObject *self, PyObject *args)\r
+{\r
+ const char *e, *p;\r
+ char *q;\r
+ Py_ssize_t i, j;\r
+ PyObject *u;\r
+ int tabsize = 8;\r
+ \r
+ if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))\r
+ return NULL;\r
+ \r
+ /* First pass: determine size of output string */\r
+ i = j = 0;\r
+ e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);\r
+ for (p = STRINGLIB_STR(self); p < e; p++) {\r
+ if (*p == '\t') {\r
+ if (tabsize > 0) {\r
+ Py_ssize_t incr = tabsize - (j % tabsize);\r
+ if (j > PY_SSIZE_T_MAX - incr)\r
+ goto overflow;\r
+ j += incr;\r
+ }\r
+ }\r
+ else {\r
+ if (j > PY_SSIZE_T_MAX - 1)\r
+ goto overflow;\r
+ j++;\r
+ if (*p == '\n' || *p == '\r') {\r
+ if (i > PY_SSIZE_T_MAX - j)\r
+ goto overflow;\r
+ i += j;\r
+ j = 0;\r
+ }\r
+ }\r
+ }\r
+ \r
+ if (i > PY_SSIZE_T_MAX - j)\r
+ goto overflow;\r
+ \r
+ /* Second pass: create output string and fill it */\r
+ u = STRINGLIB_NEW(NULL, i + j);\r
+ if (!u)\r
+ return NULL;\r
+ \r
+ j = 0;\r
+ q = STRINGLIB_STR(u);\r
+ \r
+ for (p = STRINGLIB_STR(self); p < e; p++) {\r
+ if (*p == '\t') {\r
+ if (tabsize > 0) {\r
+ i = tabsize - (j % tabsize);\r
+ j += i;\r
+ while (i--)\r
+ *q++ = ' ';\r
+ }\r
+ }\r
+ else {\r
+ j++;\r
+ *q++ = *p;\r
+ if (*p == '\n' || *p == '\r')\r
+ j = 0;\r
+ }\r
+ }\r
+\r
+ return u;\r
+ overflow:\r
+ PyErr_SetString(PyExc_OverflowError, "result too long");\r
+ return NULL;\r
+}\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)\r
+{\r
+ PyObject *u;\r
+\r
+ if (left < 0)\r
+ left = 0;\r
+ if (right < 0)\r
+ right = 0;\r
+\r
+ if (left == 0 && right == 0 && STRINGLIB_CHECK_EXACT(self)) {\r
+#if STRINGLIB_MUTABLE\r
+ /* We're defined as returning a copy; If the object is mutable\r
+ * that means we must make an identical copy. */\r
+ return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+#else\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+#endif /* STRINGLIB_MUTABLE */\r
+ }\r
+\r
+ u = STRINGLIB_NEW(NULL,\r
+ left + STRINGLIB_LEN(self) + right);\r
+ if (u) {\r
+ if (left)\r
+ memset(STRINGLIB_STR(u), fill, left);\r
+ Py_MEMCPY(STRINGLIB_STR(u) + left,\r
+ STRINGLIB_STR(self),\r
+ STRINGLIB_LEN(self));\r
+ if (right)\r
+ memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),\r
+ fill, right);\r
+ }\r
+\r
+ return u;\r
+}\r
+\r
+PyDoc_STRVAR(ljust__doc__,\r
+"B.ljust(width[, fillchar]) -> copy of B\n"\r
+"\n"\r
+"Return B left justified in a string of length width. Padding is\n"\r
+"done using the specified fill character (default is a space).");\r
+\r
+static PyObject *\r
+stringlib_ljust(PyObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t width;\r
+ char fillchar = ' ';\r
+\r
+ if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))\r
+ return NULL;\r
+\r
+ if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {\r
+#if STRINGLIB_MUTABLE\r
+ /* We're defined as returning a copy; If the object is mutable\r
+ * that means we must make an identical copy. */\r
+ return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+#else\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+#endif\r
+ }\r
+\r
+ return pad(self, 0, width - STRINGLIB_LEN(self), fillchar);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(rjust__doc__,\r
+"B.rjust(width[, fillchar]) -> copy of B\n"\r
+"\n"\r
+"Return B right justified in a string of length width. Padding is\n"\r
+"done using the specified fill character (default is a space)");\r
+\r
+static PyObject *\r
+stringlib_rjust(PyObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t width;\r
+ char fillchar = ' ';\r
+\r
+ if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar))\r
+ return NULL;\r
+\r
+ if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {\r
+#if STRINGLIB_MUTABLE\r
+ /* We're defined as returning a copy; If the object is mutable\r
+ * that means we must make an identical copy. */\r
+ return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+#else\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+#endif\r
+ }\r
+\r
+ return pad(self, width - STRINGLIB_LEN(self), 0, fillchar);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(center__doc__,\r
+"B.center(width[, fillchar]) -> copy of B\n"\r
+"\n"\r
+"Return B centered in a string of length width. Padding is\n"\r
+"done using the specified fill character (default is a space).");\r
+\r
+static PyObject *\r
+stringlib_center(PyObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t marg, left;\r
+ Py_ssize_t width;\r
+ char fillchar = ' ';\r
+\r
+ if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar))\r
+ return NULL;\r
+\r
+ if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {\r
+#if STRINGLIB_MUTABLE\r
+ /* We're defined as returning a copy; If the object is mutable\r
+ * that means we must make an identical copy. */\r
+ return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+#else\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+#endif\r
+ }\r
+\r
+ marg = width - STRINGLIB_LEN(self);\r
+ left = marg / 2 + (marg & width & 1);\r
+\r
+ return pad(self, left, marg - left, fillchar);\r
+}\r
+\r
+PyDoc_STRVAR(zfill__doc__,\r
+"B.zfill(width) -> copy of B\n"\r
+"\n"\r
+"Pad a numeric string B with zeros on the left, to fill a field\n"\r
+"of the specified width. B is never truncated.");\r
+\r
+static PyObject *\r
+stringlib_zfill(PyObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t fill;\r
+ PyObject *s;\r
+ char *p;\r
+ Py_ssize_t width;\r
+\r
+ if (!PyArg_ParseTuple(args, "n:zfill", &width))\r
+ return NULL;\r
+\r
+ if (STRINGLIB_LEN(self) >= width) {\r
+ if (STRINGLIB_CHECK_EXACT(self)) {\r
+#if STRINGLIB_MUTABLE\r
+ /* We're defined as returning a copy; If the object is mutable\r
+ * that means we must make an identical copy. */\r
+ return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r
+#else\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+#endif\r
+ }\r
+ else\r
+ return STRINGLIB_NEW(\r
+ STRINGLIB_STR(self),\r
+ STRINGLIB_LEN(self)\r
+ );\r
+ }\r
+\r
+ fill = width - STRINGLIB_LEN(self);\r
+\r
+ s = pad(self, fill, 0, '0');\r
+\r
+ if (s == NULL)\r
+ return NULL;\r
+\r
+ p = STRINGLIB_STR(s);\r
+ if (p[fill] == '+' || p[fill] == '-') {\r
+ /* move sign to beginning of string */\r
+ p[0] = p[fill];\r
+ p[fill] = '0';\r
+ }\r
+\r
+ return (PyObject*) s;\r
+}\r
--- /dev/null
+#ifndef STRINGLIB_UNICODEDEFS_H\r
+#define STRINGLIB_UNICODEDEFS_H\r
+\r
+/* this is sort of a hack. there's at least one place (formatting\r
+ floats) where some stringlib code takes a different path if it's\r
+ compiled as unicode. */\r
+#define STRINGLIB_IS_UNICODE 1\r
+\r
+#define STRINGLIB_OBJECT PyUnicodeObject\r
+#define STRINGLIB_CHAR Py_UNICODE\r
+#define STRINGLIB_TYPE_NAME "unicode"\r
+#define STRINGLIB_PARSE_CODE "U"\r
+#define STRINGLIB_EMPTY unicode_empty\r
+#define STRINGLIB_ISSPACE Py_UNICODE_ISSPACE\r
+#define STRINGLIB_ISLINEBREAK BLOOM_LINEBREAK\r
+#define STRINGLIB_ISDECIMAL Py_UNICODE_ISDECIMAL\r
+#define STRINGLIB_TODECIMAL Py_UNICODE_TODECIMAL\r
+#define STRINGLIB_TOUPPER Py_UNICODE_TOUPPER\r
+#define STRINGLIB_TOLOWER Py_UNICODE_TOLOWER\r
+#define STRINGLIB_FILL Py_UNICODE_FILL\r
+#define STRINGLIB_STR PyUnicode_AS_UNICODE\r
+#define STRINGLIB_LEN PyUnicode_GET_SIZE\r
+#define STRINGLIB_NEW PyUnicode_FromUnicode\r
+#define STRINGLIB_RESIZE PyUnicode_Resize\r
+#define STRINGLIB_CHECK PyUnicode_Check\r
+#define STRINGLIB_CHECK_EXACT PyUnicode_CheckExact\r
+#define STRINGLIB_GROUPING _PyUnicode_InsertThousandsGrouping\r
+\r
+#if PY_VERSION_HEX < 0x03000000\r
+#define STRINGLIB_TOSTR PyObject_Unicode\r
+#else\r
+#define STRINGLIB_TOSTR PyObject_Str\r
+#endif\r
+\r
+#define STRINGLIB_WANT_CONTAINS_OBJ 1\r
+\r
+#endif /* !STRINGLIB_UNICODEDEFS_H */\r
--- /dev/null
+/* String (str/bytes) object implementation */\r
+\r
+#define PY_SSIZE_T_CLEAN\r
+\r
+#include "Python.h"\r
+#include <ctype.h>\r
+#include <stddef.h>\r
+\r
+#ifdef COUNT_ALLOCS\r
+Py_ssize_t null_strings, one_strings;\r
+#endif\r
+\r
+static PyStringObject *characters[UCHAR_MAX + 1];\r
+static PyStringObject *nullstring;\r
+\r
+/* This dictionary holds all interned strings. Note that references to\r
+ strings in this dictionary are *not* counted in the string's ob_refcnt.\r
+ When the interned string reaches a refcnt of 0 the string deallocation\r
+ function will delete the reference from this dictionary.\r
+\r
+ Another way to look at this is that to say that the actual reference\r
+ count of a string is: s->ob_refcnt + (s->ob_sstate?2:0)\r
+*/\r
+static PyObject *interned;\r
+\r
+/* PyStringObject_SIZE gives the basic size of a string; any memory allocation\r
+ for a string of length n should request PyStringObject_SIZE + n bytes.\r
+\r
+ Using PyStringObject_SIZE instead of sizeof(PyStringObject) saves\r
+ 3 bytes per string allocation on a typical system.\r
+*/\r
+#define PyStringObject_SIZE (offsetof(PyStringObject, ob_sval) + 1)\r
+\r
+/*\r
+ For PyString_FromString(), the parameter `str' points to a null-terminated\r
+ string containing exactly `size' bytes.\r
+\r
+ For PyString_FromStringAndSize(), the parameter the parameter `str' is\r
+ either NULL or else points to a string containing at least `size' bytes.\r
+ For PyString_FromStringAndSize(), the string in the `str' parameter does\r
+ not have to be null-terminated. (Therefore it is safe to construct a\r
+ substring by calling `PyString_FromStringAndSize(origstring, substrlen)'.)\r
+ If `str' is NULL then PyString_FromStringAndSize() will allocate `size+1'\r
+ bytes (setting the last byte to the null terminating character) and you can\r
+ fill in the data yourself. If `str' is non-NULL then the resulting\r
+ PyString object must be treated as immutable and you must not fill in nor\r
+ alter the data yourself, since the strings may be shared.\r
+\r
+ The PyObject member `op->ob_size', which denotes the number of "extra\r
+ items" in a variable-size object, will contain the number of bytes\r
+ allocated for string data, not counting the null terminating character.\r
+ It is therefore equal to the `size' parameter (for\r
+ PyString_FromStringAndSize()) or the length of the string in the `str'\r
+ parameter (for PyString_FromString()).\r
+*/\r
+PyObject *\r
+PyString_FromStringAndSize(const char *str, Py_ssize_t size)\r
+{\r
+ register PyStringObject *op;\r
+ if (size < 0) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "Negative size passed to PyString_FromStringAndSize");\r
+ return NULL;\r
+ }\r
+ if (size == 0 && (op = nullstring) != NULL) {\r
+#ifdef COUNT_ALLOCS\r
+ null_strings++;\r
+#endif\r
+ Py_INCREF(op);\r
+ return (PyObject *)op;\r
+ }\r
+ if (size == 1 && str != NULL &&\r
+ (op = characters[*str & UCHAR_MAX]) != NULL)\r
+ {\r
+#ifdef COUNT_ALLOCS\r
+ one_strings++;\r
+#endif\r
+ Py_INCREF(op);\r
+ return (PyObject *)op;\r
+ }\r
+\r
+ if (size > PY_SSIZE_T_MAX - PyStringObject_SIZE) {\r
+ PyErr_SetString(PyExc_OverflowError, "string is too large");\r
+ return NULL;\r
+ }\r
+\r
+ /* Inline PyObject_NewVar */\r
+ op = (PyStringObject *)PyObject_MALLOC(PyStringObject_SIZE + size);\r
+ if (op == NULL)\r
+ return PyErr_NoMemory();\r
+ PyObject_INIT_VAR(op, &PyString_Type, size);\r
+ op->ob_shash = -1;\r
+ op->ob_sstate = SSTATE_NOT_INTERNED;\r
+ if (str != NULL)\r
+ Py_MEMCPY(op->ob_sval, str, size);\r
+ op->ob_sval[size] = '\0';\r
+ /* share short strings */\r
+ if (size == 0) {\r
+ PyObject *t = (PyObject *)op;\r
+ PyString_InternInPlace(&t);\r
+ op = (PyStringObject *)t;\r
+ nullstring = op;\r
+ Py_INCREF(op);\r
+ } else if (size == 1 && str != NULL) {\r
+ PyObject *t = (PyObject *)op;\r
+ PyString_InternInPlace(&t);\r
+ op = (PyStringObject *)t;\r
+ characters[*str & UCHAR_MAX] = op;\r
+ Py_INCREF(op);\r
+ }\r
+ return (PyObject *) op;\r
+}\r
+\r
+PyObject *\r
+PyString_FromString(const char *str)\r
+{\r
+ register size_t size;\r
+ register PyStringObject *op;\r
+\r
+ assert(str != NULL);\r
+ size = strlen(str);\r
+ if (size > PY_SSIZE_T_MAX - PyStringObject_SIZE) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "string is too long for a Python string");\r
+ return NULL;\r
+ }\r
+ if (size == 0 && (op = nullstring) != NULL) {\r
+#ifdef COUNT_ALLOCS\r
+ null_strings++;\r
+#endif\r
+ Py_INCREF(op);\r
+ return (PyObject *)op;\r
+ }\r
+ if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) {\r
+#ifdef COUNT_ALLOCS\r
+ one_strings++;\r
+#endif\r
+ Py_INCREF(op);\r
+ return (PyObject *)op;\r
+ }\r
+\r
+ /* Inline PyObject_NewVar */\r
+ op = (PyStringObject *)PyObject_MALLOC(PyStringObject_SIZE + size);\r
+ if (op == NULL)\r
+ return PyErr_NoMemory();\r
+ PyObject_INIT_VAR(op, &PyString_Type, size);\r
+ op->ob_shash = -1;\r
+ op->ob_sstate = SSTATE_NOT_INTERNED;\r
+ Py_MEMCPY(op->ob_sval, str, size+1);\r
+ /* share short strings */\r
+ if (size == 0) {\r
+ PyObject *t = (PyObject *)op;\r
+ PyString_InternInPlace(&t);\r
+ op = (PyStringObject *)t;\r
+ nullstring = op;\r
+ Py_INCREF(op);\r
+ } else if (size == 1) {\r
+ PyObject *t = (PyObject *)op;\r
+ PyString_InternInPlace(&t);\r
+ op = (PyStringObject *)t;\r
+ characters[*str & UCHAR_MAX] = op;\r
+ Py_INCREF(op);\r
+ }\r
+ return (PyObject *) op;\r
+}\r
+\r
+PyObject *\r
+PyString_FromFormatV(const char *format, va_list vargs)\r
+{\r
+ va_list count;\r
+ Py_ssize_t n = 0;\r
+ const char* f;\r
+ char *s;\r
+ PyObject* string;\r
+\r
+#ifdef VA_LIST_IS_ARRAY\r
+ Py_MEMCPY(count, vargs, sizeof(va_list));\r
+#else\r
+#ifdef __va_copy\r
+ __va_copy(count, vargs);\r
+#else\r
+ count = vargs;\r
+#endif\r
+#endif\r
+ /* step 1: figure out how large a buffer we need */\r
+ for (f = format; *f; f++) {\r
+ if (*f == '%') {\r
+#ifdef HAVE_LONG_LONG\r
+ int longlongflag = 0;\r
+#endif\r
+ const char* p = f;\r
+ while (*++f && *f != '%' && !isalpha(Py_CHARMASK(*f)))\r
+ ;\r
+\r
+ /* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since\r
+ * they don't affect the amount of space we reserve.\r
+ */\r
+ if (*f == 'l') {\r
+ if (f[1] == 'd' || f[1] == 'u') {\r
+ ++f;\r
+ }\r
+#ifdef HAVE_LONG_LONG\r
+ else if (f[1] == 'l' &&\r
+ (f[2] == 'd' || f[2] == 'u')) {\r
+ longlongflag = 1;\r
+ f += 2;\r
+ }\r
+#endif\r
+ }\r
+ else if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) {\r
+ ++f;\r
+ }\r
+\r
+ switch (*f) {\r
+ case 'c':\r
+ (void)va_arg(count, int);\r
+ /* fall through... */\r
+ case '%':\r
+ n++;\r
+ break;\r
+ case 'd': case 'u': case 'i': case 'x':\r
+ (void) va_arg(count, int);\r
+#ifdef HAVE_LONG_LONG\r
+ /* Need at most\r
+ ceil(log10(256)*SIZEOF_LONG_LONG) digits,\r
+ plus 1 for the sign. 53/22 is an upper\r
+ bound for log10(256). */\r
+ if (longlongflag)\r
+ n += 2 + (SIZEOF_LONG_LONG*53-1) / 22;\r
+ else\r
+#endif\r
+ /* 20 bytes is enough to hold a 64-bit\r
+ integer. Decimal takes the most\r
+ space. This isn't enough for\r
+ octal. */\r
+ n += 20;\r
+\r
+ break;\r
+ case 's':\r
+ s = va_arg(count, char*);\r
+ n += strlen(s);\r
+ break;\r
+ case 'p':\r
+ (void) va_arg(count, int);\r
+ /* maximum 64-bit pointer representation:\r
+ * 0xffffffffffffffff\r
+ * so 19 characters is enough.\r
+ * XXX I count 18 -- what's the extra for?\r
+ */\r
+ n += 19;\r
+ break;\r
+ default:\r
+ /* if we stumble upon an unknown\r
+ formatting code, copy the rest of\r
+ the format string to the output\r
+ string. (we cannot just skip the\r
+ code, since there's no way to know\r
+ what's in the argument list) */\r
+ n += strlen(p);\r
+ goto expand;\r
+ }\r
+ } else\r
+ n++;\r
+ }\r
+ expand:\r
+ /* step 2: fill the buffer */\r
+ /* Since we've analyzed how much space we need for the worst case,\r
+ use sprintf directly instead of the slower PyOS_snprintf. */\r
+ string = PyString_FromStringAndSize(NULL, n);\r
+ if (!string)\r
+ return NULL;\r
+\r
+ s = PyString_AsString(string);\r
+\r
+ for (f = format; *f; f++) {\r
+ if (*f == '%') {\r
+ const char* p = f++;\r
+ Py_ssize_t i;\r
+ int longflag = 0;\r
+#ifdef HAVE_LONG_LONG\r
+ int longlongflag = 0;\r
+#endif\r
+ int size_tflag = 0;\r
+ /* parse the width.precision part (we're only\r
+ interested in the precision value, if any) */\r
+ n = 0;\r
+ while (isdigit(Py_CHARMASK(*f)))\r
+ n = (n*10) + *f++ - '0';\r
+ if (*f == '.') {\r
+ f++;\r
+ n = 0;\r
+ while (isdigit(Py_CHARMASK(*f)))\r
+ n = (n*10) + *f++ - '0';\r
+ }\r
+ while (*f && *f != '%' && !isalpha(Py_CHARMASK(*f)))\r
+ f++;\r
+ /* Handle %ld, %lu, %lld and %llu. */\r
+ if (*f == 'l') {\r
+ if (f[1] == 'd' || f[1] == 'u') {\r
+ longflag = 1;\r
+ ++f;\r
+ }\r
+#ifdef HAVE_LONG_LONG\r
+ else if (f[1] == 'l' &&\r
+ (f[2] == 'd' || f[2] == 'u')) {\r
+ longlongflag = 1;\r
+ f += 2;\r
+ }\r
+#endif\r
+ }\r
+ /* handle the size_t flag. */\r
+ else if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) {\r
+ size_tflag = 1;\r
+ ++f;\r
+ }\r
+\r
+ switch (*f) {\r
+ case 'c':\r
+ *s++ = va_arg(vargs, int);\r
+ break;\r
+ case 'd':\r
+ if (longflag)\r
+ sprintf(s, "%ld", va_arg(vargs, long));\r
+#ifdef HAVE_LONG_LONG\r
+ else if (longlongflag)\r
+ sprintf(s, "%" PY_FORMAT_LONG_LONG "d",\r
+ va_arg(vargs, PY_LONG_LONG));\r
+#endif\r
+ else if (size_tflag)\r
+ sprintf(s, "%" PY_FORMAT_SIZE_T "d",\r
+ va_arg(vargs, Py_ssize_t));\r
+ else\r
+ sprintf(s, "%d", va_arg(vargs, int));\r
+ s += strlen(s);\r
+ break;\r
+ case 'u':\r
+ if (longflag)\r
+ sprintf(s, "%lu",\r
+ va_arg(vargs, unsigned long));\r
+#ifdef HAVE_LONG_LONG\r
+ else if (longlongflag)\r
+ sprintf(s, "%" PY_FORMAT_LONG_LONG "u",\r
+ va_arg(vargs, PY_LONG_LONG));\r
+#endif\r
+ else if (size_tflag)\r
+ sprintf(s, "%" PY_FORMAT_SIZE_T "u",\r
+ va_arg(vargs, size_t));\r
+ else\r
+ sprintf(s, "%u",\r
+ va_arg(vargs, unsigned int));\r
+ s += strlen(s);\r
+ break;\r
+ case 'i':\r
+ sprintf(s, "%i", va_arg(vargs, int));\r
+ s += strlen(s);\r
+ break;\r
+ case 'x':\r
+ sprintf(s, "%x", va_arg(vargs, int));\r
+ s += strlen(s);\r
+ break;\r
+ case 's':\r
+ p = va_arg(vargs, char*);\r
+ i = strlen(p);\r
+ if (n > 0 && i > n)\r
+ i = n;\r
+ Py_MEMCPY(s, p, i);\r
+ s += i;\r
+ break;\r
+ case 'p':\r
+ sprintf(s, "%p", va_arg(vargs, void*));\r
+ /* %p is ill-defined: ensure leading 0x. */\r
+ if (s[1] == 'X')\r
+ s[1] = 'x';\r
+ else if (s[1] != 'x') {\r
+ memmove(s+2, s, strlen(s)+1);\r
+ s[0] = '0';\r
+ s[1] = 'x';\r
+ }\r
+ s += strlen(s);\r
+ break;\r
+ case '%':\r
+ *s++ = '%';\r
+ break;\r
+ default:\r
+ strcpy(s, p);\r
+ s += strlen(s);\r
+ goto end;\r
+ }\r
+ } else\r
+ *s++ = *f;\r
+ }\r
+\r
+ end:\r
+ if (_PyString_Resize(&string, s - PyString_AS_STRING(string)))\r
+ return NULL;\r
+ return string;\r
+}\r
+\r
+PyObject *\r
+PyString_FromFormat(const char *format, ...)\r
+{\r
+ PyObject* ret;\r
+ va_list vargs;\r
+\r
+#ifdef HAVE_STDARG_PROTOTYPES\r
+ va_start(vargs, format);\r
+#else\r
+ va_start(vargs);\r
+#endif\r
+ ret = PyString_FromFormatV(format, vargs);\r
+ va_end(vargs);\r
+ return ret;\r
+}\r
+\r
+\r
+PyObject *PyString_Decode(const char *s,\r
+ Py_ssize_t size,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v, *str;\r
+\r
+ str = PyString_FromStringAndSize(s, size);\r
+ if (str == NULL)\r
+ return NULL;\r
+ v = PyString_AsDecodedString(str, encoding, errors);\r
+ Py_DECREF(str);\r
+ return v;\r
+}\r
+\r
+PyObject *PyString_AsDecodedObject(PyObject *str,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v;\r
+\r
+ if (!PyString_Check(str)) {\r
+ PyErr_BadArgument();\r
+ goto onError;\r
+ }\r
+\r
+ if (encoding == NULL) {\r
+#ifdef Py_USING_UNICODE\r
+ encoding = PyUnicode_GetDefaultEncoding();\r
+#else\r
+ PyErr_SetString(PyExc_ValueError, "no encoding specified");\r
+ goto onError;\r
+#endif\r
+ }\r
+\r
+ /* Decode via the codec registry */\r
+ v = PyCodec_Decode(str, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyString_AsDecodedString(PyObject *str,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v;\r
+\r
+ v = PyString_AsDecodedObject(str, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+\r
+#ifdef Py_USING_UNICODE\r
+ /* Convert Unicode to a string using the default encoding */\r
+ if (PyUnicode_Check(v)) {\r
+ PyObject *temp = v;\r
+ v = PyUnicode_AsEncodedString(v, NULL, NULL);\r
+ Py_DECREF(temp);\r
+ if (v == NULL)\r
+ goto onError;\r
+ }\r
+#endif\r
+ if (!PyString_Check(v)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "decoder did not return a string object (type=%.400s)",\r
+ Py_TYPE(v)->tp_name);\r
+ Py_DECREF(v);\r
+ goto onError;\r
+ }\r
+\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyString_Encode(const char *s,\r
+ Py_ssize_t size,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v, *str;\r
+\r
+ str = PyString_FromStringAndSize(s, size);\r
+ if (str == NULL)\r
+ return NULL;\r
+ v = PyString_AsEncodedString(str, encoding, errors);\r
+ Py_DECREF(str);\r
+ return v;\r
+}\r
+\r
+PyObject *PyString_AsEncodedObject(PyObject *str,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v;\r
+\r
+ if (!PyString_Check(str)) {\r
+ PyErr_BadArgument();\r
+ goto onError;\r
+ }\r
+\r
+ if (encoding == NULL) {\r
+#ifdef Py_USING_UNICODE\r
+ encoding = PyUnicode_GetDefaultEncoding();\r
+#else\r
+ PyErr_SetString(PyExc_ValueError, "no encoding specified");\r
+ goto onError;\r
+#endif\r
+ }\r
+\r
+ /* Encode via the codec registry */\r
+ v = PyCodec_Encode(str, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyString_AsEncodedString(PyObject *str,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v;\r
+\r
+ v = PyString_AsEncodedObject(str, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+\r
+#ifdef Py_USING_UNICODE\r
+ /* Convert Unicode to a string using the default encoding */\r
+ if (PyUnicode_Check(v)) {\r
+ PyObject *temp = v;\r
+ v = PyUnicode_AsEncodedString(v, NULL, NULL);\r
+ Py_DECREF(temp);\r
+ if (v == NULL)\r
+ goto onError;\r
+ }\r
+#endif\r
+ if (!PyString_Check(v)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "encoder did not return a string object (type=%.400s)",\r
+ Py_TYPE(v)->tp_name);\r
+ Py_DECREF(v);\r
+ goto onError;\r
+ }\r
+\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+static void\r
+string_dealloc(PyObject *op)\r
+{\r
+ switch (PyString_CHECK_INTERNED(op)) {\r
+ case SSTATE_NOT_INTERNED:\r
+ break;\r
+\r
+ case SSTATE_INTERNED_MORTAL:\r
+ /* revive dead object temporarily for DelItem */\r
+ Py_REFCNT(op) = 3;\r
+ if (PyDict_DelItem(interned, op) != 0)\r
+ Py_FatalError(\r
+ "deletion of interned string failed");\r
+ break;\r
+\r
+ case SSTATE_INTERNED_IMMORTAL:\r
+ Py_FatalError("Immortal interned string died.");\r
+\r
+ default:\r
+ Py_FatalError("Inconsistent interned string state.");\r
+ }\r
+ Py_TYPE(op)->tp_free(op);\r
+}\r
+\r
+/* Unescape a backslash-escaped string. If unicode is non-zero,\r
+ the string is a u-literal. If recode_encoding is non-zero,\r
+ the string is UTF-8 encoded and should be re-encoded in the\r
+ specified encoding. */\r
+\r
+PyObject *PyString_DecodeEscape(const char *s,\r
+ Py_ssize_t len,\r
+ const char *errors,\r
+ Py_ssize_t unicode,\r
+ const char *recode_encoding)\r
+{\r
+ int c;\r
+ char *p, *buf;\r
+ const char *end;\r
+ PyObject *v;\r
+ Py_ssize_t newlen = recode_encoding ? 4*len:len;\r
+ v = PyString_FromStringAndSize((char *)NULL, newlen);\r
+ if (v == NULL)\r
+ return NULL;\r
+ p = buf = PyString_AsString(v);\r
+ end = s + len;\r
+ while (s < end) {\r
+ if (*s != '\\') {\r
+ non_esc:\r
+#ifdef Py_USING_UNICODE\r
+ if (recode_encoding && (*s & 0x80)) {\r
+ PyObject *u, *w;\r
+ char *r;\r
+ const char* t;\r
+ Py_ssize_t rn;\r
+ t = s;\r
+ /* Decode non-ASCII bytes as UTF-8. */\r
+ while (t < end && (*t & 0x80)) t++;\r
+ u = PyUnicode_DecodeUTF8(s, t - s, errors);\r
+ if(!u) goto failed;\r
+\r
+ /* Recode them in target encoding. */\r
+ w = PyUnicode_AsEncodedString(\r
+ u, recode_encoding, errors);\r
+ Py_DECREF(u);\r
+ if (!w) goto failed;\r
+\r
+ /* Append bytes to output buffer. */\r
+ assert(PyString_Check(w));\r
+ r = PyString_AS_STRING(w);\r
+ rn = PyString_GET_SIZE(w);\r
+ Py_MEMCPY(p, r, rn);\r
+ p += rn;\r
+ Py_DECREF(w);\r
+ s = t;\r
+ } else {\r
+ *p++ = *s++;\r
+ }\r
+#else\r
+ *p++ = *s++;\r
+#endif\r
+ continue;\r
+ }\r
+ s++;\r
+ if (s==end) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Trailing \\ in string");\r
+ goto failed;\r
+ }\r
+ switch (*s++) {\r
+ /* XXX This assumes ASCII! */\r
+ case '\n': break;\r
+ case '\\': *p++ = '\\'; break;\r
+ case '\'': *p++ = '\''; break;\r
+ case '\"': *p++ = '\"'; break;\r
+ case 'b': *p++ = '\b'; break;\r
+ case 'f': *p++ = '\014'; break; /* FF */\r
+ case 't': *p++ = '\t'; break;\r
+ case 'n': *p++ = '\n'; break;\r
+ case 'r': *p++ = '\r'; break;\r
+ case 'v': *p++ = '\013'; break; /* VT */\r
+ case 'a': *p++ = '\007'; break; /* BEL, not classic C */\r
+ case '0': case '1': case '2': case '3':\r
+ case '4': case '5': case '6': case '7':\r
+ c = s[-1] - '0';\r
+ if (s < end && '0' <= *s && *s <= '7') {\r
+ c = (c<<3) + *s++ - '0';\r
+ if (s < end && '0' <= *s && *s <= '7')\r
+ c = (c<<3) + *s++ - '0';\r
+ }\r
+ *p++ = c;\r
+ break;\r
+ case 'x':\r
+ if (s+1 < end &&\r
+ isxdigit(Py_CHARMASK(s[0])) &&\r
+ isxdigit(Py_CHARMASK(s[1])))\r
+ {\r
+ unsigned int x = 0;\r
+ c = Py_CHARMASK(*s);\r
+ s++;\r
+ if (isdigit(c))\r
+ x = c - '0';\r
+ else if (islower(c))\r
+ x = 10 + c - 'a';\r
+ else\r
+ x = 10 + c - 'A';\r
+ x = x << 4;\r
+ c = Py_CHARMASK(*s);\r
+ s++;\r
+ if (isdigit(c))\r
+ x += c - '0';\r
+ else if (islower(c))\r
+ x += 10 + c - 'a';\r
+ else\r
+ x += 10 + c - 'A';\r
+ *p++ = x;\r
+ break;\r
+ }\r
+ if (!errors || strcmp(errors, "strict") == 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "invalid \\x escape");\r
+ goto failed;\r
+ }\r
+ if (strcmp(errors, "replace") == 0) {\r
+ *p++ = '?';\r
+ } else if (strcmp(errors, "ignore") == 0)\r
+ /* do nothing */;\r
+ else {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "decoding error; "\r
+ "unknown error handling code: %.400s",\r
+ errors);\r
+ goto failed;\r
+ }\r
+ /* skip \x */\r
+ if (s < end && isxdigit(Py_CHARMASK(s[0])))\r
+ s++; /* and a hexdigit */\r
+ break;\r
+#ifndef Py_USING_UNICODE\r
+ case 'u':\r
+ case 'U':\r
+ case 'N':\r
+ if (unicode) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "Unicode escapes not legal "\r
+ "when Unicode disabled");\r
+ goto failed;\r
+ }\r
+#endif\r
+ default:\r
+ *p++ = '\\';\r
+ s--;\r
+ goto non_esc; /* an arbitrary number of unescaped\r
+ UTF-8 bytes may follow. */\r
+ }\r
+ }\r
+ if (p-buf < newlen)\r
+ _PyString_Resize(&v, p - buf); /* v is cleared on error */\r
+ return v;\r
+ failed:\r
+ Py_DECREF(v);\r
+ return NULL;\r
+}\r
+\r
+/* -------------------------------------------------------------------- */\r
+/* object api */\r
+\r
+static Py_ssize_t\r
+string_getsize(register PyObject *op)\r
+{\r
+ char *s;\r
+ Py_ssize_t len;\r
+ if (PyString_AsStringAndSize(op, &s, &len))\r
+ return -1;\r
+ return len;\r
+}\r
+\r
+static /*const*/ char *\r
+string_getbuffer(register PyObject *op)\r
+{\r
+ char *s;\r
+ Py_ssize_t len;\r
+ if (PyString_AsStringAndSize(op, &s, &len))\r
+ return NULL;\r
+ return s;\r
+}\r
+\r
+Py_ssize_t\r
+PyString_Size(register PyObject *op)\r
+{\r
+ if (!PyString_Check(op))\r
+ return string_getsize(op);\r
+ return Py_SIZE(op);\r
+}\r
+\r
+/*const*/ char *\r
+PyString_AsString(register PyObject *op)\r
+{\r
+ if (!PyString_Check(op))\r
+ return string_getbuffer(op);\r
+ return ((PyStringObject *)op) -> ob_sval;\r
+}\r
+\r
+int\r
+PyString_AsStringAndSize(register PyObject *obj,\r
+ register char **s,\r
+ register Py_ssize_t *len)\r
+{\r
+ if (s == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+\r
+ if (!PyString_Check(obj)) {\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(obj)) {\r
+ obj = _PyUnicode_AsDefaultEncodedString(obj, NULL);\r
+ if (obj == NULL)\r
+ return -1;\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "expected string or Unicode object, "\r
+ "%.200s found", Py_TYPE(obj)->tp_name);\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ *s = PyString_AS_STRING(obj);\r
+ if (len != NULL)\r
+ *len = PyString_GET_SIZE(obj);\r
+ else if (strlen(*s) != (size_t)PyString_GET_SIZE(obj)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "expected string without null bytes");\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+/* -------------------------------------------------------------------- */\r
+/* Methods */\r
+\r
+#include "stringlib/stringdefs.h"\r
+#include "stringlib/fastsearch.h"\r
+\r
+#include "stringlib/count.h"\r
+#include "stringlib/find.h"\r
+#include "stringlib/partition.h"\r
+#include "stringlib/split.h"\r
+\r
+#define _Py_InsertThousandsGrouping _PyString_InsertThousandsGrouping\r
+#include "stringlib/localeutil.h"\r
+\r
+\r
+\r
+static int\r
+string_print(PyStringObject *op, FILE *fp, int flags)\r
+{\r
+ Py_ssize_t i, str_len;\r
+ char c;\r
+ int quote;\r
+\r
+ /* XXX Ought to check for interrupts when writing long strings */\r
+ if (! PyString_CheckExact(op)) {\r
+ int ret;\r
+ /* A str subclass may have its own __str__ method. */\r
+ op = (PyStringObject *) PyObject_Str((PyObject *)op);\r
+ if (op == NULL)\r
+ return -1;\r
+ ret = string_print(op, fp, flags);\r
+ Py_DECREF(op);\r
+ return ret;\r
+ }\r
+ if (flags & Py_PRINT_RAW) {\r
+ char *data = op->ob_sval;\r
+ Py_ssize_t size = Py_SIZE(op);\r
+ Py_BEGIN_ALLOW_THREADS\r
+ while (size > INT_MAX) {\r
+ /* Very long strings cannot be written atomically.\r
+ * But don't write exactly INT_MAX bytes at a time\r
+ * to avoid memory aligment issues.\r
+ */\r
+ const int chunk_size = INT_MAX & ~0x3FFF;\r
+ fwrite(data, 1, chunk_size, fp);\r
+ data += chunk_size;\r
+ size -= chunk_size;\r
+ }\r
+#ifdef __VMS\r
+ if (size) fwrite(data, (size_t)size, 1, fp);\r
+#else\r
+ fwrite(data, 1, (size_t)size, fp);\r
+#endif\r
+ Py_END_ALLOW_THREADS\r
+ return 0;\r
+ }\r
+\r
+ /* figure out which quote to use; single is preferred */\r
+ quote = '\'';\r
+ if (memchr(op->ob_sval, '\'', Py_SIZE(op)) &&\r
+ !memchr(op->ob_sval, '"', Py_SIZE(op)))\r
+ quote = '"';\r
+\r
+ str_len = Py_SIZE(op);\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fputc(quote, fp);\r
+ for (i = 0; i < str_len; i++) {\r
+ /* Since strings are immutable and the caller should have a\r
+ reference, accessing the interal buffer should not be an issue\r
+ with the GIL released. */\r
+ c = op->ob_sval[i];\r
+ if (c == quote || c == '\\')\r
+ fprintf(fp, "\\%c", c);\r
+ else if (c == '\t')\r
+ fprintf(fp, "\\t");\r
+ else if (c == '\n')\r
+ fprintf(fp, "\\n");\r
+ else if (c == '\r')\r
+ fprintf(fp, "\\r");\r
+ else if (c < ' ' || c >= 0x7f)\r
+ fprintf(fp, "\\x%02x", c & 0xff);\r
+ else\r
+ fputc(c, fp);\r
+ }\r
+ fputc(quote, fp);\r
+ Py_END_ALLOW_THREADS\r
+ return 0;\r
+}\r
+\r
+PyObject *\r
+PyString_Repr(PyObject *obj, int smartquotes)\r
+{\r
+ register PyStringObject* op = (PyStringObject*) obj;\r
+ size_t newsize;\r
+ PyObject *v;\r
+ if (Py_SIZE(op) > (PY_SSIZE_T_MAX - 2)/4) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "string is too large to make repr");\r
+ return NULL;\r
+ }\r
+ newsize = 2 + 4*Py_SIZE(op);\r
+ v = PyString_FromStringAndSize((char *)NULL, newsize);\r
+ if (v == NULL) {\r
+ return NULL;\r
+ }\r
+ else {\r
+ register Py_ssize_t i;\r
+ register char c;\r
+ register char *p;\r
+ int quote;\r
+\r
+ /* figure out which quote to use; single is preferred */\r
+ quote = '\'';\r
+ if (smartquotes &&\r
+ memchr(op->ob_sval, '\'', Py_SIZE(op)) &&\r
+ !memchr(op->ob_sval, '"', Py_SIZE(op)))\r
+ quote = '"';\r
+\r
+ p = PyString_AS_STRING(v);\r
+ *p++ = quote;\r
+ for (i = 0; i < Py_SIZE(op); i++) {\r
+ /* There's at least enough room for a hex escape\r
+ and a closing quote. */\r
+ assert(newsize - (p - PyString_AS_STRING(v)) >= 5);\r
+ c = op->ob_sval[i];\r
+ if (c == quote || c == '\\')\r
+ *p++ = '\\', *p++ = c;\r
+ else if (c == '\t')\r
+ *p++ = '\\', *p++ = 't';\r
+ else if (c == '\n')\r
+ *p++ = '\\', *p++ = 'n';\r
+ else if (c == '\r')\r
+ *p++ = '\\', *p++ = 'r';\r
+ else if (c < ' ' || c >= 0x7f) {\r
+ /* For performance, we don't want to call\r
+ PyOS_snprintf here (extra layers of\r
+ function call). */\r
+ sprintf(p, "\\x%02x", c & 0xff);\r
+ p += 4;\r
+ }\r
+ else\r
+ *p++ = c;\r
+ }\r
+ assert(newsize - (p - PyString_AS_STRING(v)) >= 1);\r
+ *p++ = quote;\r
+ *p = '\0';\r
+ if (_PyString_Resize(&v, (p - PyString_AS_STRING(v))))\r
+ return NULL;\r
+ return v;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+string_repr(PyObject *op)\r
+{\r
+ return PyString_Repr(op, 1);\r
+}\r
+\r
+static PyObject *\r
+string_str(PyObject *s)\r
+{\r
+ assert(PyString_Check(s));\r
+ if (PyString_CheckExact(s)) {\r
+ Py_INCREF(s);\r
+ return s;\r
+ }\r
+ else {\r
+ /* Subtype -- return genuine string with the same value. */\r
+ PyStringObject *t = (PyStringObject *) s;\r
+ return PyString_FromStringAndSize(t->ob_sval, Py_SIZE(t));\r
+ }\r
+}\r
+\r
+static Py_ssize_t\r
+string_length(PyStringObject *a)\r
+{\r
+ return Py_SIZE(a);\r
+}\r
+\r
+static PyObject *\r
+string_concat(register PyStringObject *a, register PyObject *bb)\r
+{\r
+ register Py_ssize_t size;\r
+ register PyStringObject *op;\r
+ if (!PyString_Check(bb)) {\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(bb))\r
+ return PyUnicode_Concat((PyObject *)a, bb);\r
+#endif\r
+ if (PyByteArray_Check(bb))\r
+ return PyByteArray_Concat((PyObject *)a, bb);\r
+ PyErr_Format(PyExc_TypeError,\r
+ "cannot concatenate 'str' and '%.200s' objects",\r
+ Py_TYPE(bb)->tp_name);\r
+ return NULL;\r
+ }\r
+#define b ((PyStringObject *)bb)\r
+ /* Optimize cases with empty left or right operand */\r
+ if ((Py_SIZE(a) == 0 || Py_SIZE(b) == 0) &&\r
+ PyString_CheckExact(a) && PyString_CheckExact(b)) {\r
+ if (Py_SIZE(a) == 0) {\r
+ Py_INCREF(bb);\r
+ return bb;\r
+ }\r
+ Py_INCREF(a);\r
+ return (PyObject *)a;\r
+ }\r
+ size = Py_SIZE(a) + Py_SIZE(b);\r
+ /* Check that string sizes are not negative, to prevent an\r
+ overflow in cases where we are passed incorrectly-created\r
+ strings with negative lengths (due to a bug in other code).\r
+ */\r
+ if (Py_SIZE(a) < 0 || Py_SIZE(b) < 0 ||\r
+ Py_SIZE(a) > PY_SSIZE_T_MAX - Py_SIZE(b)) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "strings are too large to concat");\r
+ return NULL;\r
+ }\r
+\r
+ /* Inline PyObject_NewVar */\r
+ if (size > PY_SSIZE_T_MAX - PyStringObject_SIZE) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "strings are too large to concat");\r
+ return NULL;\r
+ }\r
+ op = (PyStringObject *)PyObject_MALLOC(PyStringObject_SIZE + size);\r
+ if (op == NULL)\r
+ return PyErr_NoMemory();\r
+ PyObject_INIT_VAR(op, &PyString_Type, size);\r
+ op->ob_shash = -1;\r
+ op->ob_sstate = SSTATE_NOT_INTERNED;\r
+ Py_MEMCPY(op->ob_sval, a->ob_sval, Py_SIZE(a));\r
+ Py_MEMCPY(op->ob_sval + Py_SIZE(a), b->ob_sval, Py_SIZE(b));\r
+ op->ob_sval[size] = '\0';\r
+ return (PyObject *) op;\r
+#undef b\r
+}\r
+\r
+static PyObject *\r
+string_repeat(register PyStringObject *a, register Py_ssize_t n)\r
+{\r
+ register Py_ssize_t i;\r
+ register Py_ssize_t j;\r
+ register Py_ssize_t size;\r
+ register PyStringObject *op;\r
+ size_t nbytes;\r
+ if (n < 0)\r
+ n = 0;\r
+ /* watch out for overflows: the size can overflow int,\r
+ * and the # of bytes needed can overflow size_t\r
+ */\r
+ size = Py_SIZE(a) * n;\r
+ if (n && size / n != Py_SIZE(a)) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "repeated string is too long");\r
+ return NULL;\r
+ }\r
+ if (size == Py_SIZE(a) && PyString_CheckExact(a)) {\r
+ Py_INCREF(a);\r
+ return (PyObject *)a;\r
+ }\r
+ nbytes = (size_t)size;\r
+ if (nbytes + PyStringObject_SIZE <= nbytes) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "repeated string is too long");\r
+ return NULL;\r
+ }\r
+ op = (PyStringObject *)PyObject_MALLOC(PyStringObject_SIZE + nbytes);\r
+ if (op == NULL)\r
+ return PyErr_NoMemory();\r
+ PyObject_INIT_VAR(op, &PyString_Type, size);\r
+ op->ob_shash = -1;\r
+ op->ob_sstate = SSTATE_NOT_INTERNED;\r
+ op->ob_sval[size] = '\0';\r
+ if (Py_SIZE(a) == 1 && n > 0) {\r
+ memset(op->ob_sval, a->ob_sval[0] , n);\r
+ return (PyObject *) op;\r
+ }\r
+ i = 0;\r
+ if (i < size) {\r
+ Py_MEMCPY(op->ob_sval, a->ob_sval, Py_SIZE(a));\r
+ i = Py_SIZE(a);\r
+ }\r
+ while (i < size) {\r
+ j = (i <= size-i) ? i : size-i;\r
+ Py_MEMCPY(op->ob_sval+i, op->ob_sval, j);\r
+ i += j;\r
+ }\r
+ return (PyObject *) op;\r
+}\r
+\r
+/* String slice a[i:j] consists of characters a[i] ... a[j-1] */\r
+\r
+static PyObject *\r
+string_slice(register PyStringObject *a, register Py_ssize_t i,\r
+ register Py_ssize_t j)\r
+ /* j -- may be negative! */\r
+{\r
+ if (i < 0)\r
+ i = 0;\r
+ if (j < 0)\r
+ j = 0; /* Avoid signed/unsigned bug in next line */\r
+ if (j > Py_SIZE(a))\r
+ j = Py_SIZE(a);\r
+ if (i == 0 && j == Py_SIZE(a) && PyString_CheckExact(a)) {\r
+ /* It's the same as a */\r
+ Py_INCREF(a);\r
+ return (PyObject *)a;\r
+ }\r
+ if (j < i)\r
+ j = i;\r
+ return PyString_FromStringAndSize(a->ob_sval + i, j-i);\r
+}\r
+\r
+static int\r
+string_contains(PyObject *str_obj, PyObject *sub_obj)\r
+{\r
+ if (!PyString_CheckExact(sub_obj)) {\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(sub_obj))\r
+ return PyUnicode_Contains(str_obj, sub_obj);\r
+#endif\r
+ if (!PyString_Check(sub_obj)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "'in <string>' requires string as left operand, "\r
+ "not %.200s", Py_TYPE(sub_obj)->tp_name);\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ return stringlib_contains_obj(str_obj, sub_obj);\r
+}\r
+\r
+static PyObject *\r
+string_item(PyStringObject *a, register Py_ssize_t i)\r
+{\r
+ char pchar;\r
+ PyObject *v;\r
+ if (i < 0 || i >= Py_SIZE(a)) {\r
+ PyErr_SetString(PyExc_IndexError, "string index out of range");\r
+ return NULL;\r
+ }\r
+ pchar = a->ob_sval[i];\r
+ v = (PyObject *)characters[pchar & UCHAR_MAX];\r
+ if (v == NULL)\r
+ v = PyString_FromStringAndSize(&pchar, 1);\r
+ else {\r
+#ifdef COUNT_ALLOCS\r
+ one_strings++;\r
+#endif\r
+ Py_INCREF(v);\r
+ }\r
+ return v;\r
+}\r
+\r
+static PyObject*\r
+string_richcompare(PyStringObject *a, PyStringObject *b, int op)\r
+{\r
+ int c;\r
+ Py_ssize_t len_a, len_b;\r
+ Py_ssize_t min_len;\r
+ PyObject *result;\r
+\r
+ /* Make sure both arguments are strings. */\r
+ if (!(PyString_Check(a) && PyString_Check(b))) {\r
+ result = Py_NotImplemented;\r
+ goto out;\r
+ }\r
+ if (a == b) {\r
+ switch (op) {\r
+ case Py_EQ:case Py_LE:case Py_GE:\r
+ result = Py_True;\r
+ goto out;\r
+ case Py_NE:case Py_LT:case Py_GT:\r
+ result = Py_False;\r
+ goto out;\r
+ }\r
+ }\r
+ if (op == Py_EQ) {\r
+ /* Supporting Py_NE here as well does not save\r
+ much time, since Py_NE is rarely used. */\r
+ if (Py_SIZE(a) == Py_SIZE(b)\r
+ && (a->ob_sval[0] == b->ob_sval[0]\r
+ && memcmp(a->ob_sval, b->ob_sval, Py_SIZE(a)) == 0)) {\r
+ result = Py_True;\r
+ } else {\r
+ result = Py_False;\r
+ }\r
+ goto out;\r
+ }\r
+ len_a = Py_SIZE(a); len_b = Py_SIZE(b);\r
+ min_len = (len_a < len_b) ? len_a : len_b;\r
+ if (min_len > 0) {\r
+ c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);\r
+ if (c==0)\r
+ c = memcmp(a->ob_sval, b->ob_sval, min_len);\r
+ } else\r
+ c = 0;\r
+ if (c == 0)\r
+ c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;\r
+ switch (op) {\r
+ case Py_LT: c = c < 0; break;\r
+ case Py_LE: c = c <= 0; break;\r
+ case Py_EQ: assert(0); break; /* unreachable */\r
+ case Py_NE: c = c != 0; break;\r
+ case Py_GT: c = c > 0; break;\r
+ case Py_GE: c = c >= 0; break;\r
+ default:\r
+ result = Py_NotImplemented;\r
+ goto out;\r
+ }\r
+ result = c ? Py_True : Py_False;\r
+ out:\r
+ Py_INCREF(result);\r
+ return result;\r
+}\r
+\r
+int\r
+_PyString_Eq(PyObject *o1, PyObject *o2)\r
+{\r
+ PyStringObject *a = (PyStringObject*) o1;\r
+ PyStringObject *b = (PyStringObject*) o2;\r
+ return Py_SIZE(a) == Py_SIZE(b)\r
+ && memcmp(a->ob_sval, b->ob_sval, Py_SIZE(a)) == 0;\r
+}\r
+\r
+static long\r
+string_hash(PyStringObject *a)\r
+{\r
+ register Py_ssize_t len;\r
+ register unsigned char *p;\r
+ register long x;\r
+\r
+#ifdef Py_DEBUG\r
+ assert(_Py_HashSecret_Initialized);\r
+#endif\r
+ if (a->ob_shash != -1)\r
+ return a->ob_shash;\r
+ len = Py_SIZE(a);\r
+ /*\r
+ We make the hash of the empty string be 0, rather than using\r
+ (prefix ^ suffix), since this slightly obfuscates the hash secret\r
+ */\r
+ if (len == 0) {\r
+ a->ob_shash = 0;\r
+ return 0;\r
+ }\r
+ p = (unsigned char *) a->ob_sval;\r
+ x = _Py_HashSecret.prefix;\r
+ x ^= *p << 7;\r
+ while (--len >= 0)\r
+ x = (1000003*x) ^ *p++;\r
+ x ^= Py_SIZE(a);\r
+ x ^= _Py_HashSecret.suffix;\r
+ if (x == -1)\r
+ x = -2;\r
+ a->ob_shash = x;\r
+ return x;\r
+}\r
+\r
+static PyObject*\r
+string_subscript(PyStringObject* self, PyObject* item)\r
+{\r
+ if (PyIndex_Check(item)) {\r
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ if (i < 0)\r
+ i += PyString_GET_SIZE(self);\r
+ return string_item(self, i);\r
+ }\r
+ else if (PySlice_Check(item)) {\r
+ Py_ssize_t start, stop, step, slicelength, cur, i;\r
+ char* source_buf;\r
+ char* result_buf;\r
+ PyObject* result;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject*)item,\r
+ PyString_GET_SIZE(self),\r
+ &start, &stop, &step, &slicelength) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ if (slicelength <= 0) {\r
+ return PyString_FromStringAndSize("", 0);\r
+ }\r
+ else if (start == 0 && step == 1 &&\r
+ slicelength == PyString_GET_SIZE(self) &&\r
+ PyString_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+ }\r
+ else if (step == 1) {\r
+ return PyString_FromStringAndSize(\r
+ PyString_AS_STRING(self) + start,\r
+ slicelength);\r
+ }\r
+ else {\r
+ source_buf = PyString_AsString((PyObject*)self);\r
+ result_buf = (char *)PyMem_Malloc(slicelength);\r
+ if (result_buf == NULL)\r
+ return PyErr_NoMemory();\r
+\r
+ for (cur = start, i = 0; i < slicelength;\r
+ cur += step, i++) {\r
+ result_buf[i] = source_buf[cur];\r
+ }\r
+\r
+ result = PyString_FromStringAndSize(result_buf,\r
+ slicelength);\r
+ PyMem_Free(result_buf);\r
+ return result;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "string indices must be integers, not %.200s",\r
+ Py_TYPE(item)->tp_name);\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static Py_ssize_t\r
+string_buffer_getreadbuf(PyStringObject *self, Py_ssize_t index, const void **ptr)\r
+{\r
+ if ( index != 0 ) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent string segment");\r
+ return -1;\r
+ }\r
+ *ptr = (void *)self->ob_sval;\r
+ return Py_SIZE(self);\r
+}\r
+\r
+static Py_ssize_t\r
+string_buffer_getwritebuf(PyStringObject *self, Py_ssize_t index, const void **ptr)\r
+{\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "Cannot use string as modifiable buffer");\r
+ return -1;\r
+}\r
+\r
+static Py_ssize_t\r
+string_buffer_getsegcount(PyStringObject *self, Py_ssize_t *lenp)\r
+{\r
+ if ( lenp )\r
+ *lenp = Py_SIZE(self);\r
+ return 1;\r
+}\r
+\r
+static Py_ssize_t\r
+string_buffer_getcharbuf(PyStringObject *self, Py_ssize_t index, const char **ptr)\r
+{\r
+ if ( index != 0 ) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent string segment");\r
+ return -1;\r
+ }\r
+ *ptr = self->ob_sval;\r
+ return Py_SIZE(self);\r
+}\r
+\r
+static int\r
+string_buffer_getbuffer(PyStringObject *self, Py_buffer *view, int flags)\r
+{\r
+ return PyBuffer_FillInfo(view, (PyObject*)self,\r
+ (void *)self->ob_sval, Py_SIZE(self),\r
+ 1, flags);\r
+}\r
+\r
+static PySequenceMethods string_as_sequence = {\r
+ (lenfunc)string_length, /*sq_length*/\r
+ (binaryfunc)string_concat, /*sq_concat*/\r
+ (ssizeargfunc)string_repeat, /*sq_repeat*/\r
+ (ssizeargfunc)string_item, /*sq_item*/\r
+ (ssizessizeargfunc)string_slice, /*sq_slice*/\r
+ 0, /*sq_ass_item*/\r
+ 0, /*sq_ass_slice*/\r
+ (objobjproc)string_contains /*sq_contains*/\r
+};\r
+\r
+static PyMappingMethods string_as_mapping = {\r
+ (lenfunc)string_length,\r
+ (binaryfunc)string_subscript,\r
+ 0,\r
+};\r
+\r
+static PyBufferProcs string_as_buffer = {\r
+ (readbufferproc)string_buffer_getreadbuf,\r
+ (writebufferproc)string_buffer_getwritebuf,\r
+ (segcountproc)string_buffer_getsegcount,\r
+ (charbufferproc)string_buffer_getcharbuf,\r
+ (getbufferproc)string_buffer_getbuffer,\r
+ 0, /* XXX */\r
+};\r
+\r
+\r
+\r
+#define LEFTSTRIP 0\r
+#define RIGHTSTRIP 1\r
+#define BOTHSTRIP 2\r
+\r
+/* Arrays indexed by above */\r
+static const char *stripformat[] = {"|O:lstrip", "|O:rstrip", "|O:strip"};\r
+\r
+#define STRIPNAME(i) (stripformat[i]+3)\r
+\r
+PyDoc_STRVAR(split__doc__,\r
+"S.split([sep [,maxsplit]]) -> list of strings\n\\r
+\n\\r
+Return a list of the words in the string S, using sep as the\n\\r
+delimiter string. If maxsplit is given, at most maxsplit\n\\r
+splits are done. If sep is not specified or is None, any\n\\r
+whitespace string is a separator and empty strings are removed\n\\r
+from the result.");\r
+\r
+static PyObject *\r
+string_split(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t len = PyString_GET_SIZE(self), n;\r
+ Py_ssize_t maxsplit = -1;\r
+ const char *s = PyString_AS_STRING(self), *sub;\r
+ PyObject *subobj = Py_None;\r
+\r
+ if (!PyArg_ParseTuple(args, "|On:split", &subobj, &maxsplit))\r
+ return NULL;\r
+ if (maxsplit < 0)\r
+ maxsplit = PY_SSIZE_T_MAX;\r
+ if (subobj == Py_None)\r
+ return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);\r
+ if (PyString_Check(subobj)) {\r
+ sub = PyString_AS_STRING(subobj);\r
+ n = PyString_GET_SIZE(subobj);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(subobj))\r
+ return PyUnicode_Split((PyObject *)self, subobj, maxsplit);\r
+#endif\r
+ else if (PyObject_AsCharBuffer(subobj, &sub, &n))\r
+ return NULL;\r
+\r
+ return stringlib_split((PyObject*) self, s, len, sub, n, maxsplit);\r
+}\r
+\r
+PyDoc_STRVAR(partition__doc__,\r
+"S.partition(sep) -> (head, sep, tail)\n\\r
+\n\\r
+Search for the separator sep in S, and return the part before it,\n\\r
+the separator itself, and the part after it. If the separator is not\n\\r
+found, return S and two empty strings.");\r
+\r
+static PyObject *\r
+string_partition(PyStringObject *self, PyObject *sep_obj)\r
+{\r
+ const char *sep;\r
+ Py_ssize_t sep_len;\r
+\r
+ if (PyString_Check(sep_obj)) {\r
+ sep = PyString_AS_STRING(sep_obj);\r
+ sep_len = PyString_GET_SIZE(sep_obj);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(sep_obj))\r
+ return PyUnicode_Partition((PyObject *) self, sep_obj);\r
+#endif\r
+ else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))\r
+ return NULL;\r
+\r
+ return stringlib_partition(\r
+ (PyObject*) self,\r
+ PyString_AS_STRING(self), PyString_GET_SIZE(self),\r
+ sep_obj, sep, sep_len\r
+ );\r
+}\r
+\r
+PyDoc_STRVAR(rpartition__doc__,\r
+"S.rpartition(sep) -> (head, sep, tail)\n\\r
+\n\\r
+Search for the separator sep in S, starting at the end of S, and return\n\\r
+the part before it, the separator itself, and the part after it. If the\n\\r
+separator is not found, return two empty strings and S.");\r
+\r
+static PyObject *\r
+string_rpartition(PyStringObject *self, PyObject *sep_obj)\r
+{\r
+ const char *sep;\r
+ Py_ssize_t sep_len;\r
+\r
+ if (PyString_Check(sep_obj)) {\r
+ sep = PyString_AS_STRING(sep_obj);\r
+ sep_len = PyString_GET_SIZE(sep_obj);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(sep_obj))\r
+ return PyUnicode_RPartition((PyObject *) self, sep_obj);\r
+#endif\r
+ else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))\r
+ return NULL;\r
+\r
+ return stringlib_rpartition(\r
+ (PyObject*) self,\r
+ PyString_AS_STRING(self), PyString_GET_SIZE(self),\r
+ sep_obj, sep, sep_len\r
+ );\r
+}\r
+\r
+PyDoc_STRVAR(rsplit__doc__,\r
+"S.rsplit([sep [,maxsplit]]) -> list of strings\n\\r
+\n\\r
+Return a list of the words in the string S, using sep as the\n\\r
+delimiter string, starting at the end of the string and working\n\\r
+to the front. If maxsplit is given, at most maxsplit splits are\n\\r
+done. If sep is not specified or is None, any whitespace string\n\\r
+is a separator.");\r
+\r
+static PyObject *\r
+string_rsplit(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t len = PyString_GET_SIZE(self), n;\r
+ Py_ssize_t maxsplit = -1;\r
+ const char *s = PyString_AS_STRING(self), *sub;\r
+ PyObject *subobj = Py_None;\r
+\r
+ if (!PyArg_ParseTuple(args, "|On:rsplit", &subobj, &maxsplit))\r
+ return NULL;\r
+ if (maxsplit < 0)\r
+ maxsplit = PY_SSIZE_T_MAX;\r
+ if (subobj == Py_None)\r
+ return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);\r
+ if (PyString_Check(subobj)) {\r
+ sub = PyString_AS_STRING(subobj);\r
+ n = PyString_GET_SIZE(subobj);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(subobj))\r
+ return PyUnicode_RSplit((PyObject *)self, subobj, maxsplit);\r
+#endif\r
+ else if (PyObject_AsCharBuffer(subobj, &sub, &n))\r
+ return NULL;\r
+\r
+ return stringlib_rsplit((PyObject*) self, s, len, sub, n, maxsplit);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(join__doc__,\r
+"S.join(iterable) -> string\n\\r
+\n\\r
+Return a string which is the concatenation of the strings in the\n\\r
+iterable. The separator between elements is S.");\r
+\r
+static PyObject *\r
+string_join(PyStringObject *self, PyObject *orig)\r
+{\r
+ char *sep = PyString_AS_STRING(self);\r
+ const Py_ssize_t seplen = PyString_GET_SIZE(self);\r
+ PyObject *res = NULL;\r
+ char *p;\r
+ Py_ssize_t seqlen = 0;\r
+ size_t sz = 0;\r
+ Py_ssize_t i;\r
+ PyObject *seq, *item;\r
+\r
+ seq = PySequence_Fast(orig, "can only join an iterable");\r
+ if (seq == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ seqlen = PySequence_Size(seq);\r
+ if (seqlen == 0) {\r
+ Py_DECREF(seq);\r
+ return PyString_FromString("");\r
+ }\r
+ if (seqlen == 1) {\r
+ item = PySequence_Fast_GET_ITEM(seq, 0);\r
+ if (PyString_CheckExact(item) || PyUnicode_CheckExact(item)) {\r
+ Py_INCREF(item);\r
+ Py_DECREF(seq);\r
+ return item;\r
+ }\r
+ }\r
+\r
+ /* There are at least two things to join, or else we have a subclass\r
+ * of the builtin types in the sequence.\r
+ * Do a pre-pass to figure out the total amount of space we'll\r
+ * need (sz), see whether any argument is absurd, and defer to\r
+ * the Unicode join if appropriate.\r
+ */\r
+ for (i = 0; i < seqlen; i++) {\r
+ const size_t old_sz = sz;\r
+ item = PySequence_Fast_GET_ITEM(seq, i);\r
+ if (!PyString_Check(item)){\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(item)) {\r
+ /* Defer to Unicode join.\r
+ * CAUTION: There's no gurantee that the\r
+ * original sequence can be iterated over\r
+ * again, so we must pass seq here.\r
+ */\r
+ PyObject *result;\r
+ result = PyUnicode_Join((PyObject *)self, seq);\r
+ Py_DECREF(seq);\r
+ return result;\r
+ }\r
+#endif\r
+ PyErr_Format(PyExc_TypeError,\r
+ "sequence item %zd: expected string,"\r
+ " %.80s found",\r
+ i, Py_TYPE(item)->tp_name);\r
+ Py_DECREF(seq);\r
+ return NULL;\r
+ }\r
+ sz += PyString_GET_SIZE(item);\r
+ if (i != 0)\r
+ sz += seplen;\r
+ if (sz < old_sz || sz > PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "join() result is too long for a Python string");\r
+ Py_DECREF(seq);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ /* Allocate result space. */\r
+ res = PyString_FromStringAndSize((char*)NULL, sz);\r
+ if (res == NULL) {\r
+ Py_DECREF(seq);\r
+ return NULL;\r
+ }\r
+\r
+ /* Catenate everything. */\r
+ p = PyString_AS_STRING(res);\r
+ for (i = 0; i < seqlen; ++i) {\r
+ size_t n;\r
+ item = PySequence_Fast_GET_ITEM(seq, i);\r
+ n = PyString_GET_SIZE(item);\r
+ Py_MEMCPY(p, PyString_AS_STRING(item), n);\r
+ p += n;\r
+ if (i < seqlen - 1) {\r
+ Py_MEMCPY(p, sep, seplen);\r
+ p += seplen;\r
+ }\r
+ }\r
+\r
+ Py_DECREF(seq);\r
+ return res;\r
+}\r
+\r
+PyObject *\r
+_PyString_Join(PyObject *sep, PyObject *x)\r
+{\r
+ assert(sep != NULL && PyString_Check(sep));\r
+ assert(x != NULL);\r
+ return string_join((PyStringObject *)sep, x);\r
+}\r
+\r
+/* helper macro to fixup start/end slice values */\r
+#define ADJUST_INDICES(start, end, len) \\r
+ if (end > len) \\r
+ end = len; \\r
+ else if (end < 0) { \\r
+ end += len; \\r
+ if (end < 0) \\r
+ end = 0; \\r
+ } \\r
+ if (start < 0) { \\r
+ start += len; \\r
+ if (start < 0) \\r
+ start = 0; \\r
+ }\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+string_find_internal(PyStringObject *self, PyObject *args, int dir)\r
+{\r
+ PyObject *subobj;\r
+ const char *sub;\r
+ Py_ssize_t sub_len;\r
+ Py_ssize_t start=0, end=PY_SSIZE_T_MAX;\r
+\r
+ if (!stringlib_parse_args_finds("find/rfind/index/rindex",\r
+ args, &subobj, &start, &end))\r
+ return -2;\r
+\r
+ if (PyString_Check(subobj)) {\r
+ sub = PyString_AS_STRING(subobj);\r
+ sub_len = PyString_GET_SIZE(subobj);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(subobj))\r
+ return PyUnicode_Find(\r
+ (PyObject *)self, subobj, start, end, dir);\r
+#endif\r
+ else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len))\r
+ /* XXX - the "expected a character buffer object" is pretty\r
+ confusing for a non-expert. remap to something else ? */\r
+ return -2;\r
+\r
+ if (dir > 0)\r
+ return stringlib_find_slice(\r
+ PyString_AS_STRING(self), PyString_GET_SIZE(self),\r
+ sub, sub_len, start, end);\r
+ else\r
+ return stringlib_rfind_slice(\r
+ PyString_AS_STRING(self), PyString_GET_SIZE(self),\r
+ sub, sub_len, start, end);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(find__doc__,\r
+"S.find(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Return the lowest index in S where substring sub is found,\n\\r
+such that sub is contained within S[start:end]. Optional\n\\r
+arguments start and end are interpreted as in slice notation.\n\\r
+\n\\r
+Return -1 on failure.");\r
+\r
+static PyObject *\r
+string_find(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t result = string_find_internal(self, args, +1);\r
+ if (result == -2)\r
+ return NULL;\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(index__doc__,\r
+"S.index(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Like S.find() but raise ValueError when the substring is not found.");\r
+\r
+static PyObject *\r
+string_index(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t result = string_find_internal(self, args, +1);\r
+ if (result == -2)\r
+ return NULL;\r
+ if (result == -1) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "substring not found");\r
+ return NULL;\r
+ }\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(rfind__doc__,\r
+"S.rfind(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Return the highest index in S where substring sub is found,\n\\r
+such that sub is contained within S[start:end]. Optional\n\\r
+arguments start and end are interpreted as in slice notation.\n\\r
+\n\\r
+Return -1 on failure.");\r
+\r
+static PyObject *\r
+string_rfind(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t result = string_find_internal(self, args, -1);\r
+ if (result == -2)\r
+ return NULL;\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(rindex__doc__,\r
+"S.rindex(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Like S.rfind() but raise ValueError when the substring is not found.");\r
+\r
+static PyObject *\r
+string_rindex(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t result = string_find_internal(self, args, -1);\r
+ if (result == -2)\r
+ return NULL;\r
+ if (result == -1) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "substring not found");\r
+ return NULL;\r
+ }\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+do_xstrip(PyStringObject *self, int striptype, PyObject *sepobj)\r
+{\r
+ char *s = PyString_AS_STRING(self);\r
+ Py_ssize_t len = PyString_GET_SIZE(self);\r
+ char *sep = PyString_AS_STRING(sepobj);\r
+ Py_ssize_t seplen = PyString_GET_SIZE(sepobj);\r
+ Py_ssize_t i, j;\r
+\r
+ i = 0;\r
+ if (striptype != RIGHTSTRIP) {\r
+ while (i < len && memchr(sep, Py_CHARMASK(s[i]), seplen)) {\r
+ i++;\r
+ }\r
+ }\r
+\r
+ j = len;\r
+ if (striptype != LEFTSTRIP) {\r
+ do {\r
+ j--;\r
+ } while (j >= i && memchr(sep, Py_CHARMASK(s[j]), seplen));\r
+ j++;\r
+ }\r
+\r
+ if (i == 0 && j == len && PyString_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*)self;\r
+ }\r
+ else\r
+ return PyString_FromStringAndSize(s+i, j-i);\r
+}\r
+\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+do_strip(PyStringObject *self, int striptype)\r
+{\r
+ char *s = PyString_AS_STRING(self);\r
+ Py_ssize_t len = PyString_GET_SIZE(self), i, j;\r
+\r
+ i = 0;\r
+ if (striptype != RIGHTSTRIP) {\r
+ while (i < len && isspace(Py_CHARMASK(s[i]))) {\r
+ i++;\r
+ }\r
+ }\r
+\r
+ j = len;\r
+ if (striptype != LEFTSTRIP) {\r
+ do {\r
+ j--;\r
+ } while (j >= i && isspace(Py_CHARMASK(s[j])));\r
+ j++;\r
+ }\r
+\r
+ if (i == 0 && j == len && PyString_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*)self;\r
+ }\r
+ else\r
+ return PyString_FromStringAndSize(s+i, j-i);\r
+}\r
+\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+do_argstrip(PyStringObject *self, int striptype, PyObject *args)\r
+{\r
+ PyObject *sep = NULL;\r
+\r
+ if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sep))\r
+ return NULL;\r
+\r
+ if (sep != NULL && sep != Py_None) {\r
+ if (PyString_Check(sep))\r
+ return do_xstrip(self, striptype, sep);\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(sep)) {\r
+ PyObject *uniself = PyUnicode_FromObject((PyObject *)self);\r
+ PyObject *res;\r
+ if (uniself==NULL)\r
+ return NULL;\r
+ res = _PyUnicode_XStrip((PyUnicodeObject *)uniself,\r
+ striptype, sep);\r
+ Py_DECREF(uniself);\r
+ return res;\r
+ }\r
+#endif\r
+ PyErr_Format(PyExc_TypeError,\r
+#ifdef Py_USING_UNICODE\r
+ "%s arg must be None, str or unicode",\r
+#else\r
+ "%s arg must be None or str",\r
+#endif\r
+ STRIPNAME(striptype));\r
+ return NULL;\r
+ }\r
+\r
+ return do_strip(self, striptype);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(strip__doc__,\r
+"S.strip([chars]) -> string or unicode\n\\r
+\n\\r
+Return a copy of the string S with leading and trailing\n\\r
+whitespace removed.\n\\r
+If chars is given and not None, remove characters in chars instead.\n\\r
+If chars is unicode, S will be converted to unicode before stripping");\r
+\r
+static PyObject *\r
+string_strip(PyStringObject *self, PyObject *args)\r
+{\r
+ if (PyTuple_GET_SIZE(args) == 0)\r
+ return do_strip(self, BOTHSTRIP); /* Common case */\r
+ else\r
+ return do_argstrip(self, BOTHSTRIP, args);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(lstrip__doc__,\r
+"S.lstrip([chars]) -> string or unicode\n\\r
+\n\\r
+Return a copy of the string S with leading whitespace removed.\n\\r
+If chars is given and not None, remove characters in chars instead.\n\\r
+If chars is unicode, S will be converted to unicode before stripping");\r
+\r
+static PyObject *\r
+string_lstrip(PyStringObject *self, PyObject *args)\r
+{\r
+ if (PyTuple_GET_SIZE(args) == 0)\r
+ return do_strip(self, LEFTSTRIP); /* Common case */\r
+ else\r
+ return do_argstrip(self, LEFTSTRIP, args);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(rstrip__doc__,\r
+"S.rstrip([chars]) -> string or unicode\n\\r
+\n\\r
+Return a copy of the string S with trailing whitespace removed.\n\\r
+If chars is given and not None, remove characters in chars instead.\n\\r
+If chars is unicode, S will be converted to unicode before stripping");\r
+\r
+static PyObject *\r
+string_rstrip(PyStringObject *self, PyObject *args)\r
+{\r
+ if (PyTuple_GET_SIZE(args) == 0)\r
+ return do_strip(self, RIGHTSTRIP); /* Common case */\r
+ else\r
+ return do_argstrip(self, RIGHTSTRIP, args);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(lower__doc__,\r
+"S.lower() -> string\n\\r
+\n\\r
+Return a copy of the string S converted to lowercase.");\r
+\r
+/* _tolower and _toupper are defined by SUSv2, but they're not ISO C */\r
+#ifndef _tolower\r
+#define _tolower tolower\r
+#endif\r
+\r
+static PyObject *\r
+string_lower(PyStringObject *self)\r
+{\r
+ char *s;\r
+ Py_ssize_t i, n = PyString_GET_SIZE(self);\r
+ PyObject *newobj;\r
+\r
+ newobj = PyString_FromStringAndSize(NULL, n);\r
+ if (!newobj)\r
+ return NULL;\r
+\r
+ s = PyString_AS_STRING(newobj);\r
+\r
+ Py_MEMCPY(s, PyString_AS_STRING(self), n);\r
+\r
+ for (i = 0; i < n; i++) {\r
+ int c = Py_CHARMASK(s[i]);\r
+ if (isupper(c))\r
+ s[i] = _tolower(c);\r
+ }\r
+\r
+ return newobj;\r
+}\r
+\r
+PyDoc_STRVAR(upper__doc__,\r
+"S.upper() -> string\n\\r
+\n\\r
+Return a copy of the string S converted to uppercase.");\r
+\r
+#ifndef _toupper\r
+#define _toupper toupper\r
+#endif\r
+\r
+static PyObject *\r
+string_upper(PyStringObject *self)\r
+{\r
+ char *s;\r
+ Py_ssize_t i, n = PyString_GET_SIZE(self);\r
+ PyObject *newobj;\r
+\r
+ newobj = PyString_FromStringAndSize(NULL, n);\r
+ if (!newobj)\r
+ return NULL;\r
+\r
+ s = PyString_AS_STRING(newobj);\r
+\r
+ Py_MEMCPY(s, PyString_AS_STRING(self), n);\r
+\r
+ for (i = 0; i < n; i++) {\r
+ int c = Py_CHARMASK(s[i]);\r
+ if (islower(c))\r
+ s[i] = _toupper(c);\r
+ }\r
+\r
+ return newobj;\r
+}\r
+\r
+PyDoc_STRVAR(title__doc__,\r
+"S.title() -> string\n\\r
+\n\\r
+Return a titlecased version of S, i.e. words start with uppercase\n\\r
+characters, all remaining cased characters have lowercase.");\r
+\r
+static PyObject*\r
+string_title(PyStringObject *self)\r
+{\r
+ char *s = PyString_AS_STRING(self), *s_new;\r
+ Py_ssize_t i, n = PyString_GET_SIZE(self);\r
+ int previous_is_cased = 0;\r
+ PyObject *newobj;\r
+\r
+ newobj = PyString_FromStringAndSize(NULL, n);\r
+ if (newobj == NULL)\r
+ return NULL;\r
+ s_new = PyString_AsString(newobj);\r
+ for (i = 0; i < n; i++) {\r
+ int c = Py_CHARMASK(*s++);\r
+ if (islower(c)) {\r
+ if (!previous_is_cased)\r
+ c = toupper(c);\r
+ previous_is_cased = 1;\r
+ } else if (isupper(c)) {\r
+ if (previous_is_cased)\r
+ c = tolower(c);\r
+ previous_is_cased = 1;\r
+ } else\r
+ previous_is_cased = 0;\r
+ *s_new++ = c;\r
+ }\r
+ return newobj;\r
+}\r
+\r
+PyDoc_STRVAR(capitalize__doc__,\r
+"S.capitalize() -> string\n\\r
+\n\\r
+Return a copy of the string S with only its first character\n\\r
+capitalized.");\r
+\r
+static PyObject *\r
+string_capitalize(PyStringObject *self)\r
+{\r
+ char *s = PyString_AS_STRING(self), *s_new;\r
+ Py_ssize_t i, n = PyString_GET_SIZE(self);\r
+ PyObject *newobj;\r
+\r
+ newobj = PyString_FromStringAndSize(NULL, n);\r
+ if (newobj == NULL)\r
+ return NULL;\r
+ s_new = PyString_AsString(newobj);\r
+ if (0 < n) {\r
+ int c = Py_CHARMASK(*s++);\r
+ if (islower(c))\r
+ *s_new = toupper(c);\r
+ else\r
+ *s_new = c;\r
+ s_new++;\r
+ }\r
+ for (i = 1; i < n; i++) {\r
+ int c = Py_CHARMASK(*s++);\r
+ if (isupper(c))\r
+ *s_new = tolower(c);\r
+ else\r
+ *s_new = c;\r
+ s_new++;\r
+ }\r
+ return newobj;\r
+}\r
+\r
+\r
+PyDoc_STRVAR(count__doc__,\r
+"S.count(sub[, start[, end]]) -> int\n\\r
+\n\\r
+Return the number of non-overlapping occurrences of substring sub in\n\\r
+string S[start:end]. Optional arguments start and end are interpreted\n\\r
+as in slice notation.");\r
+\r
+static PyObject *\r
+string_count(PyStringObject *self, PyObject *args)\r
+{\r
+ PyObject *sub_obj;\r
+ const char *str = PyString_AS_STRING(self), *sub;\r
+ Py_ssize_t sub_len;\r
+ Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;\r
+\r
+ if (!stringlib_parse_args_finds("count", args, &sub_obj, &start, &end))\r
+ return NULL;\r
+\r
+ if (PyString_Check(sub_obj)) {\r
+ sub = PyString_AS_STRING(sub_obj);\r
+ sub_len = PyString_GET_SIZE(sub_obj);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(sub_obj)) {\r
+ Py_ssize_t count;\r
+ count = PyUnicode_Count((PyObject *)self, sub_obj, start, end);\r
+ if (count == -1)\r
+ return NULL;\r
+ else\r
+ return PyInt_FromSsize_t(count);\r
+ }\r
+#endif\r
+ else if (PyObject_AsCharBuffer(sub_obj, &sub, &sub_len))\r
+ return NULL;\r
+\r
+ ADJUST_INDICES(start, end, PyString_GET_SIZE(self));\r
+\r
+ return PyInt_FromSsize_t(\r
+ stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX)\r
+ );\r
+}\r
+\r
+PyDoc_STRVAR(swapcase__doc__,\r
+"S.swapcase() -> string\n\\r
+\n\\r
+Return a copy of the string S with uppercase characters\n\\r
+converted to lowercase and vice versa.");\r
+\r
+static PyObject *\r
+string_swapcase(PyStringObject *self)\r
+{\r
+ char *s = PyString_AS_STRING(self), *s_new;\r
+ Py_ssize_t i, n = PyString_GET_SIZE(self);\r
+ PyObject *newobj;\r
+\r
+ newobj = PyString_FromStringAndSize(NULL, n);\r
+ if (newobj == NULL)\r
+ return NULL;\r
+ s_new = PyString_AsString(newobj);\r
+ for (i = 0; i < n; i++) {\r
+ int c = Py_CHARMASK(*s++);\r
+ if (islower(c)) {\r
+ *s_new = toupper(c);\r
+ }\r
+ else if (isupper(c)) {\r
+ *s_new = tolower(c);\r
+ }\r
+ else\r
+ *s_new = c;\r
+ s_new++;\r
+ }\r
+ return newobj;\r
+}\r
+\r
+\r
+PyDoc_STRVAR(translate__doc__,\r
+"S.translate(table [,deletechars]) -> string\n\\r
+\n\\r
+Return a copy of the string S, where all characters occurring\n\\r
+in the optional argument deletechars are removed, and the\n\\r
+remaining characters have been mapped through the given\n\\r
+translation table, which must be a string of length 256 or None.\n\\r
+If the table argument is None, no translation is applied and\n\\r
+the operation simply removes the characters in deletechars.");\r
+\r
+static PyObject *\r
+string_translate(PyStringObject *self, PyObject *args)\r
+{\r
+ register char *input, *output;\r
+ const char *table;\r
+ register Py_ssize_t i, c, changed = 0;\r
+ PyObject *input_obj = (PyObject*)self;\r
+ const char *output_start, *del_table=NULL;\r
+ Py_ssize_t inlen, tablen, dellen = 0;\r
+ PyObject *result;\r
+ int trans_table[256];\r
+ PyObject *tableobj, *delobj = NULL;\r
+\r
+ if (!PyArg_UnpackTuple(args, "translate", 1, 2,\r
+ &tableobj, &delobj))\r
+ return NULL;\r
+\r
+ if (PyString_Check(tableobj)) {\r
+ table = PyString_AS_STRING(tableobj);\r
+ tablen = PyString_GET_SIZE(tableobj);\r
+ }\r
+ else if (tableobj == Py_None) {\r
+ table = NULL;\r
+ tablen = 256;\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(tableobj)) {\r
+ /* Unicode .translate() does not support the deletechars\r
+ parameter; instead a mapping to None will cause characters\r
+ to be deleted. */\r
+ if (delobj != NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "deletions are implemented differently for unicode");\r
+ return NULL;\r
+ }\r
+ return PyUnicode_Translate((PyObject *)self, tableobj, NULL);\r
+ }\r
+#endif\r
+ else if (PyObject_AsCharBuffer(tableobj, &table, &tablen))\r
+ return NULL;\r
+\r
+ if (tablen != 256) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "translation table must be 256 characters long");\r
+ return NULL;\r
+ }\r
+\r
+ if (delobj != NULL) {\r
+ if (PyString_Check(delobj)) {\r
+ del_table = PyString_AS_STRING(delobj);\r
+ dellen = PyString_GET_SIZE(delobj);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(delobj)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "deletions are implemented differently for unicode");\r
+ return NULL;\r
+ }\r
+#endif\r
+ else if (PyObject_AsCharBuffer(delobj, &del_table, &dellen))\r
+ return NULL;\r
+ }\r
+ else {\r
+ del_table = NULL;\r
+ dellen = 0;\r
+ }\r
+\r
+ inlen = PyString_GET_SIZE(input_obj);\r
+ result = PyString_FromStringAndSize((char *)NULL, inlen);\r
+ if (result == NULL)\r
+ return NULL;\r
+ output_start = output = PyString_AsString(result);\r
+ input = PyString_AS_STRING(input_obj);\r
+\r
+ if (dellen == 0 && table != NULL) {\r
+ /* If no deletions are required, use faster code */\r
+ for (i = inlen; --i >= 0; ) {\r
+ c = Py_CHARMASK(*input++);\r
+ if (Py_CHARMASK((*output++ = table[c])) != c)\r
+ changed = 1;\r
+ }\r
+ if (changed || !PyString_CheckExact(input_obj))\r
+ return result;\r
+ Py_DECREF(result);\r
+ Py_INCREF(input_obj);\r
+ return input_obj;\r
+ }\r
+\r
+ if (table == NULL) {\r
+ for (i = 0; i < 256; i++)\r
+ trans_table[i] = Py_CHARMASK(i);\r
+ } else {\r
+ for (i = 0; i < 256; i++)\r
+ trans_table[i] = Py_CHARMASK(table[i]);\r
+ }\r
+\r
+ for (i = 0; i < dellen; i++)\r
+ trans_table[(int) Py_CHARMASK(del_table[i])] = -1;\r
+\r
+ for (i = inlen; --i >= 0; ) {\r
+ c = Py_CHARMASK(*input++);\r
+ if (trans_table[c] != -1)\r
+ if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c)\r
+ continue;\r
+ changed = 1;\r
+ }\r
+ if (!changed && PyString_CheckExact(input_obj)) {\r
+ Py_DECREF(result);\r
+ Py_INCREF(input_obj);\r
+ return input_obj;\r
+ }\r
+ /* Fix the size of the resulting string */\r
+ if (inlen > 0 && _PyString_Resize(&result, output - output_start))\r
+ return NULL;\r
+ return result;\r
+}\r
+\r
+\r
+/* find and count characters and substrings */\r
+\r
+#define findchar(target, target_len, c) \\r
+ ((char *)memchr((const void *)(target), c, target_len))\r
+\r
+/* String ops must return a string. */\r
+/* If the object is subclass of string, create a copy */\r
+Py_LOCAL(PyStringObject *)\r
+return_self(PyStringObject *self)\r
+{\r
+ if (PyString_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return self;\r
+ }\r
+ return (PyStringObject *)PyString_FromStringAndSize(\r
+ PyString_AS_STRING(self),\r
+ PyString_GET_SIZE(self));\r
+}\r
+\r
+Py_LOCAL_INLINE(Py_ssize_t)\r
+countchar(const char *target, Py_ssize_t target_len, char c, Py_ssize_t maxcount)\r
+{\r
+ Py_ssize_t count=0;\r
+ const char *start=target;\r
+ const char *end=target+target_len;\r
+\r
+ while ( (start=findchar(start, end-start, c)) != NULL ) {\r
+ count++;\r
+ if (count >= maxcount)\r
+ break;\r
+ start += 1;\r
+ }\r
+ return count;\r
+}\r
+\r
+\r
+/* Algorithms for different cases of string replacement */\r
+\r
+/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */\r
+Py_LOCAL(PyStringObject *)\r
+replace_interleave(PyStringObject *self,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count, i, product;\r
+ PyStringObject *result;\r
+\r
+ self_len = PyString_GET_SIZE(self);\r
+\r
+ /* 1 at the end plus 1 after every character */\r
+ count = self_len+1;\r
+ if (maxcount < count)\r
+ count = maxcount;\r
+\r
+ /* Check for overflow */\r
+ /* result_len = count * to_len + self_len; */\r
+ product = count * to_len;\r
+ if (product / to_len != count) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "replace string is too long");\r
+ return NULL;\r
+ }\r
+ result_len = product + self_len;\r
+ if (result_len < 0) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "replace string is too long");\r
+ return NULL;\r
+ }\r
+\r
+ if (! (result = (PyStringObject *)\r
+ PyString_FromStringAndSize(NULL, result_len)) )\r
+ return NULL;\r
+\r
+ self_s = PyString_AS_STRING(self);\r
+ result_s = PyString_AS_STRING(result);\r
+\r
+ /* TODO: special case single character, which doesn't need memcpy */\r
+\r
+ /* Lay the first one down (guaranteed this will occur) */\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ count -= 1;\r
+\r
+ for (i=0; i<count; i++) {\r
+ *result_s++ = *self_s++;\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ }\r
+\r
+ /* Copy the rest of the original string */\r
+ Py_MEMCPY(result_s, self_s, self_len-i);\r
+\r
+ return result;\r
+}\r
+\r
+/* Special case for deleting a single character */\r
+/* len(self)>=1, len(from)==1, to="", maxcount>=1 */\r
+Py_LOCAL(PyStringObject *)\r
+replace_delete_single_character(PyStringObject *self,\r
+ char from_c, Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s;\r
+ char *start, *next, *end;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count;\r
+ PyStringObject *result;\r
+\r
+ self_len = PyString_GET_SIZE(self);\r
+ self_s = PyString_AS_STRING(self);\r
+\r
+ count = countchar(self_s, self_len, from_c, maxcount);\r
+ if (count == 0) {\r
+ return return_self(self);\r
+ }\r
+\r
+ result_len = self_len - count; /* from_len == 1 */\r
+ assert(result_len>=0);\r
+\r
+ if ( (result = (PyStringObject *)\r
+ PyString_FromStringAndSize(NULL, result_len)) == NULL)\r
+ return NULL;\r
+ result_s = PyString_AS_STRING(result);\r
+\r
+ start = self_s;\r
+ end = self_s + self_len;\r
+ while (count-- > 0) {\r
+ next = findchar(start, end-start, from_c);\r
+ if (next == NULL)\r
+ break;\r
+ Py_MEMCPY(result_s, start, next-start);\r
+ result_s += (next-start);\r
+ start = next+1;\r
+ }\r
+ Py_MEMCPY(result_s, start, end-start);\r
+\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */\r
+\r
+Py_LOCAL(PyStringObject *)\r
+replace_delete_substring(PyStringObject *self,\r
+ const char *from_s, Py_ssize_t from_len,\r
+ Py_ssize_t maxcount) {\r
+ char *self_s, *result_s;\r
+ char *start, *next, *end;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count, offset;\r
+ PyStringObject *result;\r
+\r
+ self_len = PyString_GET_SIZE(self);\r
+ self_s = PyString_AS_STRING(self);\r
+\r
+ count = stringlib_count(self_s, self_len,\r
+ from_s, from_len,\r
+ maxcount);\r
+\r
+ if (count == 0) {\r
+ /* no matches */\r
+ return return_self(self);\r
+ }\r
+\r
+ result_len = self_len - (count * from_len);\r
+ assert (result_len>=0);\r
+\r
+ if ( (result = (PyStringObject *)\r
+ PyString_FromStringAndSize(NULL, result_len)) == NULL )\r
+ return NULL;\r
+\r
+ result_s = PyString_AS_STRING(result);\r
+\r
+ start = self_s;\r
+ end = self_s + self_len;\r
+ while (count-- > 0) {\r
+ offset = stringlib_find(start, end-start,\r
+ from_s, from_len,\r
+ 0);\r
+ if (offset == -1)\r
+ break;\r
+ next = start + offset;\r
+\r
+ Py_MEMCPY(result_s, start, next-start);\r
+\r
+ result_s += (next-start);\r
+ start = next+from_len;\r
+ }\r
+ Py_MEMCPY(result_s, start, end-start);\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */\r
+Py_LOCAL(PyStringObject *)\r
+replace_single_character_in_place(PyStringObject *self,\r
+ char from_c, char to_c,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s, *start, *end, *next;\r
+ Py_ssize_t self_len;\r
+ PyStringObject *result;\r
+\r
+ /* The result string will be the same size */\r
+ self_s = PyString_AS_STRING(self);\r
+ self_len = PyString_GET_SIZE(self);\r
+\r
+ next = findchar(self_s, self_len, from_c);\r
+\r
+ if (next == NULL) {\r
+ /* No matches; return the original string */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* Need to make a new string */\r
+ result = (PyStringObject *) PyString_FromStringAndSize(NULL, self_len);\r
+ if (result == NULL)\r
+ return NULL;\r
+ result_s = PyString_AS_STRING(result);\r
+ Py_MEMCPY(result_s, self_s, self_len);\r
+\r
+ /* change everything in-place, starting with this one */\r
+ start = result_s + (next-self_s);\r
+ *start = to_c;\r
+ start++;\r
+ end = result_s + self_len;\r
+\r
+ while (--maxcount > 0) {\r
+ next = findchar(start, end-start, from_c);\r
+ if (next == NULL)\r
+ break;\r
+ *next = to_c;\r
+ start = next+1;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */\r
+Py_LOCAL(PyStringObject *)\r
+replace_substring_in_place(PyStringObject *self,\r
+ const char *from_s, Py_ssize_t from_len,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *result_s, *start, *end;\r
+ char *self_s;\r
+ Py_ssize_t self_len, offset;\r
+ PyStringObject *result;\r
+\r
+ /* The result string will be the same size */\r
+\r
+ self_s = PyString_AS_STRING(self);\r
+ self_len = PyString_GET_SIZE(self);\r
+\r
+ offset = stringlib_find(self_s, self_len,\r
+ from_s, from_len,\r
+ 0);\r
+ if (offset == -1) {\r
+ /* No matches; return the original string */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* Need to make a new string */\r
+ result = (PyStringObject *) PyString_FromStringAndSize(NULL, self_len);\r
+ if (result == NULL)\r
+ return NULL;\r
+ result_s = PyString_AS_STRING(result);\r
+ Py_MEMCPY(result_s, self_s, self_len);\r
+\r
+ /* change everything in-place, starting with this one */\r
+ start = result_s + offset;\r
+ Py_MEMCPY(start, to_s, from_len);\r
+ start += from_len;\r
+ end = result_s + self_len;\r
+\r
+ while ( --maxcount > 0) {\r
+ offset = stringlib_find(start, end-start,\r
+ from_s, from_len,\r
+ 0);\r
+ if (offset==-1)\r
+ break;\r
+ Py_MEMCPY(start+offset, to_s, from_len);\r
+ start += offset+from_len;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */\r
+Py_LOCAL(PyStringObject *)\r
+replace_single_character(PyStringObject *self,\r
+ char from_c,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ char *self_s, *result_s;\r
+ char *start, *next, *end;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count, product;\r
+ PyStringObject *result;\r
+\r
+ self_s = PyString_AS_STRING(self);\r
+ self_len = PyString_GET_SIZE(self);\r
+\r
+ count = countchar(self_s, self_len, from_c, maxcount);\r
+ if (count == 0) {\r
+ /* no matches, return unchanged */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* use the difference between current and new, hence the "-1" */\r
+ /* result_len = self_len + count * (to_len-1) */\r
+ product = count * (to_len-1);\r
+ if (product / (to_len-1) != count) {\r
+ PyErr_SetString(PyExc_OverflowError, "replace string is too long");\r
+ return NULL;\r
+ }\r
+ result_len = self_len + product;\r
+ if (result_len < 0) {\r
+ PyErr_SetString(PyExc_OverflowError, "replace string is too long");\r
+ return NULL;\r
+ }\r
+\r
+ if ( (result = (PyStringObject *)\r
+ PyString_FromStringAndSize(NULL, result_len)) == NULL)\r
+ return NULL;\r
+ result_s = PyString_AS_STRING(result);\r
+\r
+ start = self_s;\r
+ end = self_s + self_len;\r
+ while (count-- > 0) {\r
+ next = findchar(start, end-start, from_c);\r
+ if (next == NULL)\r
+ break;\r
+\r
+ if (next == start) {\r
+ /* replace with the 'to' */\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ start += 1;\r
+ } else {\r
+ /* copy the unchanged old then the 'to' */\r
+ Py_MEMCPY(result_s, start, next-start);\r
+ result_s += (next-start);\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ start = next+1;\r
+ }\r
+ }\r
+ /* Copy the remainder of the remaining string */\r
+ Py_MEMCPY(result_s, start, end-start);\r
+\r
+ return result;\r
+}\r
+\r
+/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */\r
+Py_LOCAL(PyStringObject *)\r
+replace_substring(PyStringObject *self,\r
+ const char *from_s, Py_ssize_t from_len,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount) {\r
+ char *self_s, *result_s;\r
+ char *start, *next, *end;\r
+ Py_ssize_t self_len, result_len;\r
+ Py_ssize_t count, offset, product;\r
+ PyStringObject *result;\r
+\r
+ self_s = PyString_AS_STRING(self);\r
+ self_len = PyString_GET_SIZE(self);\r
+\r
+ count = stringlib_count(self_s, self_len,\r
+ from_s, from_len,\r
+ maxcount);\r
+\r
+ if (count == 0) {\r
+ /* no matches, return unchanged */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* Check for overflow */\r
+ /* result_len = self_len + count * (to_len-from_len) */\r
+ product = count * (to_len-from_len);\r
+ if (product / (to_len-from_len) != count) {\r
+ PyErr_SetString(PyExc_OverflowError, "replace string is too long");\r
+ return NULL;\r
+ }\r
+ result_len = self_len + product;\r
+ if (result_len < 0) {\r
+ PyErr_SetString(PyExc_OverflowError, "replace string is too long");\r
+ return NULL;\r
+ }\r
+\r
+ if ( (result = (PyStringObject *)\r
+ PyString_FromStringAndSize(NULL, result_len)) == NULL)\r
+ return NULL;\r
+ result_s = PyString_AS_STRING(result);\r
+\r
+ start = self_s;\r
+ end = self_s + self_len;\r
+ while (count-- > 0) {\r
+ offset = stringlib_find(start, end-start,\r
+ from_s, from_len,\r
+ 0);\r
+ if (offset == -1)\r
+ break;\r
+ next = start+offset;\r
+ if (next == start) {\r
+ /* replace with the 'to' */\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ start += from_len;\r
+ } else {\r
+ /* copy the unchanged old then the 'to' */\r
+ Py_MEMCPY(result_s, start, next-start);\r
+ result_s += (next-start);\r
+ Py_MEMCPY(result_s, to_s, to_len);\r
+ result_s += to_len;\r
+ start = next+from_len;\r
+ }\r
+ }\r
+ /* Copy the remainder of the remaining string */\r
+ Py_MEMCPY(result_s, start, end-start);\r
+\r
+ return result;\r
+}\r
+\r
+\r
+Py_LOCAL(PyStringObject *)\r
+replace(PyStringObject *self,\r
+ const char *from_s, Py_ssize_t from_len,\r
+ const char *to_s, Py_ssize_t to_len,\r
+ Py_ssize_t maxcount)\r
+{\r
+ if (maxcount < 0) {\r
+ maxcount = PY_SSIZE_T_MAX;\r
+ } else if (maxcount == 0 || PyString_GET_SIZE(self) == 0) {\r
+ /* nothing to do; return the original string */\r
+ return return_self(self);\r
+ }\r
+\r
+ if (maxcount == 0 ||\r
+ (from_len == 0 && to_len == 0)) {\r
+ /* nothing to do; return the original string */\r
+ return return_self(self);\r
+ }\r
+\r
+ /* Handle zero-length special cases */\r
+\r
+ if (from_len == 0) {\r
+ /* insert the 'to' string everywhere. */\r
+ /* >>> "Python".replace("", ".") */\r
+ /* '.P.y.t.h.o.n.' */\r
+ return replace_interleave(self, to_s, to_len, maxcount);\r
+ }\r
+\r
+ /* Except for "".replace("", "A") == "A" there is no way beyond this */\r
+ /* point for an empty self string to generate a non-empty string */\r
+ /* Special case so the remaining code always gets a non-empty string */\r
+ if (PyString_GET_SIZE(self) == 0) {\r
+ return return_self(self);\r
+ }\r
+\r
+ if (to_len == 0) {\r
+ /* delete all occurances of 'from' string */\r
+ if (from_len == 1) {\r
+ return replace_delete_single_character(\r
+ self, from_s[0], maxcount);\r
+ } else {\r
+ return replace_delete_substring(self, from_s, from_len, maxcount);\r
+ }\r
+ }\r
+\r
+ /* Handle special case where both strings have the same length */\r
+\r
+ if (from_len == to_len) {\r
+ if (from_len == 1) {\r
+ return replace_single_character_in_place(\r
+ self,\r
+ from_s[0],\r
+ to_s[0],\r
+ maxcount);\r
+ } else {\r
+ return replace_substring_in_place(\r
+ self, from_s, from_len, to_s, to_len, maxcount);\r
+ }\r
+ }\r
+\r
+ /* Otherwise use the more generic algorithms */\r
+ if (from_len == 1) {\r
+ return replace_single_character(self, from_s[0],\r
+ to_s, to_len, maxcount);\r
+ } else {\r
+ /* len('from')>=2, len('to')>=1 */\r
+ return replace_substring(self, from_s, from_len, to_s, to_len, maxcount);\r
+ }\r
+}\r
+\r
+PyDoc_STRVAR(replace__doc__,\r
+"S.replace(old, new[, count]) -> string\n\\r
+\n\\r
+Return a copy of string S with all occurrences of substring\n\\r
+old replaced by new. If the optional argument count is\n\\r
+given, only the first count occurrences are replaced.");\r
+\r
+static PyObject *\r
+string_replace(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t count = -1;\r
+ PyObject *from, *to;\r
+ const char *from_s, *to_s;\r
+ Py_ssize_t from_len, to_len;\r
+\r
+ if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))\r
+ return NULL;\r
+\r
+ if (PyString_Check(from)) {\r
+ from_s = PyString_AS_STRING(from);\r
+ from_len = PyString_GET_SIZE(from);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(from))\r
+ return PyUnicode_Replace((PyObject *)self,\r
+ from, to, count);\r
+#endif\r
+ else if (PyObject_AsCharBuffer(from, &from_s, &from_len))\r
+ return NULL;\r
+\r
+ if (PyString_Check(to)) {\r
+ to_s = PyString_AS_STRING(to);\r
+ to_len = PyString_GET_SIZE(to);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(to))\r
+ return PyUnicode_Replace((PyObject *)self,\r
+ from, to, count);\r
+#endif\r
+ else if (PyObject_AsCharBuffer(to, &to_s, &to_len))\r
+ return NULL;\r
+\r
+ return (PyObject *)replace((PyStringObject *) self,\r
+ from_s, from_len,\r
+ to_s, to_len, count);\r
+}\r
+\r
+/** End DALKE **/\r
+\r
+/* Matches the end (direction >= 0) or start (direction < 0) of self\r
+ * against substr, using the start and end arguments. Returns\r
+ * -1 on error, 0 if not found and 1 if found.\r
+ */\r
+Py_LOCAL(int)\r
+_string_tailmatch(PyStringObject *self, PyObject *substr, Py_ssize_t start,\r
+ Py_ssize_t end, int direction)\r
+{\r
+ Py_ssize_t len = PyString_GET_SIZE(self);\r
+ Py_ssize_t slen;\r
+ const char* sub;\r
+ const char* str;\r
+\r
+ if (PyString_Check(substr)) {\r
+ sub = PyString_AS_STRING(substr);\r
+ slen = PyString_GET_SIZE(substr);\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyUnicode_Check(substr))\r
+ return PyUnicode_Tailmatch((PyObject *)self,\r
+ substr, start, end, direction);\r
+#endif\r
+ else if (PyObject_AsCharBuffer(substr, &sub, &slen))\r
+ return -1;\r
+ str = PyString_AS_STRING(self);\r
+\r
+ ADJUST_INDICES(start, end, len);\r
+\r
+ if (direction < 0) {\r
+ /* startswith */\r
+ if (start+slen > len)\r
+ return 0;\r
+ } else {\r
+ /* endswith */\r
+ if (end-start < slen || start > len)\r
+ return 0;\r
+\r
+ if (end-slen > start)\r
+ start = end - slen;\r
+ }\r
+ if (end-start >= slen)\r
+ return ! memcmp(str+start, sub, slen);\r
+ return 0;\r
+}\r
+\r
+\r
+PyDoc_STRVAR(startswith__doc__,\r
+"S.startswith(prefix[, start[, end]]) -> bool\n\\r
+\n\\r
+Return True if S starts with the specified prefix, False otherwise.\n\\r
+With optional start, test S beginning at that position.\n\\r
+With optional end, stop comparing S at that position.\n\\r
+prefix can also be a tuple of strings to try.");\r
+\r
+static PyObject *\r
+string_startswith(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t start = 0;\r
+ Py_ssize_t end = PY_SSIZE_T_MAX;\r
+ PyObject *subobj;\r
+ int result;\r
+\r
+ if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))\r
+ return NULL;\r
+ if (PyTuple_Check(subobj)) {\r
+ Py_ssize_t i;\r
+ for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {\r
+ result = _string_tailmatch(self,\r
+ PyTuple_GET_ITEM(subobj, i),\r
+ start, end, -1);\r
+ if (result == -1)\r
+ return NULL;\r
+ else if (result) {\r
+ Py_RETURN_TRUE;\r
+ }\r
+ }\r
+ Py_RETURN_FALSE;\r
+ }\r
+ result = _string_tailmatch(self, subobj, start, end, -1);\r
+ if (result == -1) {\r
+ if (PyErr_ExceptionMatches(PyExc_TypeError))\r
+ PyErr_Format(PyExc_TypeError, "startswith first arg must be str, "\r
+ "unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name);\r
+ return NULL;\r
+ }\r
+ else\r
+ return PyBool_FromLong(result);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(endswith__doc__,\r
+"S.endswith(suffix[, start[, end]]) -> bool\n\\r
+\n\\r
+Return True if S ends with the specified suffix, False otherwise.\n\\r
+With optional start, test S beginning at that position.\n\\r
+With optional end, stop comparing S at that position.\n\\r
+suffix can also be a tuple of strings to try.");\r
+\r
+static PyObject *\r
+string_endswith(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t start = 0;\r
+ Py_ssize_t end = PY_SSIZE_T_MAX;\r
+ PyObject *subobj;\r
+ int result;\r
+\r
+ if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))\r
+ return NULL;\r
+ if (PyTuple_Check(subobj)) {\r
+ Py_ssize_t i;\r
+ for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {\r
+ result = _string_tailmatch(self,\r
+ PyTuple_GET_ITEM(subobj, i),\r
+ start, end, +1);\r
+ if (result == -1)\r
+ return NULL;\r
+ else if (result) {\r
+ Py_RETURN_TRUE;\r
+ }\r
+ }\r
+ Py_RETURN_FALSE;\r
+ }\r
+ result = _string_tailmatch(self, subobj, start, end, +1);\r
+ if (result == -1) {\r
+ if (PyErr_ExceptionMatches(PyExc_TypeError))\r
+ PyErr_Format(PyExc_TypeError, "endswith first arg must be str, "\r
+ "unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name);\r
+ return NULL;\r
+ }\r
+ else\r
+ return PyBool_FromLong(result);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(encode__doc__,\r
+"S.encode([encoding[,errors]]) -> object\n\\r
+\n\\r
+Encodes S using the codec registered for encoding. encoding defaults\n\\r
+to the default encoding. errors may be given to set a different error\n\\r
+handling scheme. Default is 'strict' meaning that encoding errors raise\n\\r
+a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and\n\\r
+'xmlcharrefreplace' as well as any other name registered with\n\\r
+codecs.register_error that is able to handle UnicodeEncodeErrors.");\r
+\r
+static PyObject *\r
+string_encode(PyStringObject *self, PyObject *args, PyObject *kwargs)\r
+{\r
+ static char *kwlist[] = {"encoding", "errors", 0};\r
+ char *encoding = NULL;\r
+ char *errors = NULL;\r
+ PyObject *v;\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:encode",\r
+ kwlist, &encoding, &errors))\r
+ return NULL;\r
+ v = PyString_AsEncodedObject((PyObject *)self, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (!PyString_Check(v) && !PyUnicode_Check(v)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "encoder did not return a string/unicode object "\r
+ "(type=%.400s)",\r
+ Py_TYPE(v)->tp_name);\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+\r
+PyDoc_STRVAR(decode__doc__,\r
+"S.decode([encoding[,errors]]) -> object\n\\r
+\n\\r
+Decodes S using the codec registered for encoding. encoding defaults\n\\r
+to the default encoding. errors may be given to set a different error\n\\r
+handling scheme. Default is 'strict' meaning that encoding errors raise\n\\r
+a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'\n\\r
+as well as any other name registered with codecs.register_error that is\n\\r
+able to handle UnicodeDecodeErrors.");\r
+\r
+static PyObject *\r
+string_decode(PyStringObject *self, PyObject *args, PyObject *kwargs)\r
+{\r
+ static char *kwlist[] = {"encoding", "errors", 0};\r
+ char *encoding = NULL;\r
+ char *errors = NULL;\r
+ PyObject *v;\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode",\r
+ kwlist, &encoding, &errors))\r
+ return NULL;\r
+ v = PyString_AsDecodedObject((PyObject *)self, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (!PyString_Check(v) && !PyUnicode_Check(v)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "decoder did not return a string/unicode object "\r
+ "(type=%.400s)",\r
+ Py_TYPE(v)->tp_name);\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+\r
+PyDoc_STRVAR(expandtabs__doc__,\r
+"S.expandtabs([tabsize]) -> string\n\\r
+\n\\r
+Return a copy of S where all tab characters are expanded using spaces.\n\\r
+If tabsize is not given, a tab size of 8 characters is assumed.");\r
+\r
+static PyObject*\r
+string_expandtabs(PyStringObject *self, PyObject *args)\r
+{\r
+ const char *e, *p, *qe;\r
+ char *q;\r
+ Py_ssize_t i, j, incr;\r
+ PyObject *u;\r
+ int tabsize = 8;\r
+\r
+ if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))\r
+ return NULL;\r
+\r
+ /* First pass: determine size of output string */\r
+ i = 0; /* chars up to and including most recent \n or \r */\r
+ j = 0; /* chars since most recent \n or \r (use in tab calculations) */\r
+ e = PyString_AS_STRING(self) + PyString_GET_SIZE(self); /* end of input */\r
+ for (p = PyString_AS_STRING(self); p < e; p++) {\r
+ if (*p == '\t') {\r
+ if (tabsize > 0) {\r
+ incr = tabsize - (j % tabsize);\r
+ if (j > PY_SSIZE_T_MAX - incr)\r
+ goto overflow1;\r
+ j += incr;\r
+ }\r
+ }\r
+ else {\r
+ if (j > PY_SSIZE_T_MAX - 1)\r
+ goto overflow1;\r
+ j++;\r
+ if (*p == '\n' || *p == '\r') {\r
+ if (i > PY_SSIZE_T_MAX - j)\r
+ goto overflow1;\r
+ i += j;\r
+ j = 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (i > PY_SSIZE_T_MAX - j)\r
+ goto overflow1;\r
+\r
+ /* Second pass: create output string and fill it */\r
+ u = PyString_FromStringAndSize(NULL, i + j);\r
+ if (!u)\r
+ return NULL;\r
+\r
+ j = 0; /* same as in first pass */\r
+ q = PyString_AS_STRING(u); /* next output char */\r
+ qe = PyString_AS_STRING(u) + PyString_GET_SIZE(u); /* end of output */\r
+\r
+ for (p = PyString_AS_STRING(self); p < e; p++) {\r
+ if (*p == '\t') {\r
+ if (tabsize > 0) {\r
+ i = tabsize - (j % tabsize);\r
+ j += i;\r
+ while (i--) {\r
+ if (q >= qe)\r
+ goto overflow2;\r
+ *q++ = ' ';\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ if (q >= qe)\r
+ goto overflow2;\r
+ *q++ = *p;\r
+ j++;\r
+ if (*p == '\n' || *p == '\r')\r
+ j = 0;\r
+ }\r
+ }\r
+\r
+ return u;\r
+\r
+ overflow2:\r
+ Py_DECREF(u);\r
+ overflow1:\r
+ PyErr_SetString(PyExc_OverflowError, "new string is too long");\r
+ return NULL;\r
+}\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+pad(PyStringObject *self, Py_ssize_t left, Py_ssize_t right, char fill)\r
+{\r
+ PyObject *u;\r
+\r
+ if (left < 0)\r
+ left = 0;\r
+ if (right < 0)\r
+ right = 0;\r
+\r
+ if (left == 0 && right == 0 && PyString_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+ }\r
+\r
+ u = PyString_FromStringAndSize(NULL,\r
+ left + PyString_GET_SIZE(self) + right);\r
+ if (u) {\r
+ if (left)\r
+ memset(PyString_AS_STRING(u), fill, left);\r
+ Py_MEMCPY(PyString_AS_STRING(u) + left,\r
+ PyString_AS_STRING(self),\r
+ PyString_GET_SIZE(self));\r
+ if (right)\r
+ memset(PyString_AS_STRING(u) + left + PyString_GET_SIZE(self),\r
+ fill, right);\r
+ }\r
+\r
+ return u;\r
+}\r
+\r
+PyDoc_STRVAR(ljust__doc__,\r
+"S.ljust(width[, fillchar]) -> string\n"\r
+"\n"\r
+"Return S left-justified in a string of length width. Padding is\n"\r
+"done using the specified fill character (default is a space).");\r
+\r
+static PyObject *\r
+string_ljust(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t width;\r
+ char fillchar = ' ';\r
+\r
+ if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))\r
+ return NULL;\r
+\r
+ if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+ }\r
+\r
+ return pad(self, 0, width - PyString_GET_SIZE(self), fillchar);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(rjust__doc__,\r
+"S.rjust(width[, fillchar]) -> string\n"\r
+"\n"\r
+"Return S right-justified in a string of length width. Padding is\n"\r
+"done using the specified fill character (default is a space)");\r
+\r
+static PyObject *\r
+string_rjust(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t width;\r
+ char fillchar = ' ';\r
+\r
+ if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar))\r
+ return NULL;\r
+\r
+ if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+ }\r
+\r
+ return pad(self, width - PyString_GET_SIZE(self), 0, fillchar);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(center__doc__,\r
+"S.center(width[, fillchar]) -> string\n"\r
+"\n"\r
+"Return S centered in a string of length width. Padding is\n"\r
+"done using the specified fill character (default is a space)");\r
+\r
+static PyObject *\r
+string_center(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t marg, left;\r
+ Py_ssize_t width;\r
+ char fillchar = ' ';\r
+\r
+ if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar))\r
+ return NULL;\r
+\r
+ if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+ }\r
+\r
+ marg = width - PyString_GET_SIZE(self);\r
+ left = marg / 2 + (marg & width & 1);\r
+\r
+ return pad(self, left, marg - left, fillchar);\r
+}\r
+\r
+PyDoc_STRVAR(zfill__doc__,\r
+"S.zfill(width) -> string\n"\r
+"\n"\r
+"Pad a numeric string S with zeros on the left, to fill a field\n"\r
+"of the specified width. The string S is never truncated.");\r
+\r
+static PyObject *\r
+string_zfill(PyStringObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t fill;\r
+ PyObject *s;\r
+ char *p;\r
+ Py_ssize_t width;\r
+\r
+ if (!PyArg_ParseTuple(args, "n:zfill", &width))\r
+ return NULL;\r
+\r
+ if (PyString_GET_SIZE(self) >= width) {\r
+ if (PyString_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+ }\r
+ else\r
+ return PyString_FromStringAndSize(\r
+ PyString_AS_STRING(self),\r
+ PyString_GET_SIZE(self)\r
+ );\r
+ }\r
+\r
+ fill = width - PyString_GET_SIZE(self);\r
+\r
+ s = pad(self, fill, 0, '0');\r
+\r
+ if (s == NULL)\r
+ return NULL;\r
+\r
+ p = PyString_AS_STRING(s);\r
+ if (p[fill] == '+' || p[fill] == '-') {\r
+ /* move sign to beginning of string */\r
+ p[0] = p[fill];\r
+ p[fill] = '0';\r
+ }\r
+\r
+ return (PyObject*) s;\r
+}\r
+\r
+PyDoc_STRVAR(isspace__doc__,\r
+"S.isspace() -> bool\n\\r
+\n\\r
+Return True if all characters in S are whitespace\n\\r
+and there is at least one character in S, False otherwise.");\r
+\r
+static PyObject*\r
+string_isspace(PyStringObject *self)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) PyString_AS_STRING(self);\r
+ register const unsigned char *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyString_GET_SIZE(self) == 1 &&\r
+ isspace(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyString_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyString_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!isspace(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(isalpha__doc__,\r
+"S.isalpha() -> bool\n\\r
+\n\\r
+Return True if all characters in S are alphabetic\n\\r
+and there is at least one character in S, False otherwise.");\r
+\r
+static PyObject*\r
+string_isalpha(PyStringObject *self)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) PyString_AS_STRING(self);\r
+ register const unsigned char *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyString_GET_SIZE(self) == 1 &&\r
+ isalpha(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyString_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyString_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!isalpha(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(isalnum__doc__,\r
+"S.isalnum() -> bool\n\\r
+\n\\r
+Return True if all characters in S are alphanumeric\n\\r
+and there is at least one character in S, False otherwise.");\r
+\r
+static PyObject*\r
+string_isalnum(PyStringObject *self)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) PyString_AS_STRING(self);\r
+ register const unsigned char *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyString_GET_SIZE(self) == 1 &&\r
+ isalnum(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyString_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyString_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!isalnum(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(isdigit__doc__,\r
+"S.isdigit() -> bool\n\\r
+\n\\r
+Return True if all characters in S are digits\n\\r
+and there is at least one character in S, False otherwise.");\r
+\r
+static PyObject*\r
+string_isdigit(PyStringObject *self)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) PyString_AS_STRING(self);\r
+ register const unsigned char *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyString_GET_SIZE(self) == 1 &&\r
+ isdigit(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyString_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyString_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!isdigit(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(islower__doc__,\r
+"S.islower() -> bool\n\\r
+\n\\r
+Return True if all cased characters in S are lowercase and there is\n\\r
+at least one cased character in S, False otherwise.");\r
+\r
+static PyObject*\r
+string_islower(PyStringObject *self)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) PyString_AS_STRING(self);\r
+ register const unsigned char *e;\r
+ int cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyString_GET_SIZE(self) == 1)\r
+ return PyBool_FromLong(islower(*p) != 0);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyString_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyString_GET_SIZE(self);\r
+ cased = 0;\r
+ for (; p < e; p++) {\r
+ if (isupper(*p))\r
+ return PyBool_FromLong(0);\r
+ else if (!cased && islower(*p))\r
+ cased = 1;\r
+ }\r
+ return PyBool_FromLong(cased);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(isupper__doc__,\r
+"S.isupper() -> bool\n\\r
+\n\\r
+Return True if all cased characters in S are uppercase and there is\n\\r
+at least one cased character in S, False otherwise.");\r
+\r
+static PyObject*\r
+string_isupper(PyStringObject *self)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) PyString_AS_STRING(self);\r
+ register const unsigned char *e;\r
+ int cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyString_GET_SIZE(self) == 1)\r
+ return PyBool_FromLong(isupper(*p) != 0);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyString_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyString_GET_SIZE(self);\r
+ cased = 0;\r
+ for (; p < e; p++) {\r
+ if (islower(*p))\r
+ return PyBool_FromLong(0);\r
+ else if (!cased && isupper(*p))\r
+ cased = 1;\r
+ }\r
+ return PyBool_FromLong(cased);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(istitle__doc__,\r
+"S.istitle() -> bool\n\\r
+\n\\r
+Return True if S is a titlecased string and there is at least one\n\\r
+character in S, i.e. uppercase characters may only follow uncased\n\\r
+characters and lowercase characters only cased ones. Return False\n\\r
+otherwise.");\r
+\r
+static PyObject*\r
+string_istitle(PyStringObject *self, PyObject *uncased)\r
+{\r
+ register const unsigned char *p\r
+ = (unsigned char *) PyString_AS_STRING(self);\r
+ register const unsigned char *e;\r
+ int cased, previous_is_cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyString_GET_SIZE(self) == 1)\r
+ return PyBool_FromLong(isupper(*p) != 0);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyString_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyString_GET_SIZE(self);\r
+ cased = 0;\r
+ previous_is_cased = 0;\r
+ for (; p < e; p++) {\r
+ register const unsigned char ch = *p;\r
+\r
+ if (isupper(ch)) {\r
+ if (previous_is_cased)\r
+ return PyBool_FromLong(0);\r
+ previous_is_cased = 1;\r
+ cased = 1;\r
+ }\r
+ else if (islower(ch)) {\r
+ if (!previous_is_cased)\r
+ return PyBool_FromLong(0);\r
+ previous_is_cased = 1;\r
+ cased = 1;\r
+ }\r
+ else\r
+ previous_is_cased = 0;\r
+ }\r
+ return PyBool_FromLong(cased);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(splitlines__doc__,\r
+"S.splitlines(keepends=False) -> list of strings\n\\r
+\n\\r
+Return a list of the lines in S, breaking at line boundaries.\n\\r
+Line breaks are not included in the resulting list unless keepends\n\\r
+is given and true.");\r
+\r
+static PyObject*\r
+string_splitlines(PyStringObject *self, PyObject *args)\r
+{\r
+ int keepends = 0;\r
+\r
+ if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends))\r
+ return NULL;\r
+\r
+ return stringlib_splitlines(\r
+ (PyObject*) self, PyString_AS_STRING(self), PyString_GET_SIZE(self),\r
+ keepends\r
+ );\r
+}\r
+\r
+PyDoc_STRVAR(sizeof__doc__,\r
+"S.__sizeof__() -> size of S in memory, in bytes");\r
+\r
+static PyObject *\r
+string_sizeof(PyStringObject *v)\r
+{\r
+ Py_ssize_t res;\r
+ res = PyStringObject_SIZE + PyString_GET_SIZE(v) * Py_TYPE(v)->tp_itemsize;\r
+ return PyInt_FromSsize_t(res);\r
+}\r
+\r
+static PyObject *\r
+string_getnewargs(PyStringObject *v)\r
+{\r
+ return Py_BuildValue("(s#)", v->ob_sval, Py_SIZE(v));\r
+}\r
+\r
+\r
+#include "stringlib/string_format.h"\r
+\r
+PyDoc_STRVAR(format__doc__,\r
+"S.format(*args, **kwargs) -> string\n\\r
+\n\\r
+Return a formatted version of S, using substitutions from args and kwargs.\n\\r
+The substitutions are identified by braces ('{' and '}').");\r
+\r
+static PyObject *\r
+string__format__(PyObject* self, PyObject* args)\r
+{\r
+ PyObject *format_spec;\r
+ PyObject *result = NULL;\r
+ PyObject *tmp = NULL;\r
+\r
+ /* If 2.x, convert format_spec to the same type as value */\r
+ /* This is to allow things like u''.format('') */\r
+ if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))\r
+ goto done;\r
+ if (!(PyString_Check(format_spec) || PyUnicode_Check(format_spec))) {\r
+ PyErr_Format(PyExc_TypeError, "__format__ arg must be str "\r
+ "or unicode, not %s", Py_TYPE(format_spec)->tp_name);\r
+ goto done;\r
+ }\r
+ tmp = PyObject_Str(format_spec);\r
+ if (tmp == NULL)\r
+ goto done;\r
+ format_spec = tmp;\r
+\r
+ result = _PyBytes_FormatAdvanced(self,\r
+ PyString_AS_STRING(format_spec),\r
+ PyString_GET_SIZE(format_spec));\r
+done:\r
+ Py_XDECREF(tmp);\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(p_format__doc__,\r
+"S.__format__(format_spec) -> string\n\\r
+\n\\r
+Return a formatted version of S as described by format_spec.");\r
+\r
+\r
+static PyMethodDef\r
+string_methods[] = {\r
+ /* Counterparts of the obsolete stropmodule functions; except\r
+ string.maketrans(). */\r
+ {"join", (PyCFunction)string_join, METH_O, join__doc__},\r
+ {"split", (PyCFunction)string_split, METH_VARARGS, split__doc__},\r
+ {"rsplit", (PyCFunction)string_rsplit, METH_VARARGS, rsplit__doc__},\r
+ {"lower", (PyCFunction)string_lower, METH_NOARGS, lower__doc__},\r
+ {"upper", (PyCFunction)string_upper, METH_NOARGS, upper__doc__},\r
+ {"islower", (PyCFunction)string_islower, METH_NOARGS, islower__doc__},\r
+ {"isupper", (PyCFunction)string_isupper, METH_NOARGS, isupper__doc__},\r
+ {"isspace", (PyCFunction)string_isspace, METH_NOARGS, isspace__doc__},\r
+ {"isdigit", (PyCFunction)string_isdigit, METH_NOARGS, isdigit__doc__},\r
+ {"istitle", (PyCFunction)string_istitle, METH_NOARGS, istitle__doc__},\r
+ {"isalpha", (PyCFunction)string_isalpha, METH_NOARGS, isalpha__doc__},\r
+ {"isalnum", (PyCFunction)string_isalnum, METH_NOARGS, isalnum__doc__},\r
+ {"capitalize", (PyCFunction)string_capitalize, METH_NOARGS,\r
+ capitalize__doc__},\r
+ {"count", (PyCFunction)string_count, METH_VARARGS, count__doc__},\r
+ {"endswith", (PyCFunction)string_endswith, METH_VARARGS,\r
+ endswith__doc__},\r
+ {"partition", (PyCFunction)string_partition, METH_O, partition__doc__},\r
+ {"find", (PyCFunction)string_find, METH_VARARGS, find__doc__},\r
+ {"index", (PyCFunction)string_index, METH_VARARGS, index__doc__},\r
+ {"lstrip", (PyCFunction)string_lstrip, METH_VARARGS, lstrip__doc__},\r
+ {"replace", (PyCFunction)string_replace, METH_VARARGS, replace__doc__},\r
+ {"rfind", (PyCFunction)string_rfind, METH_VARARGS, rfind__doc__},\r
+ {"rindex", (PyCFunction)string_rindex, METH_VARARGS, rindex__doc__},\r
+ {"rstrip", (PyCFunction)string_rstrip, METH_VARARGS, rstrip__doc__},\r
+ {"rpartition", (PyCFunction)string_rpartition, METH_O,\r
+ rpartition__doc__},\r
+ {"startswith", (PyCFunction)string_startswith, METH_VARARGS,\r
+ startswith__doc__},\r
+ {"strip", (PyCFunction)string_strip, METH_VARARGS, strip__doc__},\r
+ {"swapcase", (PyCFunction)string_swapcase, METH_NOARGS,\r
+ swapcase__doc__},\r
+ {"translate", (PyCFunction)string_translate, METH_VARARGS,\r
+ translate__doc__},\r
+ {"title", (PyCFunction)string_title, METH_NOARGS, title__doc__},\r
+ {"ljust", (PyCFunction)string_ljust, METH_VARARGS, ljust__doc__},\r
+ {"rjust", (PyCFunction)string_rjust, METH_VARARGS, rjust__doc__},\r
+ {"center", (PyCFunction)string_center, METH_VARARGS, center__doc__},\r
+ {"zfill", (PyCFunction)string_zfill, METH_VARARGS, zfill__doc__},\r
+ {"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__},\r
+ {"__format__", (PyCFunction) string__format__, METH_VARARGS, p_format__doc__},\r
+ {"_formatter_field_name_split", (PyCFunction) formatter_field_name_split, METH_NOARGS},\r
+ {"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS},\r
+ {"encode", (PyCFunction)string_encode, METH_VARARGS | METH_KEYWORDS, encode__doc__},\r
+ {"decode", (PyCFunction)string_decode, METH_VARARGS | METH_KEYWORDS, decode__doc__},\r
+ {"expandtabs", (PyCFunction)string_expandtabs, METH_VARARGS,\r
+ expandtabs__doc__},\r
+ {"splitlines", (PyCFunction)string_splitlines, METH_VARARGS,\r
+ splitlines__doc__},\r
+ {"__sizeof__", (PyCFunction)string_sizeof, METH_NOARGS,\r
+ sizeof__doc__},\r
+ {"__getnewargs__", (PyCFunction)string_getnewargs, METH_NOARGS},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyObject *\r
+str_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);\r
+\r
+static PyObject *\r
+string_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *x = NULL;\r
+ static char *kwlist[] = {"object", 0};\r
+\r
+ if (type != &PyString_Type)\r
+ return str_subtype_new(type, args, kwds);\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:str", kwlist, &x))\r
+ return NULL;\r
+ if (x == NULL)\r
+ return PyString_FromString("");\r
+ return PyObject_Str(x);\r
+}\r
+\r
+static PyObject *\r
+str_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *tmp, *pnew;\r
+ Py_ssize_t n;\r
+\r
+ assert(PyType_IsSubtype(type, &PyString_Type));\r
+ tmp = string_new(&PyString_Type, args, kwds);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ assert(PyString_CheckExact(tmp));\r
+ n = PyString_GET_SIZE(tmp);\r
+ pnew = type->tp_alloc(type, n);\r
+ if (pnew != NULL) {\r
+ Py_MEMCPY(PyString_AS_STRING(pnew), PyString_AS_STRING(tmp), n+1);\r
+ ((PyStringObject *)pnew)->ob_shash =\r
+ ((PyStringObject *)tmp)->ob_shash;\r
+ ((PyStringObject *)pnew)->ob_sstate = SSTATE_NOT_INTERNED;\r
+ }\r
+ Py_DECREF(tmp);\r
+ return pnew;\r
+}\r
+\r
+static PyObject *\r
+basestring_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "The basestring type cannot be instantiated");\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+string_mod(PyObject *v, PyObject *w)\r
+{\r
+ if (!PyString_Check(v)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ return PyString_Format(v, w);\r
+}\r
+\r
+PyDoc_STRVAR(basestring_doc,\r
+"Type basestring cannot be instantiated; it is the base for str and unicode.");\r
+\r
+static PyNumberMethods string_as_number = {\r
+ 0, /*nb_add*/\r
+ 0, /*nb_subtract*/\r
+ 0, /*nb_multiply*/\r
+ 0, /*nb_divide*/\r
+ string_mod, /*nb_remainder*/\r
+};\r
+\r
+\r
+PyTypeObject PyBaseString_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "basestring",\r
+ 0,\r
+ 0,\r
+ 0, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ 0, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ basestring_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ &PyBaseObject_Type, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ basestring_new, /* tp_new */\r
+ 0, /* tp_free */\r
+};\r
+\r
+PyDoc_STRVAR(string_doc,\r
+"str(object='') -> string\n\\r
+\n\\r
+Return a nice string representation of the object.\n\\r
+If the argument is a string, the return value is the same object.");\r
+\r
+PyTypeObject PyString_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "str",\r
+ PyStringObject_SIZE,\r
+ sizeof(char),\r
+ string_dealloc, /* tp_dealloc */\r
+ (printfunc)string_print, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ string_repr, /* tp_repr */\r
+ &string_as_number, /* tp_as_number */\r
+ &string_as_sequence, /* tp_as_sequence */\r
+ &string_as_mapping, /* tp_as_mapping */\r
+ (hashfunc)string_hash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ string_str, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ &string_as_buffer, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |\r
+ Py_TPFLAGS_BASETYPE | Py_TPFLAGS_STRING_SUBCLASS |\r
+ Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */\r
+ string_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ (richcmpfunc)string_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ string_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ &PyBaseString_Type, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ string_new, /* tp_new */\r
+ PyObject_Del, /* tp_free */\r
+};\r
+\r
+void\r
+PyString_Concat(register PyObject **pv, register PyObject *w)\r
+{\r
+ register PyObject *v;\r
+ if (*pv == NULL)\r
+ return;\r
+ if (w == NULL || !PyString_Check(*pv)) {\r
+ Py_CLEAR(*pv);\r
+ return;\r
+ }\r
+ v = string_concat((PyStringObject *) *pv, w);\r
+ Py_DECREF(*pv);\r
+ *pv = v;\r
+}\r
+\r
+void\r
+PyString_ConcatAndDel(register PyObject **pv, register PyObject *w)\r
+{\r
+ PyString_Concat(pv, w);\r
+ Py_XDECREF(w);\r
+}\r
+\r
+\r
+/* The following function breaks the notion that strings are immutable:\r
+ it changes the size of a string. We get away with this only if there\r
+ is only one module referencing the object. You can also think of it\r
+ as creating a new string object and destroying the old one, only\r
+ more efficiently. In any case, don't use this if the string may\r
+ already be known to some other part of the code...\r
+ Note that if there's not enough memory to resize the string, the original\r
+ string object at *pv is deallocated, *pv is set to NULL, an "out of\r
+ memory" exception is set, and -1 is returned. Else (on success) 0 is\r
+ returned, and the value in *pv may or may not be the same as on input.\r
+ As always, an extra byte is allocated for a trailing \0 byte (newsize\r
+ does *not* include that), and a trailing \0 byte is stored.\r
+*/\r
+\r
+int\r
+_PyString_Resize(PyObject **pv, Py_ssize_t newsize)\r
+{\r
+ register PyObject *v;\r
+ register PyStringObject *sv;\r
+ v = *pv;\r
+ if (!PyString_Check(v) || Py_REFCNT(v) != 1 || newsize < 0 ||\r
+ PyString_CHECK_INTERNED(v)) {\r
+ *pv = 0;\r
+ Py_DECREF(v);\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ /* XXX UNREF/NEWREF interface should be more symmetrical */\r
+ _Py_DEC_REFTOTAL;\r
+ _Py_ForgetReference(v);\r
+ *pv = (PyObject *)\r
+ PyObject_REALLOC((char *)v, PyStringObject_SIZE + newsize);\r
+ if (*pv == NULL) {\r
+ PyObject_Del(v);\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ _Py_NewReference(*pv);\r
+ sv = (PyStringObject *) *pv;\r
+ Py_SIZE(sv) = newsize;\r
+ sv->ob_sval[newsize] = '\0';\r
+ sv->ob_shash = -1; /* invalidate cached hash value */\r
+ return 0;\r
+}\r
+\r
+/* Helpers for formatstring */\r
+\r
+Py_LOCAL_INLINE(PyObject *)\r
+getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx)\r
+{\r
+ Py_ssize_t argidx = *p_argidx;\r
+ if (argidx < arglen) {\r
+ (*p_argidx)++;\r
+ if (arglen < 0)\r
+ return args;\r
+ else\r
+ return PyTuple_GetItem(args, argidx);\r
+ }\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "not enough arguments for format string");\r
+ return NULL;\r
+}\r
+\r
+/* Format codes\r
+ * F_LJUST '-'\r
+ * F_SIGN '+'\r
+ * F_BLANK ' '\r
+ * F_ALT '#'\r
+ * F_ZERO '0'\r
+ */\r
+#define F_LJUST (1<<0)\r
+#define F_SIGN (1<<1)\r
+#define F_BLANK (1<<2)\r
+#define F_ALT (1<<3)\r
+#define F_ZERO (1<<4)\r
+\r
+/* Returns a new reference to a PyString object, or NULL on failure. */\r
+\r
+static PyObject *\r
+formatfloat(PyObject *v, int flags, int prec, int type)\r
+{\r
+ char *p;\r
+ PyObject *result;\r
+ double x;\r
+\r
+ x = PyFloat_AsDouble(v);\r
+ if (x == -1.0 && PyErr_Occurred()) {\r
+ PyErr_Format(PyExc_TypeError, "float argument required, "\r
+ "not %.200s", Py_TYPE(v)->tp_name);\r
+ return NULL;\r
+ }\r
+\r
+ if (prec < 0)\r
+ prec = 6;\r
+\r
+ p = PyOS_double_to_string(x, type, prec,\r
+ (flags & F_ALT) ? Py_DTSF_ALT : 0, NULL);\r
+\r
+ if (p == NULL)\r
+ return NULL;\r
+ result = PyString_FromStringAndSize(p, strlen(p));\r
+ PyMem_Free(p);\r
+ return result;\r
+}\r
+\r
+/* _PyString_FormatLong emulates the format codes d, u, o, x and X, and\r
+ * the F_ALT flag, for Python's long (unbounded) ints. It's not used for\r
+ * Python's regular ints.\r
+ * Return value: a new PyString*, or NULL if error.\r
+ * . *pbuf is set to point into it,\r
+ * *plen set to the # of chars following that.\r
+ * Caller must decref it when done using pbuf.\r
+ * The string starting at *pbuf is of the form\r
+ * "-"? ("0x" | "0X")? digit+\r
+ * "0x"/"0X" are present only for x and X conversions, with F_ALT\r
+ * set in flags. The case of hex digits will be correct,\r
+ * There will be at least prec digits, zero-filled on the left if\r
+ * necessary to get that many.\r
+ * val object to be converted\r
+ * flags bitmask of format flags; only F_ALT is looked at\r
+ * prec minimum number of digits; 0-fill on left if needed\r
+ * type a character in [duoxX]; u acts the same as d\r
+ *\r
+ * CAUTION: o, x and X conversions on regular ints can never\r
+ * produce a '-' sign, but can for Python's unbounded ints.\r
+ */\r
+PyObject*\r
+_PyString_FormatLong(PyObject *val, int flags, int prec, int type,\r
+ char **pbuf, int *plen)\r
+{\r
+ PyObject *result = NULL;\r
+ char *buf;\r
+ Py_ssize_t i;\r
+ int sign; /* 1 if '-', else 0 */\r
+ int len; /* number of characters */\r
+ Py_ssize_t llen;\r
+ int numdigits; /* len == numnondigits + numdigits */\r
+ int numnondigits = 0;\r
+\r
+ switch (type) {\r
+ case 'd':\r
+ case 'u':\r
+ result = Py_TYPE(val)->tp_str(val);\r
+ break;\r
+ case 'o':\r
+ result = Py_TYPE(val)->tp_as_number->nb_oct(val);\r
+ break;\r
+ case 'x':\r
+ case 'X':\r
+ numnondigits = 2;\r
+ result = Py_TYPE(val)->tp_as_number->nb_hex(val);\r
+ break;\r
+ default:\r
+ assert(!"'type' not in [duoxX]");\r
+ }\r
+ if (!result)\r
+ return NULL;\r
+\r
+ buf = PyString_AsString(result);\r
+ if (!buf) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+\r
+ /* To modify the string in-place, there can only be one reference. */\r
+ if (Py_REFCNT(result) != 1) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ llen = PyString_Size(result);\r
+ if (llen > INT_MAX) {\r
+ PyErr_SetString(PyExc_ValueError, "string too large in _PyString_FormatLong");\r
+ return NULL;\r
+ }\r
+ len = (int)llen;\r
+ if (buf[len-1] == 'L') {\r
+ --len;\r
+ buf[len] = '\0';\r
+ }\r
+ sign = buf[0] == '-';\r
+ numnondigits += sign;\r
+ numdigits = len - numnondigits;\r
+ assert(numdigits > 0);\r
+\r
+ /* Get rid of base marker unless F_ALT */\r
+ if ((flags & F_ALT) == 0) {\r
+ /* Need to skip 0x, 0X or 0. */\r
+ int skipped = 0;\r
+ switch (type) {\r
+ case 'o':\r
+ assert(buf[sign] == '0');\r
+ /* If 0 is only digit, leave it alone. */\r
+ if (numdigits > 1) {\r
+ skipped = 1;\r
+ --numdigits;\r
+ }\r
+ break;\r
+ case 'x':\r
+ case 'X':\r
+ assert(buf[sign] == '0');\r
+ assert(buf[sign + 1] == 'x');\r
+ skipped = 2;\r
+ numnondigits -= 2;\r
+ break;\r
+ }\r
+ if (skipped) {\r
+ buf += skipped;\r
+ len -= skipped;\r
+ if (sign)\r
+ buf[0] = '-';\r
+ }\r
+ assert(len == numnondigits + numdigits);\r
+ assert(numdigits > 0);\r
+ }\r
+\r
+ /* Fill with leading zeroes to meet minimum width. */\r
+ if (prec > numdigits) {\r
+ PyObject *r1 = PyString_FromStringAndSize(NULL,\r
+ numnondigits + prec);\r
+ char *b1;\r
+ if (!r1) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+ b1 = PyString_AS_STRING(r1);\r
+ for (i = 0; i < numnondigits; ++i)\r
+ *b1++ = *buf++;\r
+ for (i = 0; i < prec - numdigits; i++)\r
+ *b1++ = '0';\r
+ for (i = 0; i < numdigits; i++)\r
+ *b1++ = *buf++;\r
+ *b1 = '\0';\r
+ Py_DECREF(result);\r
+ result = r1;\r
+ buf = PyString_AS_STRING(result);\r
+ len = numnondigits + prec;\r
+ }\r
+\r
+ /* Fix up case for hex conversions. */\r
+ if (type == 'X') {\r
+ /* Need to convert all lower case letters to upper case.\r
+ and need to convert 0x to 0X (and -0x to -0X). */\r
+ for (i = 0; i < len; i++)\r
+ if (buf[i] >= 'a' && buf[i] <= 'x')\r
+ buf[i] -= 'a'-'A';\r
+ }\r
+ *pbuf = buf;\r
+ *plen = len;\r
+ return result;\r
+}\r
+\r
+Py_LOCAL_INLINE(int)\r
+formatint(char *buf, size_t buflen, int flags,\r
+ int prec, int type, PyObject *v)\r
+{\r
+ /* fmt = '%#.' + `prec` + 'l' + `type`\r
+ worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)\r
+ + 1 + 1 = 24 */\r
+ char fmt[64]; /* plenty big enough! */\r
+ char *sign;\r
+ long x;\r
+\r
+ x = PyInt_AsLong(v);\r
+ if (x == -1 && PyErr_Occurred()) {\r
+ PyErr_Format(PyExc_TypeError, "int argument required, not %.200s",\r
+ Py_TYPE(v)->tp_name);\r
+ return -1;\r
+ }\r
+ if (x < 0 && type == 'u') {\r
+ type = 'd';\r
+ }\r
+ if (x < 0 && (type == 'x' || type == 'X' || type == 'o'))\r
+ sign = "-";\r
+ else\r
+ sign = "";\r
+ if (prec < 0)\r
+ prec = 1;\r
+\r
+ if ((flags & F_ALT) &&\r
+ (type == 'x' || type == 'X')) {\r
+ /* When converting under %#x or %#X, there are a number\r
+ * of issues that cause pain:\r
+ * - when 0 is being converted, the C standard leaves off\r
+ * the '0x' or '0X', which is inconsistent with other\r
+ * %#x/%#X conversions and inconsistent with Python's\r
+ * hex() function\r
+ * - there are platforms that violate the standard and\r
+ * convert 0 with the '0x' or '0X'\r
+ * (Metrowerks, Compaq Tru64)\r
+ * - there are platforms that give '0x' when converting\r
+ * under %#X, but convert 0 in accordance with the\r
+ * standard (OS/2 EMX)\r
+ *\r
+ * We can achieve the desired consistency by inserting our\r
+ * own '0x' or '0X' prefix, and substituting %x/%X in place\r
+ * of %#x/%#X.\r
+ *\r
+ * Note that this is the same approach as used in\r
+ * formatint() in unicodeobject.c\r
+ */\r
+ PyOS_snprintf(fmt, sizeof(fmt), "%s0%c%%.%dl%c",\r
+ sign, type, prec, type);\r
+ }\r
+ else {\r
+ PyOS_snprintf(fmt, sizeof(fmt), "%s%%%s.%dl%c",\r
+ sign, (flags&F_ALT) ? "#" : "",\r
+ prec, type);\r
+ }\r
+\r
+ /* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal))\r
+ * worst case buf = '-0x' + [0-9]*prec, where prec >= 11\r
+ */\r
+ if (buflen <= 14 || buflen <= (size_t)3 + (size_t)prec) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "formatted integer is too long (precision too large?)");\r
+ return -1;\r
+ }\r
+ if (sign[0])\r
+ PyOS_snprintf(buf, buflen, fmt, -x);\r
+ else\r
+ PyOS_snprintf(buf, buflen, fmt, x);\r
+ return (int)strlen(buf);\r
+}\r
+\r
+Py_LOCAL_INLINE(int)\r
+formatchar(char *buf, size_t buflen, PyObject *v)\r
+{\r
+ /* presume that the buffer is at least 2 characters long */\r
+ if (PyString_Check(v)) {\r
+ if (!PyArg_Parse(v, "c;%c requires int or char", &buf[0]))\r
+ return -1;\r
+ }\r
+ else {\r
+ if (!PyArg_Parse(v, "b;%c requires int or char", &buf[0]))\r
+ return -1;\r
+ }\r
+ buf[1] = '\0';\r
+ return 1;\r
+}\r
+\r
+/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...)\r
+\r
+ FORMATBUFLEN is the length of the buffer in which the ints &\r
+ chars are formatted. XXX This is a magic number. Each formatting\r
+ routine does bounds checking to ensure no overflow, but a better\r
+ solution may be to malloc a buffer of appropriate size for each\r
+ format. For now, the current solution is sufficient.\r
+*/\r
+#define FORMATBUFLEN (size_t)120\r
+\r
+PyObject *\r
+PyString_Format(PyObject *format, PyObject *args)\r
+{\r
+ char *fmt, *res;\r
+ Py_ssize_t arglen, argidx;\r
+ Py_ssize_t reslen, rescnt, fmtcnt;\r
+ int args_owned = 0;\r
+ PyObject *result, *orig_args;\r
+#ifdef Py_USING_UNICODE\r
+ PyObject *v, *w;\r
+#endif\r
+ PyObject *dict = NULL;\r
+ if (format == NULL || !PyString_Check(format) || args == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ orig_args = args;\r
+ fmt = PyString_AS_STRING(format);\r
+ fmtcnt = PyString_GET_SIZE(format);\r
+ reslen = rescnt = fmtcnt + 100;\r
+ result = PyString_FromStringAndSize((char *)NULL, reslen);\r
+ if (result == NULL)\r
+ return NULL;\r
+ res = PyString_AsString(result);\r
+ if (PyTuple_Check(args)) {\r
+ arglen = PyTuple_GET_SIZE(args);\r
+ argidx = 0;\r
+ }\r
+ else {\r
+ arglen = -1;\r
+ argidx = -2;\r
+ }\r
+ if (Py_TYPE(args)->tp_as_mapping && Py_TYPE(args)->tp_as_mapping->mp_subscript &&\r
+ !PyTuple_Check(args) && !PyObject_TypeCheck(args, &PyBaseString_Type))\r
+ dict = args;\r
+ while (--fmtcnt >= 0) {\r
+ if (*fmt != '%') {\r
+ if (--rescnt < 0) {\r
+ rescnt = fmtcnt + 100;\r
+ reslen += rescnt;\r
+ if (_PyString_Resize(&result, reslen))\r
+ return NULL;\r
+ res = PyString_AS_STRING(result)\r
+ + reslen - rescnt;\r
+ --rescnt;\r
+ }\r
+ *res++ = *fmt++;\r
+ }\r
+ else {\r
+ /* Got a format specifier */\r
+ int flags = 0;\r
+ Py_ssize_t width = -1;\r
+ int prec = -1;\r
+ int c = '\0';\r
+ int fill;\r
+ int isnumok;\r
+ PyObject *v = NULL;\r
+ PyObject *temp = NULL;\r
+ char *pbuf;\r
+ int sign;\r
+ Py_ssize_t len;\r
+ char formatbuf[FORMATBUFLEN];\r
+ /* For format{int,char}() */\r
+#ifdef Py_USING_UNICODE\r
+ char *fmt_start = fmt;\r
+ Py_ssize_t argidx_start = argidx;\r
+#endif\r
+\r
+ fmt++;\r
+ if (*fmt == '(') {\r
+ char *keystart;\r
+ Py_ssize_t keylen;\r
+ PyObject *key;\r
+ int pcount = 1;\r
+\r
+ if (dict == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "format requires a mapping");\r
+ goto error;\r
+ }\r
+ ++fmt;\r
+ --fmtcnt;\r
+ keystart = fmt;\r
+ /* Skip over balanced parentheses */\r
+ while (pcount > 0 && --fmtcnt >= 0) {\r
+ if (*fmt == ')')\r
+ --pcount;\r
+ else if (*fmt == '(')\r
+ ++pcount;\r
+ fmt++;\r
+ }\r
+ keylen = fmt - keystart - 1;\r
+ if (fmtcnt < 0 || pcount > 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "incomplete format key");\r
+ goto error;\r
+ }\r
+ key = PyString_FromStringAndSize(keystart,\r
+ keylen);\r
+ if (key == NULL)\r
+ goto error;\r
+ if (args_owned) {\r
+ Py_DECREF(args);\r
+ args_owned = 0;\r
+ }\r
+ args = PyObject_GetItem(dict, key);\r
+ Py_DECREF(key);\r
+ if (args == NULL) {\r
+ goto error;\r
+ }\r
+ args_owned = 1;\r
+ arglen = -1;\r
+ argidx = -2;\r
+ }\r
+ while (--fmtcnt >= 0) {\r
+ switch (c = *fmt++) {\r
+ case '-': flags |= F_LJUST; continue;\r
+ case '+': flags |= F_SIGN; continue;\r
+ case ' ': flags |= F_BLANK; continue;\r
+ case '#': flags |= F_ALT; continue;\r
+ case '0': flags |= F_ZERO; continue;\r
+ }\r
+ break;\r
+ }\r
+ if (c == '*') {\r
+ v = getnextarg(args, arglen, &argidx);\r
+ if (v == NULL)\r
+ goto error;\r
+ if (!PyInt_Check(v)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "* wants int");\r
+ goto error;\r
+ }\r
+ width = PyInt_AsSsize_t(v);\r
+ if (width == -1 && PyErr_Occurred())\r
+ goto error;\r
+ if (width < 0) {\r
+ flags |= F_LJUST;\r
+ width = -width;\r
+ }\r
+ if (--fmtcnt >= 0)\r
+ c = *fmt++;\r
+ }\r
+ else if (c >= 0 && isdigit(c)) {\r
+ width = c - '0';\r
+ while (--fmtcnt >= 0) {\r
+ c = Py_CHARMASK(*fmt++);\r
+ if (!isdigit(c))\r
+ break;\r
+ if (width > (PY_SSIZE_T_MAX - ((int)c - '0')) / 10) {\r
+ PyErr_SetString(\r
+ PyExc_ValueError,\r
+ "width too big");\r
+ goto error;\r
+ }\r
+ width = width*10 + (c - '0');\r
+ }\r
+ }\r
+ if (c == '.') {\r
+ prec = 0;\r
+ if (--fmtcnt >= 0)\r
+ c = *fmt++;\r
+ if (c == '*') {\r
+ v = getnextarg(args, arglen, &argidx);\r
+ if (v == NULL)\r
+ goto error;\r
+ if (!PyInt_Check(v)) {\r
+ PyErr_SetString(\r
+ PyExc_TypeError,\r
+ "* wants int");\r
+ goto error;\r
+ }\r
+ prec = _PyInt_AsInt(v);\r
+ if (prec == -1 && PyErr_Occurred())\r
+ goto error;\r
+ if (prec < 0)\r
+ prec = 0;\r
+ if (--fmtcnt >= 0)\r
+ c = *fmt++;\r
+ }\r
+ else if (c >= 0 && isdigit(c)) {\r
+ prec = c - '0';\r
+ while (--fmtcnt >= 0) {\r
+ c = Py_CHARMASK(*fmt++);\r
+ if (!isdigit(c))\r
+ break;\r
+ if (prec > (INT_MAX - ((int)c - '0')) / 10) {\r
+ PyErr_SetString(\r
+ PyExc_ValueError,\r
+ "prec too big");\r
+ goto error;\r
+ }\r
+ prec = prec*10 + (c - '0');\r
+ }\r
+ }\r
+ } /* prec */\r
+ if (fmtcnt >= 0) {\r
+ if (c == 'h' || c == 'l' || c == 'L') {\r
+ if (--fmtcnt >= 0)\r
+ c = *fmt++;\r
+ }\r
+ }\r
+ if (fmtcnt < 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "incomplete format");\r
+ goto error;\r
+ }\r
+ if (c != '%') {\r
+ v = getnextarg(args, arglen, &argidx);\r
+ if (v == NULL)\r
+ goto error;\r
+ }\r
+ sign = 0;\r
+ fill = ' ';\r
+ switch (c) {\r
+ case '%':\r
+ pbuf = "%";\r
+ len = 1;\r
+ break;\r
+ case 's':\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(v)) {\r
+ fmt = fmt_start;\r
+ argidx = argidx_start;\r
+ goto unicode;\r
+ }\r
+#endif\r
+ temp = _PyObject_Str(v);\r
+#ifdef Py_USING_UNICODE\r
+ if (temp != NULL && PyUnicode_Check(temp)) {\r
+ Py_DECREF(temp);\r
+ fmt = fmt_start;\r
+ argidx = argidx_start;\r
+ goto unicode;\r
+ }\r
+#endif\r
+ /* Fall through */\r
+ case 'r':\r
+ if (c == 'r')\r
+ temp = PyObject_Repr(v);\r
+ if (temp == NULL)\r
+ goto error;\r
+ if (!PyString_Check(temp)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "%s argument has non-string str()");\r
+ Py_DECREF(temp);\r
+ goto error;\r
+ }\r
+ pbuf = PyString_AS_STRING(temp);\r
+ len = PyString_GET_SIZE(temp);\r
+ if (prec >= 0 && len > prec)\r
+ len = prec;\r
+ break;\r
+ case 'i':\r
+ case 'd':\r
+ case 'u':\r
+ case 'o':\r
+ case 'x':\r
+ case 'X':\r
+ if (c == 'i')\r
+ c = 'd';\r
+ isnumok = 0;\r
+ if (PyNumber_Check(v)) {\r
+ PyObject *iobj=NULL;\r
+\r
+ if (PyInt_Check(v) || (PyLong_Check(v))) {\r
+ iobj = v;\r
+ Py_INCREF(iobj);\r
+ }\r
+ else {\r
+ iobj = PyNumber_Int(v);\r
+ if (iobj==NULL) {\r
+ PyErr_Clear();\r
+ iobj = PyNumber_Long(v);\r
+ }\r
+ }\r
+ if (iobj!=NULL) {\r
+ if (PyInt_Check(iobj)) {\r
+ isnumok = 1;\r
+ pbuf = formatbuf;\r
+ len = formatint(pbuf,\r
+ sizeof(formatbuf),\r
+ flags, prec, c, iobj);\r
+ Py_DECREF(iobj);\r
+ if (len < 0)\r
+ goto error;\r
+ sign = 1;\r
+ }\r
+ else if (PyLong_Check(iobj)) {\r
+ int ilen;\r
+\r
+ isnumok = 1;\r
+ temp = _PyString_FormatLong(iobj, flags,\r
+ prec, c, &pbuf, &ilen);\r
+ Py_DECREF(iobj);\r
+ len = ilen;\r
+ if (!temp)\r
+ goto error;\r
+ sign = 1;\r
+ }\r
+ else {\r
+ Py_DECREF(iobj);\r
+ }\r
+ }\r
+ }\r
+ if (!isnumok) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%%%c format: a number is required, "\r
+ "not %.200s", c, Py_TYPE(v)->tp_name);\r
+ goto error;\r
+ }\r
+ if (flags & F_ZERO)\r
+ fill = '0';\r
+ break;\r
+ case 'e':\r
+ case 'E':\r
+ case 'f':\r
+ case 'F':\r
+ case 'g':\r
+ case 'G':\r
+ temp = formatfloat(v, flags, prec, c);\r
+ if (temp == NULL)\r
+ goto error;\r
+ pbuf = PyString_AS_STRING(temp);\r
+ len = PyString_GET_SIZE(temp);\r
+ sign = 1;\r
+ if (flags & F_ZERO)\r
+ fill = '0';\r
+ break;\r
+ case 'c':\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(v)) {\r
+ fmt = fmt_start;\r
+ argidx = argidx_start;\r
+ goto unicode;\r
+ }\r
+#endif\r
+ pbuf = formatbuf;\r
+ len = formatchar(pbuf, sizeof(formatbuf), v);\r
+ if (len < 0)\r
+ goto error;\r
+ break;\r
+ default:\r
+ PyErr_Format(PyExc_ValueError,\r
+ "unsupported format character '%c' (0x%x) "\r
+ "at index %zd",\r
+ c, c,\r
+ (Py_ssize_t)(fmt - 1 -\r
+ PyString_AsString(format)));\r
+ goto error;\r
+ }\r
+ if (sign) {\r
+ if (*pbuf == '-' || *pbuf == '+') {\r
+ sign = *pbuf++;\r
+ len--;\r
+ }\r
+ else if (flags & F_SIGN)\r
+ sign = '+';\r
+ else if (flags & F_BLANK)\r
+ sign = ' ';\r
+ else\r
+ sign = 0;\r
+ }\r
+ if (width < len)\r
+ width = len;\r
+ if (rescnt - (sign != 0) < width) {\r
+ reslen -= rescnt;\r
+ rescnt = width + fmtcnt + 100;\r
+ reslen += rescnt;\r
+ if (reslen < 0) {\r
+ Py_DECREF(result);\r
+ Py_XDECREF(temp);\r
+ return PyErr_NoMemory();\r
+ }\r
+ if (_PyString_Resize(&result, reslen)) {\r
+ Py_XDECREF(temp);\r
+ return NULL;\r
+ }\r
+ res = PyString_AS_STRING(result)\r
+ + reslen - rescnt;\r
+ }\r
+ if (sign) {\r
+ if (fill != ' ')\r
+ *res++ = sign;\r
+ rescnt--;\r
+ if (width > len)\r
+ width--;\r
+ }\r
+ if ((flags & F_ALT) && (c == 'x' || c == 'X')) {\r
+ assert(pbuf[0] == '0');\r
+ assert(pbuf[1] == c);\r
+ if (fill != ' ') {\r
+ *res++ = *pbuf++;\r
+ *res++ = *pbuf++;\r
+ }\r
+ rescnt -= 2;\r
+ width -= 2;\r
+ if (width < 0)\r
+ width = 0;\r
+ len -= 2;\r
+ }\r
+ if (width > len && !(flags & F_LJUST)) {\r
+ do {\r
+ --rescnt;\r
+ *res++ = fill;\r
+ } while (--width > len);\r
+ }\r
+ if (fill == ' ') {\r
+ if (sign)\r
+ *res++ = sign;\r
+ if ((flags & F_ALT) &&\r
+ (c == 'x' || c == 'X')) {\r
+ assert(pbuf[0] == '0');\r
+ assert(pbuf[1] == c);\r
+ *res++ = *pbuf++;\r
+ *res++ = *pbuf++;\r
+ }\r
+ }\r
+ Py_MEMCPY(res, pbuf, len);\r
+ res += len;\r
+ rescnt -= len;\r
+ while (--width >= len) {\r
+ --rescnt;\r
+ *res++ = ' ';\r
+ }\r
+ if (dict && (argidx < arglen) && c != '%') {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "not all arguments converted during string formatting");\r
+ Py_XDECREF(temp);\r
+ goto error;\r
+ }\r
+ Py_XDECREF(temp);\r
+ } /* '%' */\r
+ } /* until end */\r
+ if (argidx < arglen && !dict) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "not all arguments converted during string formatting");\r
+ goto error;\r
+ }\r
+ if (args_owned) {\r
+ Py_DECREF(args);\r
+ }\r
+ if (_PyString_Resize(&result, reslen - rescnt))\r
+ return NULL;\r
+ return result;\r
+\r
+#ifdef Py_USING_UNICODE\r
+ unicode:\r
+ if (args_owned) {\r
+ Py_DECREF(args);\r
+ args_owned = 0;\r
+ }\r
+ /* Fiddle args right (remove the first argidx arguments) */\r
+ if (PyTuple_Check(orig_args) && argidx > 0) {\r
+ PyObject *v;\r
+ Py_ssize_t n = PyTuple_GET_SIZE(orig_args) - argidx;\r
+ v = PyTuple_New(n);\r
+ if (v == NULL)\r
+ goto error;\r
+ while (--n >= 0) {\r
+ PyObject *w = PyTuple_GET_ITEM(orig_args, n + argidx);\r
+ Py_INCREF(w);\r
+ PyTuple_SET_ITEM(v, n, w);\r
+ }\r
+ args = v;\r
+ } else {\r
+ Py_INCREF(orig_args);\r
+ args = orig_args;\r
+ }\r
+ args_owned = 1;\r
+ /* Take what we have of the result and let the Unicode formatting\r
+ function format the rest of the input. */\r
+ rescnt = res - PyString_AS_STRING(result);\r
+ if (_PyString_Resize(&result, rescnt))\r
+ goto error;\r
+ fmtcnt = PyString_GET_SIZE(format) - \\r
+ (fmt - PyString_AS_STRING(format));\r
+ format = PyUnicode_Decode(fmt, fmtcnt, NULL, NULL);\r
+ if (format == NULL)\r
+ goto error;\r
+ v = PyUnicode_Format(format, args);\r
+ Py_DECREF(format);\r
+ if (v == NULL)\r
+ goto error;\r
+ /* Paste what we have (result) to what the Unicode formatting\r
+ function returned (v) and return the result (or error) */\r
+ w = PyUnicode_Concat(result, v);\r
+ Py_DECREF(result);\r
+ Py_DECREF(v);\r
+ Py_DECREF(args);\r
+ return w;\r
+#endif /* Py_USING_UNICODE */\r
+\r
+ error:\r
+ Py_DECREF(result);\r
+ if (args_owned) {\r
+ Py_DECREF(args);\r
+ }\r
+ return NULL;\r
+}\r
+\r
+void\r
+PyString_InternInPlace(PyObject **p)\r
+{\r
+ register PyStringObject *s = (PyStringObject *)(*p);\r
+ PyObject *t;\r
+ if (s == NULL || !PyString_Check(s))\r
+ Py_FatalError("PyString_InternInPlace: strings only please!");\r
+ /* If it's a string subclass, we don't really know what putting\r
+ it in the interned dict might do. */\r
+ if (!PyString_CheckExact(s))\r
+ return;\r
+ if (PyString_CHECK_INTERNED(s))\r
+ return;\r
+ if (interned == NULL) {\r
+ interned = PyDict_New();\r
+ if (interned == NULL) {\r
+ PyErr_Clear(); /* Don't leave an exception */\r
+ return;\r
+ }\r
+ }\r
+ t = PyDict_GetItem(interned, (PyObject *)s);\r
+ if (t) {\r
+ Py_INCREF(t);\r
+ Py_DECREF(*p);\r
+ *p = t;\r
+ return;\r
+ }\r
+\r
+ if (PyDict_SetItem(interned, (PyObject *)s, (PyObject *)s) < 0) {\r
+ PyErr_Clear();\r
+ return;\r
+ }\r
+ /* The two references in interned are not counted by refcnt.\r
+ The string deallocator will take care of this */\r
+ Py_REFCNT(s) -= 2;\r
+ PyString_CHECK_INTERNED(s) = SSTATE_INTERNED_MORTAL;\r
+}\r
+\r
+void\r
+PyString_InternImmortal(PyObject **p)\r
+{\r
+ PyString_InternInPlace(p);\r
+ if (PyString_CHECK_INTERNED(*p) != SSTATE_INTERNED_IMMORTAL) {\r
+ PyString_CHECK_INTERNED(*p) = SSTATE_INTERNED_IMMORTAL;\r
+ Py_INCREF(*p);\r
+ }\r
+}\r
+\r
+\r
+PyObject *\r
+PyString_InternFromString(const char *cp)\r
+{\r
+ PyObject *s = PyString_FromString(cp);\r
+ if (s == NULL)\r
+ return NULL;\r
+ PyString_InternInPlace(&s);\r
+ return s;\r
+}\r
+\r
+void\r
+PyString_Fini(void)\r
+{\r
+ int i;\r
+ for (i = 0; i < UCHAR_MAX + 1; i++)\r
+ Py_CLEAR(characters[i]);\r
+ Py_CLEAR(nullstring);\r
+}\r
+\r
+void _Py_ReleaseInternedStrings(void)\r
+{\r
+ PyObject *keys;\r
+ PyStringObject *s;\r
+ Py_ssize_t i, n;\r
+ Py_ssize_t immortal_size = 0, mortal_size = 0;\r
+\r
+ if (interned == NULL || !PyDict_Check(interned))\r
+ return;\r
+ keys = PyDict_Keys(interned);\r
+ if (keys == NULL || !PyList_Check(keys)) {\r
+ PyErr_Clear();\r
+ return;\r
+ }\r
+\r
+ /* Since _Py_ReleaseInternedStrings() is intended to help a leak\r
+ detector, interned strings are not forcibly deallocated; rather, we\r
+ give them their stolen references back, and then clear and DECREF\r
+ the interned dict. */\r
+\r
+ n = PyList_GET_SIZE(keys);\r
+ fprintf(stderr, "releasing %" PY_FORMAT_SIZE_T "d interned strings\n",\r
+ n);\r
+ for (i = 0; i < n; i++) {\r
+ s = (PyStringObject *) PyList_GET_ITEM(keys, i);\r
+ switch (s->ob_sstate) {\r
+ case SSTATE_NOT_INTERNED:\r
+ /* XXX Shouldn't happen */\r
+ break;\r
+ case SSTATE_INTERNED_IMMORTAL:\r
+ Py_REFCNT(s) += 1;\r
+ immortal_size += Py_SIZE(s);\r
+ break;\r
+ case SSTATE_INTERNED_MORTAL:\r
+ Py_REFCNT(s) += 2;\r
+ mortal_size += Py_SIZE(s);\r
+ break;\r
+ default:\r
+ Py_FatalError("Inconsistent interned string state.");\r
+ }\r
+ s->ob_sstate = SSTATE_NOT_INTERNED;\r
+ }\r
+ fprintf(stderr, "total size of all interned strings: "\r
+ "%" PY_FORMAT_SIZE_T "d/%" PY_FORMAT_SIZE_T "d "\r
+ "mortal/immortal\n", mortal_size, immortal_size);\r
+ Py_DECREF(keys);\r
+ PyDict_Clear(interned);\r
+ Py_CLEAR(interned);\r
+}\r
--- /dev/null
+/* Implementation helper: a struct that looks like a tuple. See timemodule\r
+ and posixmodule for example uses. */\r
+\r
+#include "Python.h"\r
+#include "structmember.h"\r
+#include "structseq.h"\r
+\r
+static char visible_length_key[] = "n_sequence_fields";\r
+static char real_length_key[] = "n_fields";\r
+static char unnamed_fields_key[] = "n_unnamed_fields";\r
+\r
+/* Fields with this name have only a field index, not a field name.\r
+ They are only allowed for indices < n_visible_fields. */\r
+char *PyStructSequence_UnnamedField = "unnamed field";\r
+\r
+#define VISIBLE_SIZE(op) Py_SIZE(op)\r
+#define VISIBLE_SIZE_TP(tp) PyInt_AsLong( \\r
+ PyDict_GetItemString((tp)->tp_dict, visible_length_key))\r
+\r
+#define REAL_SIZE_TP(tp) PyInt_AsLong( \\r
+ PyDict_GetItemString((tp)->tp_dict, real_length_key))\r
+#define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op))\r
+\r
+#define UNNAMED_FIELDS_TP(tp) PyInt_AsLong( \\r
+ PyDict_GetItemString((tp)->tp_dict, unnamed_fields_key))\r
+#define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op))\r
+\r
+\r
+PyObject *\r
+PyStructSequence_New(PyTypeObject *type)\r
+{\r
+ PyStructSequence *obj;\r
+\r
+ obj = PyObject_New(PyStructSequence, type);\r
+ if (obj == NULL)\r
+ return NULL;\r
+ Py_SIZE(obj) = VISIBLE_SIZE_TP(type);\r
+\r
+ return (PyObject*) obj;\r
+}\r
+\r
+static void\r
+structseq_dealloc(PyStructSequence *obj)\r
+{\r
+ Py_ssize_t i, size;\r
+\r
+ size = REAL_SIZE(obj);\r
+ for (i = 0; i < size; ++i) {\r
+ Py_XDECREF(obj->ob_item[i]);\r
+ }\r
+ PyObject_Del(obj);\r
+}\r
+\r
+static Py_ssize_t\r
+structseq_length(PyStructSequence *obj)\r
+{\r
+ return VISIBLE_SIZE(obj);\r
+}\r
+\r
+static PyObject*\r
+structseq_item(PyStructSequence *obj, Py_ssize_t i)\r
+{\r
+ if (i < 0 || i >= VISIBLE_SIZE(obj)) {\r
+ PyErr_SetString(PyExc_IndexError, "tuple index out of range");\r
+ return NULL;\r
+ }\r
+ Py_INCREF(obj->ob_item[i]);\r
+ return obj->ob_item[i];\r
+}\r
+\r
+static PyObject*\r
+structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)\r
+{\r
+ PyTupleObject *np;\r
+ Py_ssize_t i;\r
+\r
+ if (low < 0)\r
+ low = 0;\r
+ if (high > VISIBLE_SIZE(obj))\r
+ high = VISIBLE_SIZE(obj);\r
+ if (high < low)\r
+ high = low;\r
+ np = (PyTupleObject *)PyTuple_New(high-low);\r
+ if (np == NULL)\r
+ return NULL;\r
+ for(i = low; i < high; ++i) {\r
+ PyObject *v = obj->ob_item[i];\r
+ Py_INCREF(v);\r
+ PyTuple_SET_ITEM(np, i-low, v);\r
+ }\r
+ return (PyObject *) np;\r
+}\r
+\r
+static PyObject *\r
+structseq_subscript(PyStructSequence *self, PyObject *item)\r
+{\r
+ if (PyIndex_Check(item)) {\r
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+\r
+ if (i < 0)\r
+ i += VISIBLE_SIZE(self);\r
+\r
+ if (i < 0 || i >= VISIBLE_SIZE(self)) {\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "tuple index out of range");\r
+ return NULL;\r
+ }\r
+ Py_INCREF(self->ob_item[i]);\r
+ return self->ob_item[i];\r
+ }\r
+ else if (PySlice_Check(item)) {\r
+ Py_ssize_t start, stop, step, slicelen, cur, i;\r
+ PyObject *result;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject *)item,\r
+ VISIBLE_SIZE(self), &start, &stop,\r
+ &step, &slicelen) < 0) {\r
+ return NULL;\r
+ }\r
+ if (slicelen <= 0)\r
+ return PyTuple_New(0);\r
+ result = PyTuple_New(slicelen);\r
+ if (result == NULL)\r
+ return NULL;\r
+ for (cur = start, i = 0; i < slicelen;\r
+ cur += step, i++) {\r
+ PyObject *v = self->ob_item[cur];\r
+ Py_INCREF(v);\r
+ PyTuple_SET_ITEM(result, i, v);\r
+ }\r
+ return result;\r
+ }\r
+ else {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "structseq index must be integer");\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *arg = NULL;\r
+ PyObject *dict = NULL;\r
+ PyObject *ob;\r
+ PyStructSequence *res = NULL;\r
+ Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;\r
+ static char *kwlist[] = {"sequence", "dict", 0};\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq",\r
+ kwlist, &arg, &dict))\r
+ return NULL;\r
+\r
+ arg = PySequence_Fast(arg, "constructor requires a sequence");\r
+\r
+ if (!arg) {\r
+ return NULL;\r
+ }\r
+\r
+ if (dict && !PyDict_Check(dict)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%.500s() takes a dict as second arg, if any",\r
+ type->tp_name);\r
+ Py_DECREF(arg);\r
+ return NULL;\r
+ }\r
+\r
+ len = PySequence_Fast_GET_SIZE(arg);\r
+ min_len = VISIBLE_SIZE_TP(type);\r
+ max_len = REAL_SIZE_TP(type);\r
+ n_unnamed_fields = UNNAMED_FIELDS_TP(type);\r
+\r
+ if (min_len != max_len) {\r
+ if (len < min_len) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%.500s() takes an at least %zd-sequence (%zd-sequence given)",\r
+ type->tp_name, min_len, len);\r
+ Py_DECREF(arg);\r
+ return NULL;\r
+ }\r
+\r
+ if (len > max_len) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%.500s() takes an at most %zd-sequence (%zd-sequence given)",\r
+ type->tp_name, max_len, len);\r
+ Py_DECREF(arg);\r
+ return NULL;\r
+ }\r
+ }\r
+ else {\r
+ if (len != min_len) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%.500s() takes a %zd-sequence (%zd-sequence given)",\r
+ type->tp_name, min_len, len);\r
+ Py_DECREF(arg);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ res = (PyStructSequence*) PyStructSequence_New(type);\r
+ if (res == NULL) {\r
+ Py_DECREF(arg);\r
+ return NULL;\r
+ }\r
+ for (i = 0; i < len; ++i) {\r
+ PyObject *v = PySequence_Fast_GET_ITEM(arg, i);\r
+ Py_INCREF(v);\r
+ res->ob_item[i] = v;\r
+ }\r
+ for (; i < max_len; ++i) {\r
+ if (dict && (ob = PyDict_GetItemString(\r
+ dict, type->tp_members[i-n_unnamed_fields].name))) {\r
+ }\r
+ else {\r
+ ob = Py_None;\r
+ }\r
+ Py_INCREF(ob);\r
+ res->ob_item[i] = ob;\r
+ }\r
+\r
+ Py_DECREF(arg);\r
+ return (PyObject*) res;\r
+}\r
+\r
+static PyObject *\r
+make_tuple(PyStructSequence *obj)\r
+{\r
+ return structseq_slice(obj, 0, VISIBLE_SIZE(obj));\r
+}\r
+\r
+static PyObject *\r
+structseq_repr(PyStructSequence *obj)\r
+{\r
+ /* buffer and type size were chosen well considered. */\r
+#define REPR_BUFFER_SIZE 512\r
+#define TYPE_MAXSIZE 100\r
+\r
+ PyObject *tup;\r
+ PyTypeObject *typ = Py_TYPE(obj);\r
+ int i, removelast = 0;\r
+ Py_ssize_t len;\r
+ char buf[REPR_BUFFER_SIZE];\r
+ char *endofbuf, *pbuf = buf;\r
+\r
+ /* pointer to end of writeable buffer; safes space for "...)\0" */\r
+ endofbuf= &buf[REPR_BUFFER_SIZE-5];\r
+\r
+ if ((tup = make_tuple(obj)) == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ /* "typename(", limited to TYPE_MAXSIZE */\r
+ len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE :\r
+ strlen(typ->tp_name);\r
+ strncpy(pbuf, typ->tp_name, len);\r
+ pbuf += len;\r
+ *pbuf++ = '(';\r
+\r
+ for (i=0; i < VISIBLE_SIZE(obj); i++) {\r
+ PyObject *val, *repr;\r
+ char *cname, *crepr;\r
+\r
+ cname = typ->tp_members[i].name;\r
+\r
+ val = PyTuple_GetItem(tup, i);\r
+ if (cname == NULL || val == NULL) {\r
+ return NULL;\r
+ }\r
+ repr = PyObject_Repr(val);\r
+ if (repr == NULL) {\r
+ Py_DECREF(tup);\r
+ return NULL;\r
+ }\r
+ crepr = PyString_AsString(repr);\r
+ if (crepr == NULL) {\r
+ Py_DECREF(tup);\r
+ Py_DECREF(repr);\r
+ return NULL;\r
+ }\r
+\r
+ /* + 3: keep space for "=" and ", " */\r
+ len = strlen(cname) + strlen(crepr) + 3;\r
+ if ((pbuf+len) <= endofbuf) {\r
+ strcpy(pbuf, cname);\r
+ pbuf += strlen(cname);\r
+ *pbuf++ = '=';\r
+ strcpy(pbuf, crepr);\r
+ pbuf += strlen(crepr);\r
+ *pbuf++ = ',';\r
+ *pbuf++ = ' ';\r
+ removelast = 1;\r
+ Py_DECREF(repr);\r
+ }\r
+ else {\r
+ strcpy(pbuf, "...");\r
+ pbuf += 3;\r
+ removelast = 0;\r
+ Py_DECREF(repr);\r
+ break;\r
+ }\r
+ }\r
+ Py_DECREF(tup);\r
+ if (removelast) {\r
+ /* overwrite last ", " */\r
+ pbuf-=2;\r
+ }\r
+ *pbuf++ = ')';\r
+ *pbuf = '\0';\r
+\r
+ return PyString_FromString(buf);\r
+}\r
+\r
+static PyObject *\r
+structseq_concat(PyStructSequence *obj, PyObject *b)\r
+{\r
+ PyObject *tup, *result;\r
+ tup = make_tuple(obj);\r
+ result = PySequence_Concat(tup, b);\r
+ Py_DECREF(tup);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+structseq_repeat(PyStructSequence *obj, Py_ssize_t n)\r
+{\r
+ PyObject *tup, *result;\r
+ tup = make_tuple(obj);\r
+ result = PySequence_Repeat(tup, n);\r
+ Py_DECREF(tup);\r
+ return result;\r
+}\r
+\r
+static int\r
+structseq_contains(PyStructSequence *obj, PyObject *o)\r
+{\r
+ PyObject *tup;\r
+ int result;\r
+ tup = make_tuple(obj);\r
+ if (!tup)\r
+ return -1;\r
+ result = PySequence_Contains(tup, o);\r
+ Py_DECREF(tup);\r
+ return result;\r
+}\r
+\r
+static long\r
+structseq_hash(PyObject *obj)\r
+{\r
+ PyObject *tup;\r
+ long result;\r
+ tup = make_tuple((PyStructSequence*) obj);\r
+ if (!tup)\r
+ return -1;\r
+ result = PyObject_Hash(tup);\r
+ Py_DECREF(tup);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+structseq_richcompare(PyObject *obj, PyObject *o2, int op)\r
+{\r
+ PyObject *tup, *result;\r
+ tup = make_tuple((PyStructSequence*) obj);\r
+ result = PyObject_RichCompare(tup, o2, op);\r
+ Py_DECREF(tup);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+structseq_reduce(PyStructSequence* self)\r
+{\r
+ PyObject* tup;\r
+ PyObject* dict;\r
+ PyObject* result;\r
+ Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;\r
+ int i;\r
+\r
+ n_fields = REAL_SIZE(self);\r
+ n_visible_fields = VISIBLE_SIZE(self);\r
+ n_unnamed_fields = UNNAMED_FIELDS(self);\r
+ tup = PyTuple_New(n_visible_fields);\r
+ if (!tup) {\r
+ return NULL;\r
+ }\r
+\r
+ dict = PyDict_New();\r
+ if (!dict) {\r
+ Py_DECREF(tup);\r
+ return NULL;\r
+ }\r
+\r
+ for (i = 0; i < n_visible_fields; i++) {\r
+ Py_INCREF(self->ob_item[i]);\r
+ PyTuple_SET_ITEM(tup, i, self->ob_item[i]);\r
+ }\r
+\r
+ for (; i < n_fields; i++) {\r
+ char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;\r
+ PyDict_SetItemString(dict, n,\r
+ self->ob_item[i]);\r
+ }\r
+\r
+ result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);\r
+\r
+ Py_DECREF(tup);\r
+ Py_DECREF(dict);\r
+\r
+ return result;\r
+}\r
+\r
+static PySequenceMethods structseq_as_sequence = {\r
+ (lenfunc)structseq_length,\r
+ (binaryfunc)structseq_concat, /* sq_concat */\r
+ (ssizeargfunc)structseq_repeat, /* sq_repeat */\r
+ (ssizeargfunc)structseq_item, /* sq_item */\r
+ (ssizessizeargfunc)structseq_slice, /* sq_slice */\r
+ 0, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ (objobjproc)structseq_contains, /* sq_contains */\r
+};\r
+\r
+static PyMappingMethods structseq_as_mapping = {\r
+ (lenfunc)structseq_length,\r
+ (binaryfunc)structseq_subscript,\r
+};\r
+\r
+static PyMethodDef structseq_methods[] = {\r
+ {"__reduce__", (PyCFunction)structseq_reduce,\r
+ METH_NOARGS, NULL},\r
+ {NULL, NULL}\r
+};\r
+\r
+static PyTypeObject _struct_sequence_template = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ NULL, /* tp_name */\r
+ 0, /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ (destructor)structseq_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)structseq_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &structseq_as_sequence, /* tp_as_sequence */\r
+ &structseq_as_mapping, /* tp_as_mapping */\r
+ structseq_hash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ 0, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT, /* tp_flags */\r
+ NULL, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ structseq_richcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ structseq_methods, /* tp_methods */\r
+ NULL, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ structseq_new, /* tp_new */\r
+};\r
+\r
+void\r
+PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)\r
+{\r
+ PyObject *dict;\r
+ PyMemberDef* members;\r
+ int n_members, n_unnamed_members, i, k;\r
+\r
+#ifdef Py_TRACE_REFS\r
+ /* if the type object was chained, unchain it first\r
+ before overwriting its storage */\r
+ if (type->_ob_next) {\r
+ _Py_ForgetReference((PyObject*)type);\r
+ }\r
+#endif\r
+\r
+ n_unnamed_members = 0;\r
+ for (i = 0; desc->fields[i].name != NULL; ++i)\r
+ if (desc->fields[i].name == PyStructSequence_UnnamedField)\r
+ n_unnamed_members++;\r
+ n_members = i;\r
+\r
+ memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));\r
+ type->tp_name = desc->name;\r
+ type->tp_doc = desc->doc;\r
+ type->tp_basicsize = sizeof(PyStructSequence)+\r
+ sizeof(PyObject*)*(n_members-1);\r
+ type->tp_itemsize = 0;\r
+\r
+ members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);\r
+ if (members == NULL)\r
+ return;\r
+\r
+ for (i = k = 0; i < n_members; ++i) {\r
+ if (desc->fields[i].name == PyStructSequence_UnnamedField)\r
+ continue;\r
+ members[k].name = desc->fields[i].name;\r
+ members[k].type = T_OBJECT;\r
+ members[k].offset = offsetof(PyStructSequence, ob_item)\r
+ + i * sizeof(PyObject*);\r
+ members[k].flags = READONLY;\r
+ members[k].doc = desc->fields[i].doc;\r
+ k++;\r
+ }\r
+ members[k].name = NULL;\r
+\r
+ type->tp_members = members;\r
+\r
+ if (PyType_Ready(type) < 0)\r
+ return;\r
+ Py_INCREF(type);\r
+\r
+ dict = type->tp_dict;\r
+#define SET_DICT_FROM_INT(key, value) \\r
+ do { \\r
+ PyObject *v = PyInt_FromLong((long) value); \\r
+ if (v != NULL) { \\r
+ PyDict_SetItemString(dict, key, v); \\r
+ Py_DECREF(v); \\r
+ } \\r
+ } while (0)\r
+\r
+ SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence);\r
+ SET_DICT_FROM_INT(real_length_key, n_members);\r
+ SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members);\r
+}\r
--- /dev/null
+\r
+/* Tuple object implementation */\r
+\r
+#include "Python.h"\r
+\r
+/* Speed optimization to avoid frequent malloc/free of small tuples */\r
+#ifndef PyTuple_MAXSAVESIZE\r
+#define PyTuple_MAXSAVESIZE 20 /* Largest tuple to save on free list */\r
+#endif\r
+#ifndef PyTuple_MAXFREELIST\r
+#define PyTuple_MAXFREELIST 2000 /* Maximum number of tuples of each size to save */\r
+#endif\r
+\r
+#if PyTuple_MAXSAVESIZE > 0\r
+/* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, entry 0 is the empty\r
+ tuple () of which at most one instance will be allocated.\r
+*/\r
+static PyTupleObject *free_list[PyTuple_MAXSAVESIZE];\r
+static int numfree[PyTuple_MAXSAVESIZE];\r
+#endif\r
+#ifdef COUNT_ALLOCS\r
+Py_ssize_t fast_tuple_allocs;\r
+Py_ssize_t tuple_zero_allocs;\r
+#endif\r
+\r
+/* Debug statistic to count GC tracking of tuples.\r
+ Please note that tuples are only untracked when considered by the GC, and\r
+ many of them will be dead before. Therefore, a tracking rate close to 100%\r
+ does not necessarily prove that the heuristic is inefficient.\r
+*/\r
+#ifdef SHOW_TRACK_COUNT\r
+static Py_ssize_t count_untracked = 0;\r
+static Py_ssize_t count_tracked = 0;\r
+\r
+static void\r
+show_track(void)\r
+{\r
+ fprintf(stderr, "Tuples created: %" PY_FORMAT_SIZE_T "d\n",\r
+ count_tracked + count_untracked);\r
+ fprintf(stderr, "Tuples tracked by the GC: %" PY_FORMAT_SIZE_T\r
+ "d\n", count_tracked);\r
+ fprintf(stderr, "%.2f%% tuple tracking rate\n\n",\r
+ (100.0*count_tracked/(count_untracked+count_tracked)));\r
+}\r
+#endif\r
+\r
+\r
+PyObject *\r
+PyTuple_New(register Py_ssize_t size)\r
+{\r
+ register PyTupleObject *op;\r
+ Py_ssize_t i;\r
+ if (size < 0) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+#if PyTuple_MAXSAVESIZE > 0\r
+ if (size == 0 && free_list[0]) {\r
+ op = free_list[0];\r
+ Py_INCREF(op);\r
+#ifdef COUNT_ALLOCS\r
+ tuple_zero_allocs++;\r
+#endif\r
+ return (PyObject *) op;\r
+ }\r
+ if (size < PyTuple_MAXSAVESIZE && (op = free_list[size]) != NULL) {\r
+ free_list[size] = (PyTupleObject *) op->ob_item[0];\r
+ numfree[size]--;\r
+#ifdef COUNT_ALLOCS\r
+ fast_tuple_allocs++;\r
+#endif\r
+ /* Inline PyObject_InitVar */\r
+#ifdef Py_TRACE_REFS\r
+ Py_SIZE(op) = size;\r
+ Py_TYPE(op) = &PyTuple_Type;\r
+#endif\r
+ _Py_NewReference((PyObject *)op);\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ Py_ssize_t nbytes = size * sizeof(PyObject *);\r
+ /* Check for overflow */\r
+ if (nbytes / sizeof(PyObject *) != (size_t)size ||\r
+ (nbytes > PY_SSIZE_T_MAX - sizeof(PyTupleObject) - sizeof(PyObject *)))\r
+ {\r
+ return PyErr_NoMemory();\r
+ }\r
+\r
+ op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);\r
+ if (op == NULL)\r
+ return NULL;\r
+ }\r
+ for (i=0; i < size; i++)\r
+ op->ob_item[i] = NULL;\r
+#if PyTuple_MAXSAVESIZE > 0\r
+ if (size == 0) {\r
+ free_list[0] = op;\r
+ ++numfree[0];\r
+ Py_INCREF(op); /* extra INCREF so that this is never freed */\r
+ }\r
+#endif\r
+#ifdef SHOW_TRACK_COUNT\r
+ count_tracked++;\r
+#endif\r
+ _PyObject_GC_TRACK(op);\r
+ return (PyObject *) op;\r
+}\r
+\r
+Py_ssize_t\r
+PyTuple_Size(register PyObject *op)\r
+{\r
+ if (!PyTuple_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ else\r
+ return Py_SIZE(op);\r
+}\r
+\r
+PyObject *\r
+PyTuple_GetItem(register PyObject *op, register Py_ssize_t i)\r
+{\r
+ if (!PyTuple_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ if (i < 0 || i >= Py_SIZE(op)) {\r
+ PyErr_SetString(PyExc_IndexError, "tuple index out of range");\r
+ return NULL;\r
+ }\r
+ return ((PyTupleObject *)op) -> ob_item[i];\r
+}\r
+\r
+int\r
+PyTuple_SetItem(register PyObject *op, register Py_ssize_t i, PyObject *newitem)\r
+{\r
+ register PyObject *olditem;\r
+ register PyObject **p;\r
+ if (!PyTuple_Check(op) || op->ob_refcnt != 1) {\r
+ Py_XDECREF(newitem);\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ if (i < 0 || i >= Py_SIZE(op)) {\r
+ Py_XDECREF(newitem);\r
+ PyErr_SetString(PyExc_IndexError,\r
+ "tuple assignment index out of range");\r
+ return -1;\r
+ }\r
+ p = ((PyTupleObject *)op) -> ob_item + i;\r
+ olditem = *p;\r
+ *p = newitem;\r
+ Py_XDECREF(olditem);\r
+ return 0;\r
+}\r
+\r
+void\r
+_PyTuple_MaybeUntrack(PyObject *op)\r
+{\r
+ PyTupleObject *t;\r
+ Py_ssize_t i, n;\r
+\r
+ if (!PyTuple_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))\r
+ return;\r
+ t = (PyTupleObject *) op;\r
+ n = Py_SIZE(t);\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *elt = PyTuple_GET_ITEM(t, i);\r
+ /* Tuple with NULL elements aren't\r
+ fully constructed, don't untrack\r
+ them yet. */\r
+ if (!elt ||\r
+ _PyObject_GC_MAY_BE_TRACKED(elt))\r
+ return;\r
+ }\r
+#ifdef SHOW_TRACK_COUNT\r
+ count_tracked--;\r
+ count_untracked++;\r
+#endif\r
+ _PyObject_GC_UNTRACK(op);\r
+}\r
+\r
+PyObject *\r
+PyTuple_Pack(Py_ssize_t n, ...)\r
+{\r
+ Py_ssize_t i;\r
+ PyObject *o;\r
+ PyObject *result;\r
+ PyObject **items;\r
+ va_list vargs;\r
+\r
+ va_start(vargs, n);\r
+ result = PyTuple_New(n);\r
+ if (result == NULL) {\r
+ va_end(vargs);\r
+ return NULL;\r
+ }\r
+ items = ((PyTupleObject *)result)->ob_item;\r
+ for (i = 0; i < n; i++) {\r
+ o = va_arg(vargs, PyObject *);\r
+ Py_INCREF(o);\r
+ items[i] = o;\r
+ }\r
+ va_end(vargs);\r
+ return result;\r
+}\r
+\r
+\r
+/* Methods */\r
+\r
+static void\r
+tupledealloc(register PyTupleObject *op)\r
+{\r
+ register Py_ssize_t i;\r
+ register Py_ssize_t len = Py_SIZE(op);\r
+ PyObject_GC_UnTrack(op);\r
+ Py_TRASHCAN_SAFE_BEGIN(op)\r
+ if (len > 0) {\r
+ i = len;\r
+ while (--i >= 0)\r
+ Py_XDECREF(op->ob_item[i]);\r
+#if PyTuple_MAXSAVESIZE > 0\r
+ if (len < PyTuple_MAXSAVESIZE &&\r
+ numfree[len] < PyTuple_MAXFREELIST &&\r
+ Py_TYPE(op) == &PyTuple_Type)\r
+ {\r
+ op->ob_item[0] = (PyObject *) free_list[len];\r
+ numfree[len]++;\r
+ free_list[len] = op;\r
+ goto done; /* return */\r
+ }\r
+#endif\r
+ }\r
+ Py_TYPE(op)->tp_free((PyObject *)op);\r
+done:\r
+ Py_TRASHCAN_SAFE_END(op)\r
+}\r
+\r
+static int\r
+tupleprint(PyTupleObject *op, FILE *fp, int flags)\r
+{\r
+ Py_ssize_t i;\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, "(");\r
+ Py_END_ALLOW_THREADS\r
+ for (i = 0; i < Py_SIZE(op); i++) {\r
+ if (i > 0) {\r
+ Py_BEGIN_ALLOW_THREADS\r
+ fprintf(fp, ", ");\r
+ Py_END_ALLOW_THREADS\r
+ }\r
+ if (PyObject_Print(op->ob_item[i], fp, 0) != 0)\r
+ return -1;\r
+ }\r
+ i = Py_SIZE(op);\r
+ Py_BEGIN_ALLOW_THREADS\r
+ if (i == 1)\r
+ fprintf(fp, ",");\r
+ fprintf(fp, ")");\r
+ Py_END_ALLOW_THREADS\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+tuplerepr(PyTupleObject *v)\r
+{\r
+ Py_ssize_t i, n;\r
+ PyObject *s, *temp;\r
+ PyObject *pieces, *result = NULL;\r
+\r
+ n = Py_SIZE(v);\r
+ if (n == 0)\r
+ return PyString_FromString("()");\r
+\r
+ /* While not mutable, it is still possible to end up with a cycle in a\r
+ tuple through an object that stores itself within a tuple (and thus\r
+ infinitely asks for the repr of itself). This should only be\r
+ possible within a type. */\r
+ i = Py_ReprEnter((PyObject *)v);\r
+ if (i != 0) {\r
+ return i > 0 ? PyString_FromString("(...)") : NULL;\r
+ }\r
+\r
+ pieces = PyTuple_New(n);\r
+ if (pieces == NULL)\r
+ return NULL;\r
+\r
+ /* Do repr() on each element. */\r
+ for (i = 0; i < n; ++i) {\r
+ if (Py_EnterRecursiveCall(" while getting the repr of a tuple"))\r
+ goto Done;\r
+ s = PyObject_Repr(v->ob_item[i]);\r
+ Py_LeaveRecursiveCall();\r
+ if (s == NULL)\r
+ goto Done;\r
+ PyTuple_SET_ITEM(pieces, i, s);\r
+ }\r
+\r
+ /* Add "()" decorations to the first and last items. */\r
+ assert(n > 0);\r
+ s = PyString_FromString("(");\r
+ if (s == NULL)\r
+ goto Done;\r
+ temp = PyTuple_GET_ITEM(pieces, 0);\r
+ PyString_ConcatAndDel(&s, temp);\r
+ PyTuple_SET_ITEM(pieces, 0, s);\r
+ if (s == NULL)\r
+ goto Done;\r
+\r
+ s = PyString_FromString(n == 1 ? ",)" : ")");\r
+ if (s == NULL)\r
+ goto Done;\r
+ temp = PyTuple_GET_ITEM(pieces, n-1);\r
+ PyString_ConcatAndDel(&temp, s);\r
+ PyTuple_SET_ITEM(pieces, n-1, temp);\r
+ if (temp == NULL)\r
+ goto Done;\r
+\r
+ /* Paste them all together with ", " between. */\r
+ s = PyString_FromString(", ");\r
+ if (s == NULL)\r
+ goto Done;\r
+ result = _PyString_Join(s, pieces);\r
+ Py_DECREF(s);\r
+\r
+Done:\r
+ Py_DECREF(pieces);\r
+ Py_ReprLeave((PyObject *)v);\r
+ return result;\r
+}\r
+\r
+/* The addend 82520, was selected from the range(0, 1000000) for\r
+ generating the greatest number of prime multipliers for tuples\r
+ upto length eight:\r
+\r
+ 1082527, 1165049, 1082531, 1165057, 1247581, 1330103, 1082533,\r
+ 1330111, 1412633, 1165069, 1247599, 1495177, 1577699\r
+*/\r
+\r
+static long\r
+tuplehash(PyTupleObject *v)\r
+{\r
+ register long x, y;\r
+ register Py_ssize_t len = Py_SIZE(v);\r
+ register PyObject **p;\r
+ long mult = 1000003L;\r
+ x = 0x345678L;\r
+ p = v->ob_item;\r
+ while (--len >= 0) {\r
+ y = PyObject_Hash(*p++);\r
+ if (y == -1)\r
+ return -1;\r
+ x = (x ^ y) * mult;\r
+ /* the cast might truncate len; that doesn't change hash stability */\r
+ mult += (long)(82520L + len + len);\r
+ }\r
+ x += 97531L;\r
+ if (x == -1)\r
+ x = -2;\r
+ return x;\r
+}\r
+\r
+static Py_ssize_t\r
+tuplelength(PyTupleObject *a)\r
+{\r
+ return Py_SIZE(a);\r
+}\r
+\r
+static int\r
+tuplecontains(PyTupleObject *a, PyObject *el)\r
+{\r
+ Py_ssize_t i;\r
+ int cmp;\r
+\r
+ for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)\r
+ cmp = PyObject_RichCompareBool(el, PyTuple_GET_ITEM(a, i),\r
+ Py_EQ);\r
+ return cmp;\r
+}\r
+\r
+static PyObject *\r
+tupleitem(register PyTupleObject *a, register Py_ssize_t i)\r
+{\r
+ if (i < 0 || i >= Py_SIZE(a)) {\r
+ PyErr_SetString(PyExc_IndexError, "tuple index out of range");\r
+ return NULL;\r
+ }\r
+ Py_INCREF(a->ob_item[i]);\r
+ return a->ob_item[i];\r
+}\r
+\r
+static PyObject *\r
+tupleslice(register PyTupleObject *a, register Py_ssize_t ilow,\r
+ register Py_ssize_t ihigh)\r
+{\r
+ register PyTupleObject *np;\r
+ PyObject **src, **dest;\r
+ register Py_ssize_t i;\r
+ Py_ssize_t len;\r
+ if (ilow < 0)\r
+ ilow = 0;\r
+ if (ihigh > Py_SIZE(a))\r
+ ihigh = Py_SIZE(a);\r
+ if (ihigh < ilow)\r
+ ihigh = ilow;\r
+ if (ilow == 0 && ihigh == Py_SIZE(a) && PyTuple_CheckExact(a)) {\r
+ Py_INCREF(a);\r
+ return (PyObject *)a;\r
+ }\r
+ len = ihigh - ilow;\r
+ np = (PyTupleObject *)PyTuple_New(len);\r
+ if (np == NULL)\r
+ return NULL;\r
+ src = a->ob_item + ilow;\r
+ dest = np->ob_item;\r
+ for (i = 0; i < len; i++) {\r
+ PyObject *v = src[i];\r
+ Py_INCREF(v);\r
+ dest[i] = v;\r
+ }\r
+ return (PyObject *)np;\r
+}\r
+\r
+PyObject *\r
+PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j)\r
+{\r
+ if (op == NULL || !PyTuple_Check(op)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return tupleslice((PyTupleObject *)op, i, j);\r
+}\r
+\r
+static PyObject *\r
+tupleconcat(register PyTupleObject *a, register PyObject *bb)\r
+{\r
+ register Py_ssize_t size;\r
+ register Py_ssize_t i;\r
+ PyObject **src, **dest;\r
+ PyTupleObject *np;\r
+ if (!PyTuple_Check(bb)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can only concatenate tuple (not \"%.200s\") to tuple",\r
+ Py_TYPE(bb)->tp_name);\r
+ return NULL;\r
+ }\r
+#define b ((PyTupleObject *)bb)\r
+ size = Py_SIZE(a) + Py_SIZE(b);\r
+ if (size < 0)\r
+ return PyErr_NoMemory();\r
+ np = (PyTupleObject *) PyTuple_New(size);\r
+ if (np == NULL) {\r
+ return NULL;\r
+ }\r
+ src = a->ob_item;\r
+ dest = np->ob_item;\r
+ for (i = 0; i < Py_SIZE(a); i++) {\r
+ PyObject *v = src[i];\r
+ Py_INCREF(v);\r
+ dest[i] = v;\r
+ }\r
+ src = b->ob_item;\r
+ dest = np->ob_item + Py_SIZE(a);\r
+ for (i = 0; i < Py_SIZE(b); i++) {\r
+ PyObject *v = src[i];\r
+ Py_INCREF(v);\r
+ dest[i] = v;\r
+ }\r
+ return (PyObject *)np;\r
+#undef b\r
+}\r
+\r
+static PyObject *\r
+tuplerepeat(PyTupleObject *a, Py_ssize_t n)\r
+{\r
+ Py_ssize_t i, j;\r
+ Py_ssize_t size;\r
+ PyTupleObject *np;\r
+ PyObject **p, **items;\r
+ if (n < 0)\r
+ n = 0;\r
+ if (Py_SIZE(a) == 0 || n == 1) {\r
+ if (PyTuple_CheckExact(a)) {\r
+ /* Since tuples are immutable, we can return a shared\r
+ copy in this case */\r
+ Py_INCREF(a);\r
+ return (PyObject *)a;\r
+ }\r
+ if (Py_SIZE(a) == 0)\r
+ return PyTuple_New(0);\r
+ }\r
+ size = Py_SIZE(a) * n;\r
+ if (size/Py_SIZE(a) != n)\r
+ return PyErr_NoMemory();\r
+ np = (PyTupleObject *) PyTuple_New(size);\r
+ if (np == NULL)\r
+ return NULL;\r
+ p = np->ob_item;\r
+ items = a->ob_item;\r
+ for (i = 0; i < n; i++) {\r
+ for (j = 0; j < Py_SIZE(a); j++) {\r
+ *p = items[j];\r
+ Py_INCREF(*p);\r
+ p++;\r
+ }\r
+ }\r
+ return (PyObject *) np;\r
+}\r
+\r
+static PyObject *\r
+tupleindex(PyTupleObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t i, start=0, stop=Py_SIZE(self);\r
+ PyObject *v;\r
+\r
+ if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,\r
+ _PyEval_SliceIndex, &start,\r
+ _PyEval_SliceIndex, &stop))\r
+ return NULL;\r
+ if (start < 0) {\r
+ start += Py_SIZE(self);\r
+ if (start < 0)\r
+ start = 0;\r
+ }\r
+ if (stop < 0) {\r
+ stop += Py_SIZE(self);\r
+ if (stop < 0)\r
+ stop = 0;\r
+ }\r
+ for (i = start; i < stop && i < Py_SIZE(self); i++) {\r
+ int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);\r
+ if (cmp > 0)\r
+ return PyInt_FromSsize_t(i);\r
+ else if (cmp < 0)\r
+ return NULL;\r
+ }\r
+ PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in tuple");\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+tuplecount(PyTupleObject *self, PyObject *v)\r
+{\r
+ Py_ssize_t count = 0;\r
+ Py_ssize_t i;\r
+\r
+ for (i = 0; i < Py_SIZE(self); i++) {\r
+ int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);\r
+ if (cmp > 0)\r
+ count++;\r
+ else if (cmp < 0)\r
+ return NULL;\r
+ }\r
+ return PyInt_FromSsize_t(count);\r
+}\r
+\r
+static int\r
+tupletraverse(PyTupleObject *o, visitproc visit, void *arg)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ for (i = Py_SIZE(o); --i >= 0; )\r
+ Py_VISIT(o->ob_item[i]);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+tuplerichcompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyTupleObject *vt, *wt;\r
+ Py_ssize_t i;\r
+ Py_ssize_t vlen, wlen;\r
+\r
+ if (!PyTuple_Check(v) || !PyTuple_Check(w)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+\r
+ vt = (PyTupleObject *)v;\r
+ wt = (PyTupleObject *)w;\r
+\r
+ vlen = Py_SIZE(vt);\r
+ wlen = Py_SIZE(wt);\r
+\r
+ /* Note: the corresponding code for lists has an "early out" test\r
+ * here when op is EQ or NE and the lengths differ. That pays there,\r
+ * but Tim was unable to find any real code where EQ/NE tuple\r
+ * compares don't have the same length, so testing for it here would\r
+ * have cost without benefit.\r
+ */\r
+\r
+ /* Search for the first index where items are different.\r
+ * Note that because tuples are immutable, it's safe to reuse\r
+ * vlen and wlen across the comparison calls.\r
+ */\r
+ for (i = 0; i < vlen && i < wlen; i++) {\r
+ int k = PyObject_RichCompareBool(vt->ob_item[i],\r
+ wt->ob_item[i], Py_EQ);\r
+ if (k < 0)\r
+ return NULL;\r
+ if (!k)\r
+ break;\r
+ }\r
+\r
+ if (i >= vlen || i >= wlen) {\r
+ /* No more items to compare -- compare sizes */\r
+ int cmp;\r
+ PyObject *res;\r
+ switch (op) {\r
+ case Py_LT: cmp = vlen < wlen; break;\r
+ case Py_LE: cmp = vlen <= wlen; break;\r
+ case Py_EQ: cmp = vlen == wlen; break;\r
+ case Py_NE: cmp = vlen != wlen; break;\r
+ case Py_GT: cmp = vlen > wlen; break;\r
+ case Py_GE: cmp = vlen >= wlen; break;\r
+ default: return NULL; /* cannot happen */\r
+ }\r
+ if (cmp)\r
+ res = Py_True;\r
+ else\r
+ res = Py_False;\r
+ Py_INCREF(res);\r
+ return res;\r
+ }\r
+\r
+ /* We have an item that differs -- shortcuts for EQ/NE */\r
+ if (op == Py_EQ) {\r
+ Py_INCREF(Py_False);\r
+ return Py_False;\r
+ }\r
+ if (op == Py_NE) {\r
+ Py_INCREF(Py_True);\r
+ return Py_True;\r
+ }\r
+\r
+ /* Compare the final item again using the proper operator */\r
+ return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op);\r
+}\r
+\r
+static PyObject *\r
+tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);\r
+\r
+static PyObject *\r
+tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *arg = NULL;\r
+ static char *kwlist[] = {"sequence", 0};\r
+\r
+ if (type != &PyTuple_Type)\r
+ return tuple_subtype_new(type, args, kwds);\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))\r
+ return NULL;\r
+\r
+ if (arg == NULL)\r
+ return PyTuple_New(0);\r
+ else\r
+ return PySequence_Tuple(arg);\r
+}\r
+\r
+static PyObject *\r
+tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *tmp, *newobj, *item;\r
+ Py_ssize_t i, n;\r
+\r
+ assert(PyType_IsSubtype(type, &PyTuple_Type));\r
+ tmp = tuple_new(&PyTuple_Type, args, kwds);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ assert(PyTuple_Check(tmp));\r
+ newobj = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));\r
+ if (newobj == NULL)\r
+ return NULL;\r
+ for (i = 0; i < n; i++) {\r
+ item = PyTuple_GET_ITEM(tmp, i);\r
+ Py_INCREF(item);\r
+ PyTuple_SET_ITEM(newobj, i, item);\r
+ }\r
+ Py_DECREF(tmp);\r
+ return newobj;\r
+}\r
+\r
+PyDoc_STRVAR(tuple_doc,\r
+"tuple() -> empty tuple\n\\r
+tuple(iterable) -> tuple initialized from iterable's items\n\\r
+\n\\r
+If the argument is a tuple, the return value is the same object.");\r
+\r
+static PySequenceMethods tuple_as_sequence = {\r
+ (lenfunc)tuplelength, /* sq_length */\r
+ (binaryfunc)tupleconcat, /* sq_concat */\r
+ (ssizeargfunc)tuplerepeat, /* sq_repeat */\r
+ (ssizeargfunc)tupleitem, /* sq_item */\r
+ (ssizessizeargfunc)tupleslice, /* sq_slice */\r
+ 0, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ (objobjproc)tuplecontains, /* sq_contains */\r
+};\r
+\r
+static PyObject*\r
+tuplesubscript(PyTupleObject* self, PyObject* item)\r
+{\r
+ if (PyIndex_Check(item)) {\r
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ if (i < 0)\r
+ i += PyTuple_GET_SIZE(self);\r
+ return tupleitem(self, i);\r
+ }\r
+ else if (PySlice_Check(item)) {\r
+ Py_ssize_t start, stop, step, slicelength, cur, i;\r
+ PyObject* result;\r
+ PyObject* it;\r
+ PyObject **src, **dest;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject*)item,\r
+ PyTuple_GET_SIZE(self),\r
+ &start, &stop, &step, &slicelength) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ if (slicelength <= 0) {\r
+ return PyTuple_New(0);\r
+ }\r
+ else if (start == 0 && step == 1 &&\r
+ slicelength == PyTuple_GET_SIZE(self) &&\r
+ PyTuple_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+ }\r
+ else {\r
+ result = PyTuple_New(slicelength);\r
+ if (!result) return NULL;\r
+\r
+ src = self->ob_item;\r
+ dest = ((PyTupleObject *)result)->ob_item;\r
+ for (cur = start, i = 0; i < slicelength;\r
+ cur += step, i++) {\r
+ it = src[cur];\r
+ Py_INCREF(it);\r
+ dest[i] = it;\r
+ }\r
+\r
+ return result;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "tuple indices must be integers, not %.200s",\r
+ Py_TYPE(item)->tp_name);\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static PyObject *\r
+tuple_getnewargs(PyTupleObject *v)\r
+{\r
+ return Py_BuildValue("(N)", tupleslice(v, 0, Py_SIZE(v)));\r
+\r
+}\r
+\r
+PyDoc_STRVAR(index_doc,\r
+"T.index(value, [start, [stop]]) -> integer -- return first index of value.\n"\r
+"Raises ValueError if the value is not present."\r
+);\r
+PyDoc_STRVAR(count_doc,\r
+"T.count(value) -> integer -- return number of occurrences of value");\r
+\r
+static PyMethodDef tuple_methods[] = {\r
+ {"__getnewargs__", (PyCFunction)tuple_getnewargs, METH_NOARGS},\r
+ {"index", (PyCFunction)tupleindex, METH_VARARGS, index_doc},\r
+ {"count", (PyCFunction)tuplecount, METH_O, count_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+static PyMappingMethods tuple_as_mapping = {\r
+ (lenfunc)tuplelength,\r
+ (binaryfunc)tuplesubscript,\r
+ 0\r
+};\r
+\r
+static PyObject *tuple_iter(PyObject *seq);\r
+\r
+PyTypeObject PyTuple_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "tuple",\r
+ sizeof(PyTupleObject) - sizeof(PyObject *),\r
+ sizeof(PyObject *),\r
+ (destructor)tupledealloc, /* tp_dealloc */\r
+ (printfunc)tupleprint, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)tuplerepr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ &tuple_as_sequence, /* tp_as_sequence */\r
+ &tuple_as_mapping, /* tp_as_mapping */\r
+ (hashfunc)tuplehash, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS, /* tp_flags */\r
+ tuple_doc, /* tp_doc */\r
+ (traverseproc)tupletraverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ tuplerichcompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ tuple_iter, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ tuple_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ tuple_new, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
+\r
+/* The following function breaks the notion that tuples are immutable:\r
+ it changes the size of a tuple. We get away with this only if there\r
+ is only one module referencing the object. You can also think of it\r
+ as creating a new tuple object and destroying the old one, only more\r
+ efficiently. In any case, don't use this if the tuple may already be\r
+ known to some other part of the code. */\r
+\r
+int\r
+_PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)\r
+{\r
+ register PyTupleObject *v;\r
+ register PyTupleObject *sv;\r
+ Py_ssize_t i;\r
+ Py_ssize_t oldsize;\r
+\r
+ v = (PyTupleObject *) *pv;\r
+ if (v == NULL || Py_TYPE(v) != &PyTuple_Type ||\r
+ (Py_SIZE(v) != 0 && Py_REFCNT(v) != 1)) {\r
+ *pv = 0;\r
+ Py_XDECREF(v);\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ oldsize = Py_SIZE(v);\r
+ if (oldsize == newsize)\r
+ return 0;\r
+\r
+ if (oldsize == 0) {\r
+ /* Empty tuples are often shared, so we should never\r
+ resize them in-place even if we do own the only\r
+ (current) reference */\r
+ Py_DECREF(v);\r
+ *pv = PyTuple_New(newsize);\r
+ return *pv == NULL ? -1 : 0;\r
+ }\r
+\r
+ /* XXX UNREF/NEWREF interface should be more symmetrical */\r
+ _Py_DEC_REFTOTAL;\r
+ if (_PyObject_GC_IS_TRACKED(v))\r
+ _PyObject_GC_UNTRACK(v);\r
+ _Py_ForgetReference((PyObject *) v);\r
+ /* DECREF items deleted by shrinkage */\r
+ for (i = newsize; i < oldsize; i++) {\r
+ Py_CLEAR(v->ob_item[i]);\r
+ }\r
+ sv = PyObject_GC_Resize(PyTupleObject, v, newsize);\r
+ if (sv == NULL) {\r
+ *pv = NULL;\r
+ PyObject_GC_Del(v);\r
+ return -1;\r
+ }\r
+ _Py_NewReference((PyObject *) sv);\r
+ /* Zero out items added by growing */\r
+ if (newsize > oldsize)\r
+ memset(&sv->ob_item[oldsize], 0,\r
+ sizeof(*sv->ob_item) * (newsize - oldsize));\r
+ *pv = (PyObject *) sv;\r
+ _PyObject_GC_TRACK(sv);\r
+ return 0;\r
+}\r
+\r
+int\r
+PyTuple_ClearFreeList(void)\r
+{\r
+ int freelist_size = 0;\r
+#if PyTuple_MAXSAVESIZE > 0\r
+ int i;\r
+ for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {\r
+ PyTupleObject *p, *q;\r
+ p = free_list[i];\r
+ freelist_size += numfree[i];\r
+ free_list[i] = NULL;\r
+ numfree[i] = 0;\r
+ while (p) {\r
+ q = p;\r
+ p = (PyTupleObject *)(p->ob_item[0]);\r
+ PyObject_GC_Del(q);\r
+ }\r
+ }\r
+#endif\r
+ return freelist_size;\r
+}\r
+\r
+void\r
+PyTuple_Fini(void)\r
+{\r
+#if PyTuple_MAXSAVESIZE > 0\r
+ /* empty tuples are used all over the place and applications may\r
+ * rely on the fact that an empty tuple is a singleton. */\r
+ Py_CLEAR(free_list[0]);\r
+\r
+ (void)PyTuple_ClearFreeList();\r
+#endif\r
+#ifdef SHOW_TRACK_COUNT\r
+ show_track();\r
+#endif\r
+}\r
+\r
+/*********************** Tuple Iterator **************************/\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ long it_index;\r
+ PyTupleObject *it_seq; /* Set to NULL when iterator is exhausted */\r
+} tupleiterobject;\r
+\r
+static void\r
+tupleiter_dealloc(tupleiterobject *it)\r
+{\r
+ _PyObject_GC_UNTRACK(it);\r
+ Py_XDECREF(it->it_seq);\r
+ PyObject_GC_Del(it);\r
+}\r
+\r
+static int\r
+tupleiter_traverse(tupleiterobject *it, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(it->it_seq);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+tupleiter_next(tupleiterobject *it)\r
+{\r
+ PyTupleObject *seq;\r
+ PyObject *item;\r
+\r
+ assert(it != NULL);\r
+ seq = it->it_seq;\r
+ if (seq == NULL)\r
+ return NULL;\r
+ assert(PyTuple_Check(seq));\r
+\r
+ if (it->it_index < PyTuple_GET_SIZE(seq)) {\r
+ item = PyTuple_GET_ITEM(seq, it->it_index);\r
+ ++it->it_index;\r
+ Py_INCREF(item);\r
+ return item;\r
+ }\r
+\r
+ Py_DECREF(seq);\r
+ it->it_seq = NULL;\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+tupleiter_len(tupleiterobject *it)\r
+{\r
+ Py_ssize_t len = 0;\r
+ if (it->it_seq)\r
+ len = PyTuple_GET_SIZE(it->it_seq) - it->it_index;\r
+ return PyInt_FromSsize_t(len);\r
+}\r
+\r
+PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
+\r
+static PyMethodDef tupleiter_methods[] = {\r
+ {"__length_hint__", (PyCFunction)tupleiter_len, METH_NOARGS, length_hint_doc},\r
+ {NULL, NULL} /* sentinel */\r
+};\r
+\r
+PyTypeObject PyTupleIter_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "tupleiterator", /* tp_name */\r
+ sizeof(tupleiterobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ (destructor)tupleiter_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ 0, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)tupleiter_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ PyObject_SelfIter, /* tp_iter */\r
+ (iternextfunc)tupleiter_next, /* tp_iternext */\r
+ tupleiter_methods, /* tp_methods */\r
+ 0,\r
+};\r
+\r
+static PyObject *\r
+tuple_iter(PyObject *seq)\r
+{\r
+ tupleiterobject *it;\r
+\r
+ if (!PyTuple_Check(seq)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ it = PyObject_GC_New(tupleiterobject, &PyTupleIter_Type);\r
+ if (it == NULL)\r
+ return NULL;\r
+ it->it_index = 0;\r
+ Py_INCREF(seq);\r
+ it->it_seq = (PyTupleObject *)seq;\r
+ _PyObject_GC_TRACK(it);\r
+ return (PyObject *)it;\r
+}\r
--- /dev/null
+/* Type object implementation */\r
+\r
+#include "Python.h"\r
+#include "structmember.h"\r
+\r
+#include <ctype.h>\r
+\r
+\r
+/* Support type attribute cache */\r
+\r
+/* The cache can keep references to the names alive for longer than\r
+ they normally would. This is why the maximum size is limited to\r
+ MCACHE_MAX_ATTR_SIZE, since it might be a problem if very large\r
+ strings are used as attribute names. */\r
+#define MCACHE_MAX_ATTR_SIZE 100\r
+#define MCACHE_SIZE_EXP 10\r
+#define MCACHE_HASH(version, name_hash) \\r
+ (((unsigned int)(version) * (unsigned int)(name_hash)) \\r
+ >> (8*sizeof(unsigned int) - MCACHE_SIZE_EXP))\r
+#define MCACHE_HASH_METHOD(type, name) \\r
+ MCACHE_HASH((type)->tp_version_tag, \\r
+ ((PyStringObject *)(name))->ob_shash)\r
+#define MCACHE_CACHEABLE_NAME(name) \\r
+ PyString_CheckExact(name) && \\r
+ PyString_GET_SIZE(name) <= MCACHE_MAX_ATTR_SIZE\r
+\r
+struct method_cache_entry {\r
+ unsigned int version;\r
+ PyObject *name; /* reference to exactly a str or None */\r
+ PyObject *value; /* borrowed */\r
+};\r
+\r
+static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP];\r
+static unsigned int next_version_tag = 0;\r
+\r
+unsigned int\r
+PyType_ClearCache(void)\r
+{\r
+ Py_ssize_t i;\r
+ unsigned int cur_version_tag = next_version_tag - 1;\r
+\r
+ for (i = 0; i < (1 << MCACHE_SIZE_EXP); i++) {\r
+ method_cache[i].version = 0;\r
+ Py_CLEAR(method_cache[i].name);\r
+ method_cache[i].value = NULL;\r
+ }\r
+ next_version_tag = 0;\r
+ /* mark all version tags as invalid */\r
+ PyType_Modified(&PyBaseObject_Type);\r
+ return cur_version_tag;\r
+}\r
+\r
+void\r
+PyType_Modified(PyTypeObject *type)\r
+{\r
+ /* Invalidate any cached data for the specified type and all\r
+ subclasses. This function is called after the base\r
+ classes, mro, or attributes of the type are altered.\r
+\r
+ Invariants:\r
+\r
+ - Py_TPFLAGS_VALID_VERSION_TAG is never set if\r
+ Py_TPFLAGS_HAVE_VERSION_TAG is not set (e.g. on type\r
+ objects coming from non-recompiled extension modules)\r
+\r
+ - before Py_TPFLAGS_VALID_VERSION_TAG can be set on a type,\r
+ it must first be set on all super types.\r
+\r
+ This function clears the Py_TPFLAGS_VALID_VERSION_TAG of a\r
+ type (so it must first clear it on all subclasses). The\r
+ tp_version_tag value is meaningless unless this flag is set.\r
+ We don't assign new version tags eagerly, but only as\r
+ needed.\r
+ */\r
+ PyObject *raw, *ref;\r
+ Py_ssize_t i, n;\r
+\r
+ if (!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))\r
+ return;\r
+\r
+ raw = type->tp_subclasses;\r
+ if (raw != NULL) {\r
+ n = PyList_GET_SIZE(raw);\r
+ for (i = 0; i < n; i++) {\r
+ ref = PyList_GET_ITEM(raw, i);\r
+ ref = PyWeakref_GET_OBJECT(ref);\r
+ if (ref != Py_None) {\r
+ PyType_Modified((PyTypeObject *)ref);\r
+ }\r
+ }\r
+ }\r
+ type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;\r
+}\r
+\r
+static void\r
+type_mro_modified(PyTypeObject *type, PyObject *bases) {\r
+ /*\r
+ Check that all base classes or elements of the mro of type are\r
+ able to be cached. This function is called after the base\r
+ classes or mro of the type are altered.\r
+\r
+ Unset HAVE_VERSION_TAG and VALID_VERSION_TAG if the type\r
+ inherits from an old-style class, either directly or if it\r
+ appears in the MRO of a new-style class. No support either for\r
+ custom MROs that include types that are not officially super\r
+ types.\r
+\r
+ Called from mro_internal, which will subsequently be called on\r
+ each subclass when their mro is recursively updated.\r
+ */\r
+ Py_ssize_t i, n;\r
+ int clear = 0;\r
+\r
+ if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))\r
+ return;\r
+\r
+ n = PyTuple_GET_SIZE(bases);\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *b = PyTuple_GET_ITEM(bases, i);\r
+ PyTypeObject *cls;\r
+\r
+ if (!PyType_Check(b) ) {\r
+ clear = 1;\r
+ break;\r
+ }\r
+\r
+ cls = (PyTypeObject *)b;\r
+\r
+ if (!PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) ||\r
+ !PyType_IsSubtype(type, cls)) {\r
+ clear = 1;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (clear)\r
+ type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG|\r
+ Py_TPFLAGS_VALID_VERSION_TAG);\r
+}\r
+\r
+static int\r
+assign_version_tag(PyTypeObject *type)\r
+{\r
+ /* Ensure that the tp_version_tag is valid and set\r
+ Py_TPFLAGS_VALID_VERSION_TAG. To respect the invariant, this\r
+ must first be done on all super classes. Return 0 if this\r
+ cannot be done, 1 if Py_TPFLAGS_VALID_VERSION_TAG.\r
+ */\r
+ Py_ssize_t i, n;\r
+ PyObject *bases;\r
+\r
+ if (PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))\r
+ return 1;\r
+ if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))\r
+ return 0;\r
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))\r
+ return 0;\r
+\r
+ type->tp_version_tag = next_version_tag++;\r
+ /* for stress-testing: next_version_tag &= 0xFF; */\r
+\r
+ if (type->tp_version_tag == 0) {\r
+ /* wrap-around or just starting Python - clear the whole\r
+ cache by filling names with references to Py_None.\r
+ Values are also set to NULL for added protection, as they\r
+ are borrowed reference */\r
+ for (i = 0; i < (1 << MCACHE_SIZE_EXP); i++) {\r
+ method_cache[i].value = NULL;\r
+ Py_XDECREF(method_cache[i].name);\r
+ method_cache[i].name = Py_None;\r
+ Py_INCREF(Py_None);\r
+ }\r
+ /* mark all version tags as invalid */\r
+ PyType_Modified(&PyBaseObject_Type);\r
+ return 1;\r
+ }\r
+ bases = type->tp_bases;\r
+ n = PyTuple_GET_SIZE(bases);\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *b = PyTuple_GET_ITEM(bases, i);\r
+ assert(PyType_Check(b));\r
+ if (!assign_version_tag((PyTypeObject *)b))\r
+ return 0;\r
+ }\r
+ type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;\r
+ return 1;\r
+}\r
+\r
+\r
+static PyMemberDef type_members[] = {\r
+ {"__basicsize__", T_PYSSIZET, offsetof(PyTypeObject,tp_basicsize),READONLY},\r
+ {"__itemsize__", T_PYSSIZET, offsetof(PyTypeObject, tp_itemsize), READONLY},\r
+ {"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY},\r
+ {"__weakrefoffset__", T_LONG,\r
+ offsetof(PyTypeObject, tp_weaklistoffset), READONLY},\r
+ {"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY},\r
+ {"__dictoffset__", T_LONG,\r
+ offsetof(PyTypeObject, tp_dictoffset), READONLY},\r
+ {"__mro__", T_OBJECT, offsetof(PyTypeObject, tp_mro), READONLY},\r
+ {0}\r
+};\r
+\r
+static PyObject *\r
+type_name(PyTypeObject *type, void *context)\r
+{\r
+ const char *s;\r
+\r
+ if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {\r
+ PyHeapTypeObject* et = (PyHeapTypeObject*)type;\r
+\r
+ Py_INCREF(et->ht_name);\r
+ return et->ht_name;\r
+ }\r
+ else {\r
+ s = strrchr(type->tp_name, '.');\r
+ if (s == NULL)\r
+ s = type->tp_name;\r
+ else\r
+ s++;\r
+ return PyString_FromString(s);\r
+ }\r
+}\r
+\r
+static int\r
+type_set_name(PyTypeObject *type, PyObject *value, void *context)\r
+{\r
+ PyHeapTypeObject* et;\r
+ PyObject *tmp;\r
+\r
+ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can't set %s.__name__", type->tp_name);\r
+ return -1;\r
+ }\r
+ if (!value) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can't delete %s.__name__", type->tp_name);\r
+ return -1;\r
+ }\r
+ if (!PyString_Check(value)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can only assign string to %s.__name__, not '%s'",\r
+ type->tp_name, Py_TYPE(value)->tp_name);\r
+ return -1;\r
+ }\r
+ if (strlen(PyString_AS_STRING(value))\r
+ != (size_t)PyString_GET_SIZE(value)) {\r
+ PyErr_Format(PyExc_ValueError,\r
+ "__name__ must not contain null bytes");\r
+ return -1;\r
+ }\r
+\r
+ et = (PyHeapTypeObject*)type;\r
+\r
+ Py_INCREF(value);\r
+\r
+ /* Wait until et is a sane state before Py_DECREF'ing the old et->ht_name\r
+ value. (Bug #16447.) */\r
+ tmp = et->ht_name;\r
+ et->ht_name = value;\r
+\r
+ type->tp_name = PyString_AS_STRING(value);\r
+ Py_DECREF(tmp);\r
+\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+type_module(PyTypeObject *type, void *context)\r
+{\r
+ PyObject *mod;\r
+ char *s;\r
+\r
+ if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {\r
+ mod = PyDict_GetItemString(type->tp_dict, "__module__");\r
+ if (!mod) {\r
+ PyErr_Format(PyExc_AttributeError, "__module__");\r
+ return 0;\r
+ }\r
+ Py_XINCREF(mod);\r
+ return mod;\r
+ }\r
+ else {\r
+ s = strrchr(type->tp_name, '.');\r
+ if (s != NULL)\r
+ return PyString_FromStringAndSize(\r
+ type->tp_name, (Py_ssize_t)(s - type->tp_name));\r
+ return PyString_FromString("__builtin__");\r
+ }\r
+}\r
+\r
+static int\r
+type_set_module(PyTypeObject *type, PyObject *value, void *context)\r
+{\r
+ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can't set %s.__module__", type->tp_name);\r
+ return -1;\r
+ }\r
+ if (!value) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can't delete %s.__module__", type->tp_name);\r
+ return -1;\r
+ }\r
+\r
+ PyType_Modified(type);\r
+\r
+ return PyDict_SetItemString(type->tp_dict, "__module__", value);\r
+}\r
+\r
+static PyObject *\r
+type_abstractmethods(PyTypeObject *type, void *context)\r
+{\r
+ PyObject *mod = NULL;\r
+ /* type itself has an __abstractmethods__ descriptor (this). Don't return\r
+ that. */\r
+ if (type != &PyType_Type)\r
+ mod = PyDict_GetItemString(type->tp_dict, "__abstractmethods__");\r
+ if (!mod) {\r
+ PyErr_SetString(PyExc_AttributeError, "__abstractmethods__");\r
+ return NULL;\r
+ }\r
+ Py_XINCREF(mod);\r
+ return mod;\r
+}\r
+\r
+static int\r
+type_set_abstractmethods(PyTypeObject *type, PyObject *value, void *context)\r
+{\r
+ /* __abstractmethods__ should only be set once on a type, in\r
+ abc.ABCMeta.__new__, so this function doesn't do anything\r
+ special to update subclasses.\r
+ */\r
+ int abstract, res;\r
+ if (value != NULL) {\r
+ abstract = PyObject_IsTrue(value);\r
+ if (abstract < 0)\r
+ return -1;\r
+ res = PyDict_SetItemString(type->tp_dict, "__abstractmethods__", value);\r
+ }\r
+ else {\r
+ abstract = 0;\r
+ res = PyDict_DelItemString(type->tp_dict, "__abstractmethods__");\r
+ if (res && PyErr_ExceptionMatches(PyExc_KeyError)) {\r
+ PyErr_SetString(PyExc_AttributeError, "__abstractmethods__");\r
+ return -1;\r
+ }\r
+ }\r
+ if (res == 0) {\r
+ PyType_Modified(type);\r
+ if (abstract)\r
+ type->tp_flags |= Py_TPFLAGS_IS_ABSTRACT;\r
+ else\r
+ type->tp_flags &= ~Py_TPFLAGS_IS_ABSTRACT;\r
+ }\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+type_get_bases(PyTypeObject *type, void *context)\r
+{\r
+ Py_INCREF(type->tp_bases);\r
+ return type->tp_bases;\r
+}\r
+\r
+static PyTypeObject *best_base(PyObject *);\r
+static int mro_internal(PyTypeObject *);\r
+static int compatible_for_assignment(PyTypeObject *, PyTypeObject *, char *);\r
+static int add_subclass(PyTypeObject*, PyTypeObject*);\r
+static void remove_subclass(PyTypeObject *, PyTypeObject *);\r
+static void update_all_slots(PyTypeObject *);\r
+\r
+typedef int (*update_callback)(PyTypeObject *, void *);\r
+static int update_subclasses(PyTypeObject *type, PyObject *name,\r
+ update_callback callback, void *data);\r
+static int recurse_down_subclasses(PyTypeObject *type, PyObject *name,\r
+ update_callback callback, void *data);\r
+\r
+static int\r
+mro_subclasses(PyTypeObject *type, PyObject* temp)\r
+{\r
+ PyTypeObject *subclass;\r
+ PyObject *ref, *subclasses, *old_mro;\r
+ Py_ssize_t i, n;\r
+\r
+ subclasses = type->tp_subclasses;\r
+ if (subclasses == NULL)\r
+ return 0;\r
+ assert(PyList_Check(subclasses));\r
+ n = PyList_GET_SIZE(subclasses);\r
+ for (i = 0; i < n; i++) {\r
+ ref = PyList_GET_ITEM(subclasses, i);\r
+ assert(PyWeakref_CheckRef(ref));\r
+ subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref);\r
+ assert(subclass != NULL);\r
+ if ((PyObject *)subclass == Py_None)\r
+ continue;\r
+ assert(PyType_Check(subclass));\r
+ old_mro = subclass->tp_mro;\r
+ if (mro_internal(subclass) < 0) {\r
+ subclass->tp_mro = old_mro;\r
+ return -1;\r
+ }\r
+ else {\r
+ PyObject* tuple;\r
+ tuple = PyTuple_Pack(2, subclass, old_mro);\r
+ Py_DECREF(old_mro);\r
+ if (!tuple)\r
+ return -1;\r
+ if (PyList_Append(temp, tuple) < 0)\r
+ return -1;\r
+ Py_DECREF(tuple);\r
+ }\r
+ if (mro_subclasses(subclass, temp) < 0)\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+type_set_bases(PyTypeObject *type, PyObject *value, void *context)\r
+{\r
+ Py_ssize_t i;\r
+ int r = 0;\r
+ PyObject *ob, *temp;\r
+ PyTypeObject *new_base, *old_base;\r
+ PyObject *old_bases, *old_mro;\r
+\r
+ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can't set %s.__bases__", type->tp_name);\r
+ return -1;\r
+ }\r
+ if (!value) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can't delete %s.__bases__", type->tp_name);\r
+ return -1;\r
+ }\r
+ if (!PyTuple_Check(value)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can only assign tuple to %s.__bases__, not %s",\r
+ type->tp_name, Py_TYPE(value)->tp_name);\r
+ return -1;\r
+ }\r
+ if (PyTuple_GET_SIZE(value) == 0) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can only assign non-empty tuple to %s.__bases__, not ()",\r
+ type->tp_name);\r
+ return -1;\r
+ }\r
+ for (i = 0; i < PyTuple_GET_SIZE(value); i++) {\r
+ ob = PyTuple_GET_ITEM(value, i);\r
+ if (!PyClass_Check(ob) && !PyType_Check(ob)) {\r
+ PyErr_Format(\r
+ PyExc_TypeError,\r
+ "%s.__bases__ must be tuple of old- or new-style classes, not '%s'",\r
+ type->tp_name, Py_TYPE(ob)->tp_name);\r
+ return -1;\r
+ }\r
+ if (PyType_Check(ob)) {\r
+ if (PyType_IsSubtype((PyTypeObject*)ob, type)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "a __bases__ item causes an inheritance cycle");\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+\r
+ new_base = best_base(value);\r
+\r
+ if (!new_base) {\r
+ return -1;\r
+ }\r
+\r
+ if (!compatible_for_assignment(type->tp_base, new_base, "__bases__"))\r
+ return -1;\r
+\r
+ Py_INCREF(new_base);\r
+ Py_INCREF(value);\r
+\r
+ old_bases = type->tp_bases;\r
+ old_base = type->tp_base;\r
+ old_mro = type->tp_mro;\r
+\r
+ type->tp_bases = value;\r
+ type->tp_base = new_base;\r
+\r
+ if (mro_internal(type) < 0) {\r
+ goto bail;\r
+ }\r
+\r
+ temp = PyList_New(0);\r
+ if (!temp)\r
+ goto bail;\r
+\r
+ r = mro_subclasses(type, temp);\r
+\r
+ if (r < 0) {\r
+ for (i = 0; i < PyList_Size(temp); i++) {\r
+ PyTypeObject* cls;\r
+ PyObject* mro;\r
+ PyArg_UnpackTuple(PyList_GET_ITEM(temp, i),\r
+ "", 2, 2, &cls, &mro);\r
+ Py_INCREF(mro);\r
+ ob = cls->tp_mro;\r
+ cls->tp_mro = mro;\r
+ Py_DECREF(ob);\r
+ }\r
+ Py_DECREF(temp);\r
+ goto bail;\r
+ }\r
+\r
+ Py_DECREF(temp);\r
+\r
+ /* any base that was in __bases__ but now isn't, we\r
+ need to remove |type| from its tp_subclasses.\r
+ conversely, any class now in __bases__ that wasn't\r
+ needs to have |type| added to its subclasses. */\r
+\r
+ /* for now, sod that: just remove from all old_bases,\r
+ add to all new_bases */\r
+\r
+ for (i = PyTuple_GET_SIZE(old_bases) - 1; i >= 0; i--) {\r
+ ob = PyTuple_GET_ITEM(old_bases, i);\r
+ if (PyType_Check(ob)) {\r
+ remove_subclass(\r
+ (PyTypeObject*)ob, type);\r
+ }\r
+ }\r
+\r
+ for (i = PyTuple_GET_SIZE(value) - 1; i >= 0; i--) {\r
+ ob = PyTuple_GET_ITEM(value, i);\r
+ if (PyType_Check(ob)) {\r
+ if (add_subclass((PyTypeObject*)ob, type) < 0)\r
+ r = -1;\r
+ }\r
+ }\r
+\r
+ update_all_slots(type);\r
+\r
+ Py_DECREF(old_bases);\r
+ Py_DECREF(old_base);\r
+ Py_DECREF(old_mro);\r
+\r
+ return r;\r
+\r
+ bail:\r
+ Py_DECREF(type->tp_bases);\r
+ Py_DECREF(type->tp_base);\r
+ if (type->tp_mro != old_mro) {\r
+ Py_DECREF(type->tp_mro);\r
+ }\r
+\r
+ type->tp_bases = old_bases;\r
+ type->tp_base = old_base;\r
+ type->tp_mro = old_mro;\r
+\r
+ return -1;\r
+}\r
+\r
+static PyObject *\r
+type_dict(PyTypeObject *type, void *context)\r
+{\r
+ if (type->tp_dict == NULL) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+ return PyDictProxy_New(type->tp_dict);\r
+}\r
+\r
+static PyObject *\r
+type_get_doc(PyTypeObject *type, void *context)\r
+{\r
+ PyObject *result;\r
+ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) && type->tp_doc != NULL)\r
+ return PyString_FromString(type->tp_doc);\r
+ result = PyDict_GetItemString(type->tp_dict, "__doc__");\r
+ if (result == NULL) {\r
+ result = Py_None;\r
+ Py_INCREF(result);\r
+ }\r
+ else if (Py_TYPE(result)->tp_descr_get) {\r
+ result = Py_TYPE(result)->tp_descr_get(result, NULL,\r
+ (PyObject *)type);\r
+ }\r
+ else {\r
+ Py_INCREF(result);\r
+ }\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+type___instancecheck__(PyObject *type, PyObject *inst)\r
+{\r
+ switch (_PyObject_RealIsInstance(inst, type)) {\r
+ case -1:\r
+ return NULL;\r
+ case 0:\r
+ Py_RETURN_FALSE;\r
+ default:\r
+ Py_RETURN_TRUE;\r
+ }\r
+}\r
+\r
+\r
+static PyObject *\r
+type___subclasscheck__(PyObject *type, PyObject *inst)\r
+{\r
+ switch (_PyObject_RealIsSubclass(inst, type)) {\r
+ case -1:\r
+ return NULL;\r
+ case 0:\r
+ Py_RETURN_FALSE;\r
+ default:\r
+ Py_RETURN_TRUE;\r
+ }\r
+}\r
+\r
+\r
+static PyGetSetDef type_getsets[] = {\r
+ {"__name__", (getter)type_name, (setter)type_set_name, NULL},\r
+ {"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL},\r
+ {"__module__", (getter)type_module, (setter)type_set_module, NULL},\r
+ {"__abstractmethods__", (getter)type_abstractmethods,\r
+ (setter)type_set_abstractmethods, NULL},\r
+ {"__dict__", (getter)type_dict, NULL, NULL},\r
+ {"__doc__", (getter)type_get_doc, NULL, NULL},\r
+ {0}\r
+};\r
+\r
+\r
+static PyObject*\r
+type_richcompare(PyObject *v, PyObject *w, int op)\r
+{\r
+ PyObject *result;\r
+ Py_uintptr_t vv, ww;\r
+ int c;\r
+\r
+ /* Make sure both arguments are types. */\r
+ if (!PyType_Check(v) || !PyType_Check(w) ||\r
+ /* If there is a __cmp__ method defined, let it be called instead\r
+ of our dumb function designed merely to warn. See bug\r
+ #7491. */\r
+ Py_TYPE(v)->tp_compare || Py_TYPE(w)->tp_compare) {\r
+ result = Py_NotImplemented;\r
+ goto out;\r
+ }\r
+\r
+ /* Py3K warning if comparison isn't == or != */\r
+ if (Py_Py3kWarningFlag && op != Py_EQ && op != Py_NE &&\r
+ PyErr_WarnEx(PyExc_DeprecationWarning,\r
+ "type inequality comparisons not supported "\r
+ "in 3.x", 1) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ /* Compare addresses */\r
+ vv = (Py_uintptr_t)v;\r
+ ww = (Py_uintptr_t)w;\r
+ switch (op) {\r
+ case Py_LT: c = vv < ww; break;\r
+ case Py_LE: c = vv <= ww; break;\r
+ case Py_EQ: c = vv == ww; break;\r
+ case Py_NE: c = vv != ww; break;\r
+ case Py_GT: c = vv > ww; break;\r
+ case Py_GE: c = vv >= ww; break;\r
+ default:\r
+ result = Py_NotImplemented;\r
+ goto out;\r
+ }\r
+ result = c ? Py_True : Py_False;\r
+\r
+ /* incref and return */\r
+ out:\r
+ Py_INCREF(result);\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+type_repr(PyTypeObject *type)\r
+{\r
+ PyObject *mod, *name, *rtn;\r
+ char *kind;\r
+\r
+ mod = type_module(type, NULL);\r
+ if (mod == NULL)\r
+ PyErr_Clear();\r
+ else if (!PyString_Check(mod)) {\r
+ Py_DECREF(mod);\r
+ mod = NULL;\r
+ }\r
+ name = type_name(type, NULL);\r
+ if (name == NULL) {\r
+ Py_XDECREF(mod);\r
+ return NULL;\r
+ }\r
+\r
+ if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)\r
+ kind = "class";\r
+ else\r
+ kind = "type";\r
+\r
+ if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__")) {\r
+ rtn = PyString_FromFormat("<%s '%s.%s'>",\r
+ kind,\r
+ PyString_AS_STRING(mod),\r
+ PyString_AS_STRING(name));\r
+ }\r
+ else\r
+ rtn = PyString_FromFormat("<%s '%s'>", kind, type->tp_name);\r
+\r
+ Py_XDECREF(mod);\r
+ Py_DECREF(name);\r
+ return rtn;\r
+}\r
+\r
+static PyObject *\r
+type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *obj;\r
+\r
+ if (type->tp_new == NULL) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "cannot create '%.100s' instances",\r
+ type->tp_name);\r
+ return NULL;\r
+ }\r
+\r
+ obj = type->tp_new(type, args, kwds);\r
+ if (obj != NULL) {\r
+ /* Ugly exception: when the call was type(something),\r
+ don't call tp_init on the result. */\r
+ if (type == &PyType_Type &&\r
+ PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&\r
+ (kwds == NULL ||\r
+ (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))\r
+ return obj;\r
+ /* If the returned object is not an instance of type,\r
+ it won't be initialized. */\r
+ if (!PyType_IsSubtype(obj->ob_type, type))\r
+ return obj;\r
+ type = obj->ob_type;\r
+ if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS) &&\r
+ type->tp_init != NULL &&\r
+ type->tp_init(obj, args, kwds) < 0) {\r
+ Py_DECREF(obj);\r
+ obj = NULL;\r
+ }\r
+ }\r
+ return obj;\r
+}\r
+\r
+PyObject *\r
+PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)\r
+{\r
+ PyObject *obj;\r
+ const size_t size = _PyObject_VAR_SIZE(type, nitems+1);\r
+ /* note that we need to add one, for the sentinel */\r
+\r
+ if (PyType_IS_GC(type))\r
+ obj = _PyObject_GC_Malloc(size);\r
+ else\r
+ obj = (PyObject *)PyObject_MALLOC(size);\r
+\r
+ if (obj == NULL)\r
+ return PyErr_NoMemory();\r
+\r
+ memset(obj, '\0', size);\r
+\r
+ if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)\r
+ Py_INCREF(type);\r
+\r
+ if (type->tp_itemsize == 0)\r
+ PyObject_INIT(obj, type);\r
+ else\r
+ (void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems);\r
+\r
+ if (PyType_IS_GC(type))\r
+ _PyObject_GC_TRACK(obj);\r
+ return obj;\r
+}\r
+\r
+PyObject *\r
+PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ return type->tp_alloc(type, 0);\r
+}\r
+\r
+/* Helpers for subtyping */\r
+\r
+static int\r
+traverse_slots(PyTypeObject *type, PyObject *self, visitproc visit, void *arg)\r
+{\r
+ Py_ssize_t i, n;\r
+ PyMemberDef *mp;\r
+\r
+ n = Py_SIZE(type);\r
+ mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type);\r
+ for (i = 0; i < n; i++, mp++) {\r
+ if (mp->type == T_OBJECT_EX) {\r
+ char *addr = (char *)self + mp->offset;\r
+ PyObject *obj = *(PyObject **)addr;\r
+ if (obj != NULL) {\r
+ int err = visit(obj, arg);\r
+ if (err)\r
+ return err;\r
+ }\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+subtype_traverse(PyObject *self, visitproc visit, void *arg)\r
+{\r
+ PyTypeObject *type, *base;\r
+ traverseproc basetraverse;\r
+\r
+ /* Find the nearest base with a different tp_traverse,\r
+ and traverse slots while we're at it */\r
+ type = Py_TYPE(self);\r
+ base = type;\r
+ while ((basetraverse = base->tp_traverse) == subtype_traverse) {\r
+ if (Py_SIZE(base)) {\r
+ int err = traverse_slots(base, self, visit, arg);\r
+ if (err)\r
+ return err;\r
+ }\r
+ base = base->tp_base;\r
+ assert(base);\r
+ }\r
+\r
+ if (type->tp_dictoffset != base->tp_dictoffset) {\r
+ PyObject **dictptr = _PyObject_GetDictPtr(self);\r
+ if (dictptr && *dictptr)\r
+ Py_VISIT(*dictptr);\r
+ }\r
+\r
+ if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)\r
+ /* For a heaptype, the instances count as references\r
+ to the type. Traverse the type so the collector\r
+ can find cycles involving this link. */\r
+ Py_VISIT(type);\r
+\r
+ if (basetraverse)\r
+ return basetraverse(self, visit, arg);\r
+ return 0;\r
+}\r
+\r
+static void\r
+clear_slots(PyTypeObject *type, PyObject *self)\r
+{\r
+ Py_ssize_t i, n;\r
+ PyMemberDef *mp;\r
+\r
+ n = Py_SIZE(type);\r
+ mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type);\r
+ for (i = 0; i < n; i++, mp++) {\r
+ if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) {\r
+ char *addr = (char *)self + mp->offset;\r
+ PyObject *obj = *(PyObject **)addr;\r
+ if (obj != NULL) {\r
+ *(PyObject **)addr = NULL;\r
+ Py_DECREF(obj);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+static int\r
+subtype_clear(PyObject *self)\r
+{\r
+ PyTypeObject *type, *base;\r
+ inquiry baseclear;\r
+\r
+ /* Find the nearest base with a different tp_clear\r
+ and clear slots while we're at it */\r
+ type = Py_TYPE(self);\r
+ base = type;\r
+ while ((baseclear = base->tp_clear) == subtype_clear) {\r
+ if (Py_SIZE(base))\r
+ clear_slots(base, self);\r
+ base = base->tp_base;\r
+ assert(base);\r
+ }\r
+\r
+ /* Clear the instance dict (if any), to break cycles involving only\r
+ __dict__ slots (as in the case 'self.__dict__ is self'). */\r
+ if (type->tp_dictoffset != base->tp_dictoffset) {\r
+ PyObject **dictptr = _PyObject_GetDictPtr(self);\r
+ if (dictptr && *dictptr)\r
+ Py_CLEAR(*dictptr);\r
+ }\r
+\r
+ if (baseclear)\r
+ return baseclear(self);\r
+ return 0;\r
+}\r
+\r
+static void\r
+subtype_dealloc(PyObject *self)\r
+{\r
+ PyTypeObject *type, *base;\r
+ destructor basedealloc;\r
+ PyThreadState *tstate = PyThreadState_GET();\r
+\r
+ /* Extract the type; we expect it to be a heap type */\r
+ type = Py_TYPE(self);\r
+ assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);\r
+\r
+ /* Test whether the type has GC exactly once */\r
+\r
+ if (!PyType_IS_GC(type)) {\r
+ /* It's really rare to find a dynamic type that doesn't have\r
+ GC; it can only happen when deriving from 'object' and not\r
+ adding any slots or instance variables. This allows\r
+ certain simplifications: there's no need to call\r
+ clear_slots(), or DECREF the dict, or clear weakrefs. */\r
+\r
+ /* Maybe call finalizer; exit early if resurrected */\r
+ if (type->tp_del) {\r
+ type->tp_del(self);\r
+ if (self->ob_refcnt > 0)\r
+ return;\r
+ }\r
+\r
+ /* Find the nearest base with a different tp_dealloc */\r
+ base = type;\r
+ while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {\r
+ assert(Py_SIZE(base) == 0);\r
+ base = base->tp_base;\r
+ assert(base);\r
+ }\r
+\r
+ /* Extract the type again; tp_del may have changed it */\r
+ type = Py_TYPE(self);\r
+\r
+ /* Call the base tp_dealloc() */\r
+ assert(basedealloc);\r
+ basedealloc(self);\r
+\r
+ /* Can't reference self beyond this point */\r
+ Py_DECREF(type);\r
+\r
+ /* Done */\r
+ return;\r
+ }\r
+\r
+ /* We get here only if the type has GC */\r
+\r
+ /* UnTrack and re-Track around the trashcan macro, alas */\r
+ /* See explanation at end of function for full disclosure */\r
+ PyObject_GC_UnTrack(self);\r
+ ++_PyTrash_delete_nesting;\r
+ ++ tstate->trash_delete_nesting;\r
+ Py_TRASHCAN_SAFE_BEGIN(self);\r
+ --_PyTrash_delete_nesting;\r
+ -- tstate->trash_delete_nesting;\r
+ /* DO NOT restore GC tracking at this point. weakref callbacks\r
+ * (if any, and whether directly here or indirectly in something we\r
+ * call) may trigger GC, and if self is tracked at that point, it\r
+ * will look like trash to GC and GC will try to delete self again.\r
+ */\r
+\r
+ /* Find the nearest base with a different tp_dealloc */\r
+ base = type;\r
+ while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {\r
+ base = base->tp_base;\r
+ assert(base);\r
+ }\r
+\r
+ /* If we added a weaklist, we clear it. Do this *before* calling\r
+ the finalizer (__del__), clearing slots, or clearing the instance\r
+ dict. */\r
+\r
+ if (type->tp_weaklistoffset && !base->tp_weaklistoffset)\r
+ PyObject_ClearWeakRefs(self);\r
+\r
+ /* Maybe call finalizer; exit early if resurrected */\r
+ if (type->tp_del) {\r
+ _PyObject_GC_TRACK(self);\r
+ type->tp_del(self);\r
+ if (self->ob_refcnt > 0)\r
+ goto endlabel; /* resurrected */\r
+ else\r
+ _PyObject_GC_UNTRACK(self);\r
+ /* New weakrefs could be created during the finalizer call.\r
+ If this occurs, clear them out without calling their\r
+ finalizers since they might rely on part of the object\r
+ being finalized that has already been destroyed. */\r
+ if (type->tp_weaklistoffset && !base->tp_weaklistoffset) {\r
+ /* Modeled after GET_WEAKREFS_LISTPTR() */\r
+ PyWeakReference **list = (PyWeakReference **) \\r
+ PyObject_GET_WEAKREFS_LISTPTR(self);\r
+ while (*list)\r
+ _PyWeakref_ClearRef(*list);\r
+ }\r
+ }\r
+\r
+ /* Clear slots up to the nearest base with a different tp_dealloc */\r
+ base = type;\r
+ while (base->tp_dealloc == subtype_dealloc) {\r
+ if (Py_SIZE(base))\r
+ clear_slots(base, self);\r
+ base = base->tp_base;\r
+ assert(base);\r
+ }\r
+\r
+ /* If we added a dict, DECREF it */\r
+ if (type->tp_dictoffset && !base->tp_dictoffset) {\r
+ PyObject **dictptr = _PyObject_GetDictPtr(self);\r
+ if (dictptr != NULL) {\r
+ PyObject *dict = *dictptr;\r
+ if (dict != NULL) {\r
+ Py_DECREF(dict);\r
+ *dictptr = NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Extract the type again; tp_del may have changed it */\r
+ type = Py_TYPE(self);\r
+\r
+ /* Call the base tp_dealloc(); first retrack self if\r
+ * basedealloc knows about gc.\r
+ */\r
+ if (PyType_IS_GC(base))\r
+ _PyObject_GC_TRACK(self);\r
+ assert(basedealloc);\r
+ basedealloc(self);\r
+\r
+ /* Can't reference self beyond this point */\r
+ Py_DECREF(type);\r
+\r
+ endlabel:\r
+ ++_PyTrash_delete_nesting;\r
+ ++ tstate->trash_delete_nesting;\r
+ Py_TRASHCAN_SAFE_END(self);\r
+ --_PyTrash_delete_nesting;\r
+ -- tstate->trash_delete_nesting;\r
+\r
+ /* Explanation of the weirdness around the trashcan macros:\r
+\r
+ Q. What do the trashcan macros do?\r
+\r
+ A. Read the comment titled "Trashcan mechanism" in object.h.\r
+ For one, this explains why there must be a call to GC-untrack\r
+ before the trashcan begin macro. Without understanding the\r
+ trashcan code, the answers to the following questions don't make\r
+ sense.\r
+\r
+ Q. Why do we GC-untrack before the trashcan and then immediately\r
+ GC-track again afterward?\r
+\r
+ A. In the case that the base class is GC-aware, the base class\r
+ probably GC-untracks the object. If it does that using the\r
+ UNTRACK macro, this will crash when the object is already\r
+ untracked. Because we don't know what the base class does, the\r
+ only safe thing is to make sure the object is tracked when we\r
+ call the base class dealloc. But... The trashcan begin macro\r
+ requires that the object is *untracked* before it is called. So\r
+ the dance becomes:\r
+\r
+ GC untrack\r
+ trashcan begin\r
+ GC track\r
+\r
+ Q. Why did the last question say "immediately GC-track again"?\r
+ It's nowhere near immediately.\r
+\r
+ A. Because the code *used* to re-track immediately. Bad Idea.\r
+ self has a refcount of 0, and if gc ever gets its hands on it\r
+ (which can happen if any weakref callback gets invoked), it\r
+ looks like trash to gc too, and gc also tries to delete self\r
+ then. But we're already deleting self. Double deallocation is\r
+ a subtle disaster.\r
+\r
+ Q. Why the bizarre (net-zero) manipulation of\r
+ _PyTrash_delete_nesting around the trashcan macros?\r
+\r
+ A. Some base classes (e.g. list) also use the trashcan mechanism.\r
+ The following scenario used to be possible:\r
+\r
+ - suppose the trashcan level is one below the trashcan limit\r
+\r
+ - subtype_dealloc() is called\r
+\r
+ - the trashcan limit is not yet reached, so the trashcan level\r
+ is incremented and the code between trashcan begin and end is\r
+ executed\r
+\r
+ - this destroys much of the object's contents, including its\r
+ slots and __dict__\r
+\r
+ - basedealloc() is called; this is really list_dealloc(), or\r
+ some other type which also uses the trashcan macros\r
+\r
+ - the trashcan limit is now reached, so the object is put on the\r
+ trashcan's to-be-deleted-later list\r
+\r
+ - basedealloc() returns\r
+\r
+ - subtype_dealloc() decrefs the object's type\r
+\r
+ - subtype_dealloc() returns\r
+\r
+ - later, the trashcan code starts deleting the objects from its\r
+ to-be-deleted-later list\r
+\r
+ - subtype_dealloc() is called *AGAIN* for the same object\r
+\r
+ - at the very least (if the destroyed slots and __dict__ don't\r
+ cause problems) the object's type gets decref'ed a second\r
+ time, which is *BAD*!!!\r
+\r
+ The remedy is to make sure that if the code between trashcan\r
+ begin and end in subtype_dealloc() is called, the code between\r
+ trashcan begin and end in basedealloc() will also be called.\r
+ This is done by decrementing the level after passing into the\r
+ trashcan block, and incrementing it just before leaving the\r
+ block.\r
+\r
+ But now it's possible that a chain of objects consisting solely\r
+ of objects whose deallocator is subtype_dealloc() will defeat\r
+ the trashcan mechanism completely: the decremented level means\r
+ that the effective level never reaches the limit. Therefore, we\r
+ *increment* the level *before* entering the trashcan block, and\r
+ matchingly decrement it after leaving. This means the trashcan\r
+ code will trigger a little early, but that's no big deal.\r
+\r
+ Q. Are there any live examples of code in need of all this\r
+ complexity?\r
+\r
+ A. Yes. See SF bug 668433 for code that crashed (when Python was\r
+ compiled in debug mode) before the trashcan level manipulations\r
+ were added. For more discussion, see SF patches 581742, 575073\r
+ and bug 574207.\r
+ */\r
+}\r
+\r
+static PyTypeObject *solid_base(PyTypeObject *type);\r
+\r
+/* type test with subclassing support */\r
+\r
+int\r
+PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)\r
+{\r
+ PyObject *mro;\r
+\r
+ if (!(a->tp_flags & Py_TPFLAGS_HAVE_CLASS))\r
+ return b == a || b == &PyBaseObject_Type;\r
+\r
+ mro = a->tp_mro;\r
+ if (mro != NULL) {\r
+ /* Deal with multiple inheritance without recursion\r
+ by walking the MRO tuple */\r
+ Py_ssize_t i, n;\r
+ assert(PyTuple_Check(mro));\r
+ n = PyTuple_GET_SIZE(mro);\r
+ for (i = 0; i < n; i++) {\r
+ if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b)\r
+ return 1;\r
+ }\r
+ return 0;\r
+ }\r
+ else {\r
+ /* a is not completely initilized yet; follow tp_base */\r
+ do {\r
+ if (a == b)\r
+ return 1;\r
+ a = a->tp_base;\r
+ } while (a != NULL);\r
+ return b == &PyBaseObject_Type;\r
+ }\r
+}\r
+\r
+/* Internal routines to do a method lookup in the type\r
+ without looking in the instance dictionary\r
+ (so we can't use PyObject_GetAttr) but still binding\r
+ it to the instance. The arguments are the object,\r
+ the method name as a C string, and the address of a\r
+ static variable used to cache the interned Python string.\r
+\r
+ Two variants:\r
+\r
+ - lookup_maybe() returns NULL without raising an exception\r
+ when the _PyType_Lookup() call fails;\r
+\r
+ - lookup_method() always raises an exception upon errors.\r
+\r
+ - _PyObject_LookupSpecial() exported for the benefit of other places.\r
+*/\r
+\r
+static PyObject *\r
+lookup_maybe(PyObject *self, char *attrstr, PyObject **attrobj)\r
+{\r
+ PyObject *res;\r
+\r
+ if (*attrobj == NULL) {\r
+ *attrobj = PyString_InternFromString(attrstr);\r
+ if (*attrobj == NULL)\r
+ return NULL;\r
+ }\r
+ res = _PyType_Lookup(Py_TYPE(self), *attrobj);\r
+ if (res != NULL) {\r
+ descrgetfunc f;\r
+ if ((f = Py_TYPE(res)->tp_descr_get) == NULL)\r
+ Py_INCREF(res);\r
+ else\r
+ res = f(res, self, (PyObject *)(Py_TYPE(self)));\r
+ }\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+lookup_method(PyObject *self, char *attrstr, PyObject **attrobj)\r
+{\r
+ PyObject *res = lookup_maybe(self, attrstr, attrobj);\r
+ if (res == NULL && !PyErr_Occurred())\r
+ PyErr_SetObject(PyExc_AttributeError, *attrobj);\r
+ return res;\r
+}\r
+\r
+PyObject *\r
+_PyObject_LookupSpecial(PyObject *self, char *attrstr, PyObject **attrobj)\r
+{\r
+ assert(!PyInstance_Check(self));\r
+ return lookup_maybe(self, attrstr, attrobj);\r
+}\r
+\r
+/* A variation of PyObject_CallMethod that uses lookup_method()\r
+ instead of PyObject_GetAttrString(). This uses the same convention\r
+ as lookup_method to cache the interned name string object. */\r
+\r
+static PyObject *\r
+call_method(PyObject *o, char *name, PyObject **nameobj, char *format, ...)\r
+{\r
+ va_list va;\r
+ PyObject *args, *func = 0, *retval;\r
+ va_start(va, format);\r
+\r
+ func = lookup_maybe(o, name, nameobj);\r
+ if (func == NULL) {\r
+ va_end(va);\r
+ if (!PyErr_Occurred())\r
+ PyErr_SetObject(PyExc_AttributeError, *nameobj);\r
+ return NULL;\r
+ }\r
+\r
+ if (format && *format)\r
+ args = Py_VaBuildValue(format, va);\r
+ else\r
+ args = PyTuple_New(0);\r
+\r
+ va_end(va);\r
+\r
+ if (args == NULL)\r
+ return NULL;\r
+\r
+ assert(PyTuple_Check(args));\r
+ retval = PyObject_Call(func, args, NULL);\r
+\r
+ Py_DECREF(args);\r
+ Py_DECREF(func);\r
+\r
+ return retval;\r
+}\r
+\r
+/* Clone of call_method() that returns NotImplemented when the lookup fails. */\r
+\r
+static PyObject *\r
+call_maybe(PyObject *o, char *name, PyObject **nameobj, char *format, ...)\r
+{\r
+ va_list va;\r
+ PyObject *args, *func = 0, *retval;\r
+ va_start(va, format);\r
+\r
+ func = lookup_maybe(o, name, nameobj);\r
+ if (func == NULL) {\r
+ va_end(va);\r
+ if (!PyErr_Occurred()) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ return NULL;\r
+ }\r
+\r
+ if (format && *format)\r
+ args = Py_VaBuildValue(format, va);\r
+ else\r
+ args = PyTuple_New(0);\r
+\r
+ va_end(va);\r
+\r
+ if (args == NULL)\r
+ return NULL;\r
+\r
+ assert(PyTuple_Check(args));\r
+ retval = PyObject_Call(func, args, NULL);\r
+\r
+ Py_DECREF(args);\r
+ Py_DECREF(func);\r
+\r
+ return retval;\r
+}\r
+\r
+static int\r
+fill_classic_mro(PyObject *mro, PyObject *cls)\r
+{\r
+ PyObject *bases, *base;\r
+ Py_ssize_t i, n;\r
+\r
+ assert(PyList_Check(mro));\r
+ assert(PyClass_Check(cls));\r
+ i = PySequence_Contains(mro, cls);\r
+ if (i < 0)\r
+ return -1;\r
+ if (!i) {\r
+ if (PyList_Append(mro, cls) < 0)\r
+ return -1;\r
+ }\r
+ bases = ((PyClassObject *)cls)->cl_bases;\r
+ assert(bases && PyTuple_Check(bases));\r
+ n = PyTuple_GET_SIZE(bases);\r
+ for (i = 0; i < n; i++) {\r
+ base = PyTuple_GET_ITEM(bases, i);\r
+ if (fill_classic_mro(mro, base) < 0)\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+classic_mro(PyObject *cls)\r
+{\r
+ PyObject *mro;\r
+\r
+ assert(PyClass_Check(cls));\r
+ mro = PyList_New(0);\r
+ if (mro != NULL) {\r
+ if (fill_classic_mro(mro, cls) == 0)\r
+ return mro;\r
+ Py_DECREF(mro);\r
+ }\r
+ return NULL;\r
+}\r
+\r
+/*\r
+ Method resolution order algorithm C3 described in\r
+ "A Monotonic Superclass Linearization for Dylan",\r
+ by Kim Barrett, Bob Cassel, Paul Haahr,\r
+ David A. Moon, Keith Playford, and P. Tucker Withington.\r
+ (OOPSLA 1996)\r
+\r
+ Some notes about the rules implied by C3:\r
+\r
+ No duplicate bases.\r
+ It isn't legal to repeat a class in a list of base classes.\r
+\r
+ The next three properties are the 3 constraints in "C3".\r
+\r
+ Local precendece order.\r
+ If A precedes B in C's MRO, then A will precede B in the MRO of all\r
+ subclasses of C.\r
+\r
+ Monotonicity.\r
+ The MRO of a class must be an extension without reordering of the\r
+ MRO of each of its superclasses.\r
+\r
+ Extended Precedence Graph (EPG).\r
+ Linearization is consistent if there is a path in the EPG from\r
+ each class to all its successors in the linearization. See\r
+ the paper for definition of EPG.\r
+ */\r
+\r
+static int\r
+tail_contains(PyObject *list, int whence, PyObject *o) {\r
+ Py_ssize_t j, size;\r
+ size = PyList_GET_SIZE(list);\r
+\r
+ for (j = whence+1; j < size; j++) {\r
+ if (PyList_GET_ITEM(list, j) == o)\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+class_name(PyObject *cls)\r
+{\r
+ PyObject *name = PyObject_GetAttrString(cls, "__name__");\r
+ if (name == NULL) {\r
+ PyErr_Clear();\r
+ Py_XDECREF(name);\r
+ name = PyObject_Repr(cls);\r
+ }\r
+ if (name == NULL)\r
+ return NULL;\r
+ if (!PyString_Check(name)) {\r
+ Py_DECREF(name);\r
+ return NULL;\r
+ }\r
+ return name;\r
+}\r
+\r
+static int\r
+check_duplicates(PyObject *list)\r
+{\r
+ Py_ssize_t i, j, n;\r
+ /* Let's use a quadratic time algorithm,\r
+ assuming that the bases lists is short.\r
+ */\r
+ n = PyList_GET_SIZE(list);\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *o = PyList_GET_ITEM(list, i);\r
+ for (j = i + 1; j < n; j++) {\r
+ if (PyList_GET_ITEM(list, j) == o) {\r
+ o = class_name(o);\r
+ PyErr_Format(PyExc_TypeError,\r
+ "duplicate base class %s",\r
+ o ? PyString_AS_STRING(o) : "?");\r
+ Py_XDECREF(o);\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+/* Raise a TypeError for an MRO order disagreement.\r
+\r
+ It's hard to produce a good error message. In the absence of better\r
+ insight into error reporting, report the classes that were candidates\r
+ to be put next into the MRO. There is some conflict between the\r
+ order in which they should be put in the MRO, but it's hard to\r
+ diagnose what constraint can't be satisfied.\r
+*/\r
+\r
+static void\r
+set_mro_error(PyObject *to_merge, int *remain)\r
+{\r
+ Py_ssize_t i, n, off, to_merge_size;\r
+ char buf[1000];\r
+ PyObject *k, *v;\r
+ PyObject *set = PyDict_New();\r
+ if (!set) return;\r
+\r
+ to_merge_size = PyList_GET_SIZE(to_merge);\r
+ for (i = 0; i < to_merge_size; i++) {\r
+ PyObject *L = PyList_GET_ITEM(to_merge, i);\r
+ if (remain[i] < PyList_GET_SIZE(L)) {\r
+ PyObject *c = PyList_GET_ITEM(L, remain[i]);\r
+ if (PyDict_SetItem(set, c, Py_None) < 0) {\r
+ Py_DECREF(set);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ n = PyDict_Size(set);\r
+\r
+ off = PyOS_snprintf(buf, sizeof(buf), "Cannot create a \\r
+consistent method resolution\norder (MRO) for bases");\r
+ i = 0;\r
+ while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) {\r
+ PyObject *name = class_name(k);\r
+ off += PyOS_snprintf(buf + off, sizeof(buf) - off, " %s",\r
+ name ? PyString_AS_STRING(name) : "?");\r
+ Py_XDECREF(name);\r
+ if (--n && (size_t)(off+1) < sizeof(buf)) {\r
+ buf[off++] = ',';\r
+ buf[off] = '\0';\r
+ }\r
+ }\r
+ PyErr_SetString(PyExc_TypeError, buf);\r
+ Py_DECREF(set);\r
+}\r
+\r
+static int\r
+pmerge(PyObject *acc, PyObject* to_merge) {\r
+ Py_ssize_t i, j, to_merge_size, empty_cnt;\r
+ int *remain;\r
+ int ok;\r
+\r
+ to_merge_size = PyList_GET_SIZE(to_merge);\r
+\r
+ /* remain stores an index into each sublist of to_merge.\r
+ remain[i] is the index of the next base in to_merge[i]\r
+ that is not included in acc.\r
+ */\r
+ remain = (int *)PyMem_MALLOC(SIZEOF_INT*to_merge_size);\r
+ if (remain == NULL)\r
+ return -1;\r
+ for (i = 0; i < to_merge_size; i++)\r
+ remain[i] = 0;\r
+\r
+ again:\r
+ empty_cnt = 0;\r
+ for (i = 0; i < to_merge_size; i++) {\r
+ PyObject *candidate;\r
+\r
+ PyObject *cur_list = PyList_GET_ITEM(to_merge, i);\r
+\r
+ if (remain[i] >= PyList_GET_SIZE(cur_list)) {\r
+ empty_cnt++;\r
+ continue;\r
+ }\r
+\r
+ /* Choose next candidate for MRO.\r
+\r
+ The input sequences alone can determine the choice.\r
+ If not, choose the class which appears in the MRO\r
+ of the earliest direct superclass of the new class.\r
+ */\r
+\r
+ candidate = PyList_GET_ITEM(cur_list, remain[i]);\r
+ for (j = 0; j < to_merge_size; j++) {\r
+ PyObject *j_lst = PyList_GET_ITEM(to_merge, j);\r
+ if (tail_contains(j_lst, remain[j], candidate)) {\r
+ goto skip; /* continue outer loop */\r
+ }\r
+ }\r
+ ok = PyList_Append(acc, candidate);\r
+ if (ok < 0) {\r
+ PyMem_Free(remain);\r
+ return -1;\r
+ }\r
+ for (j = 0; j < to_merge_size; j++) {\r
+ PyObject *j_lst = PyList_GET_ITEM(to_merge, j);\r
+ if (remain[j] < PyList_GET_SIZE(j_lst) &&\r
+ PyList_GET_ITEM(j_lst, remain[j]) == candidate) {\r
+ remain[j]++;\r
+ }\r
+ }\r
+ goto again;\r
+ skip: ;\r
+ }\r
+\r
+ if (empty_cnt == to_merge_size) {\r
+ PyMem_FREE(remain);\r
+ return 0;\r
+ }\r
+ set_mro_error(to_merge, remain);\r
+ PyMem_FREE(remain);\r
+ return -1;\r
+}\r
+\r
+static PyObject *\r
+mro_implementation(PyTypeObject *type)\r
+{\r
+ Py_ssize_t i, n;\r
+ int ok;\r
+ PyObject *bases, *result;\r
+ PyObject *to_merge, *bases_aslist;\r
+\r
+ if (type->tp_dict == NULL) {\r
+ if (PyType_Ready(type) < 0)\r
+ return NULL;\r
+ }\r
+\r
+ /* Find a superclass linearization that honors the constraints\r
+ of the explicit lists of bases and the constraints implied by\r
+ each base class.\r
+\r
+ to_merge is a list of lists, where each list is a superclass\r
+ linearization implied by a base class. The last element of\r
+ to_merge is the declared list of bases.\r
+ */\r
+\r
+ bases = type->tp_bases;\r
+ n = PyTuple_GET_SIZE(bases);\r
+\r
+ to_merge = PyList_New(n+1);\r
+ if (to_merge == NULL)\r
+ return NULL;\r
+\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *base = PyTuple_GET_ITEM(bases, i);\r
+ PyObject *parentMRO;\r
+ if (PyType_Check(base))\r
+ parentMRO = PySequence_List(\r
+ ((PyTypeObject*)base)->tp_mro);\r
+ else\r
+ parentMRO = classic_mro(base);\r
+ if (parentMRO == NULL) {\r
+ Py_DECREF(to_merge);\r
+ return NULL;\r
+ }\r
+\r
+ PyList_SET_ITEM(to_merge, i, parentMRO);\r
+ }\r
+\r
+ bases_aslist = PySequence_List(bases);\r
+ if (bases_aslist == NULL) {\r
+ Py_DECREF(to_merge);\r
+ return NULL;\r
+ }\r
+ /* This is just a basic sanity check. */\r
+ if (check_duplicates(bases_aslist) < 0) {\r
+ Py_DECREF(to_merge);\r
+ Py_DECREF(bases_aslist);\r
+ return NULL;\r
+ }\r
+ PyList_SET_ITEM(to_merge, n, bases_aslist);\r
+\r
+ result = Py_BuildValue("[O]", (PyObject *)type);\r
+ if (result == NULL) {\r
+ Py_DECREF(to_merge);\r
+ return NULL;\r
+ }\r
+\r
+ ok = pmerge(result, to_merge);\r
+ Py_DECREF(to_merge);\r
+ if (ok < 0) {\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+mro_external(PyObject *self)\r
+{\r
+ PyTypeObject *type = (PyTypeObject *)self;\r
+\r
+ return mro_implementation(type);\r
+}\r
+\r
+static int\r
+mro_internal(PyTypeObject *type)\r
+{\r
+ PyObject *mro, *result, *tuple;\r
+ int checkit = 0;\r
+\r
+ if (Py_TYPE(type) == &PyType_Type) {\r
+ result = mro_implementation(type);\r
+ }\r
+ else {\r
+ static PyObject *mro_str;\r
+ checkit = 1;\r
+ mro = lookup_method((PyObject *)type, "mro", &mro_str);\r
+ if (mro == NULL)\r
+ return -1;\r
+ result = PyObject_CallObject(mro, NULL);\r
+ Py_DECREF(mro);\r
+ }\r
+ if (result == NULL)\r
+ return -1;\r
+ tuple = PySequence_Tuple(result);\r
+ Py_DECREF(result);\r
+ if (tuple == NULL)\r
+ return -1;\r
+ if (checkit) {\r
+ Py_ssize_t i, len;\r
+ PyObject *cls;\r
+ PyTypeObject *solid;\r
+\r
+ solid = solid_base(type);\r
+\r
+ len = PyTuple_GET_SIZE(tuple);\r
+\r
+ for (i = 0; i < len; i++) {\r
+ PyTypeObject *t;\r
+ cls = PyTuple_GET_ITEM(tuple, i);\r
+ if (PyClass_Check(cls))\r
+ continue;\r
+ else if (!PyType_Check(cls)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "mro() returned a non-class ('%.500s')",\r
+ Py_TYPE(cls)->tp_name);\r
+ Py_DECREF(tuple);\r
+ return -1;\r
+ }\r
+ t = (PyTypeObject*)cls;\r
+ if (!PyType_IsSubtype(solid, solid_base(t))) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "mro() returned base with unsuitable layout ('%.500s')",\r
+ t->tp_name);\r
+ Py_DECREF(tuple);\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+ type->tp_mro = tuple;\r
+\r
+ type_mro_modified(type, type->tp_mro);\r
+ /* corner case: the old-style super class might have been hidden\r
+ from the custom MRO */\r
+ type_mro_modified(type, type->tp_bases);\r
+\r
+ PyType_Modified(type);\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+/* Calculate the best base amongst multiple base classes.\r
+ This is the first one that's on the path to the "solid base". */\r
+\r
+static PyTypeObject *\r
+best_base(PyObject *bases)\r
+{\r
+ Py_ssize_t i, n;\r
+ PyTypeObject *base, *winner, *candidate, *base_i;\r
+ PyObject *base_proto;\r
+\r
+ assert(PyTuple_Check(bases));\r
+ n = PyTuple_GET_SIZE(bases);\r
+ assert(n > 0);\r
+ base = NULL;\r
+ winner = NULL;\r
+ for (i = 0; i < n; i++) {\r
+ base_proto = PyTuple_GET_ITEM(bases, i);\r
+ if (PyClass_Check(base_proto))\r
+ continue;\r
+ if (!PyType_Check(base_proto)) {\r
+ PyErr_SetString(\r
+ PyExc_TypeError,\r
+ "bases must be types");\r
+ return NULL;\r
+ }\r
+ base_i = (PyTypeObject *)base_proto;\r
+ if (base_i->tp_dict == NULL) {\r
+ if (PyType_Ready(base_i) < 0)\r
+ return NULL;\r
+ }\r
+ candidate = solid_base(base_i);\r
+ if (winner == NULL) {\r
+ winner = candidate;\r
+ base = base_i;\r
+ }\r
+ else if (PyType_IsSubtype(winner, candidate))\r
+ ;\r
+ else if (PyType_IsSubtype(candidate, winner)) {\r
+ winner = candidate;\r
+ base = base_i;\r
+ }\r
+ else {\r
+ PyErr_SetString(\r
+ PyExc_TypeError,\r
+ "multiple bases have "\r
+ "instance lay-out conflict");\r
+ return NULL;\r
+ }\r
+ }\r
+ if (base == NULL)\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "a new-style class can't have only classic bases");\r
+ return base;\r
+}\r
+\r
+static int\r
+extra_ivars(PyTypeObject *type, PyTypeObject *base)\r
+{\r
+ size_t t_size = type->tp_basicsize;\r
+ size_t b_size = base->tp_basicsize;\r
+\r
+ assert(t_size >= b_size); /* Else type smaller than base! */\r
+ if (type->tp_itemsize || base->tp_itemsize) {\r
+ /* If itemsize is involved, stricter rules */\r
+ return t_size != b_size ||\r
+ type->tp_itemsize != base->tp_itemsize;\r
+ }\r
+ if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 &&\r
+ type->tp_weaklistoffset + sizeof(PyObject *) == t_size &&\r
+ type->tp_flags & Py_TPFLAGS_HEAPTYPE)\r
+ t_size -= sizeof(PyObject *);\r
+ if (type->tp_dictoffset && base->tp_dictoffset == 0 &&\r
+ type->tp_dictoffset + sizeof(PyObject *) == t_size &&\r
+ type->tp_flags & Py_TPFLAGS_HEAPTYPE)\r
+ t_size -= sizeof(PyObject *);\r
+\r
+ return t_size != b_size;\r
+}\r
+\r
+static PyTypeObject *\r
+solid_base(PyTypeObject *type)\r
+{\r
+ PyTypeObject *base;\r
+\r
+ if (type->tp_base)\r
+ base = solid_base(type->tp_base);\r
+ else\r
+ base = &PyBaseObject_Type;\r
+ if (extra_ivars(type, base))\r
+ return type;\r
+ else\r
+ return base;\r
+}\r
+\r
+static void object_dealloc(PyObject *);\r
+static int object_init(PyObject *, PyObject *, PyObject *);\r
+static int update_slot(PyTypeObject *, PyObject *);\r
+static void fixup_slot_dispatchers(PyTypeObject *);\r
+\r
+/*\r
+ * Helpers for __dict__ descriptor. We don't want to expose the dicts\r
+ * inherited from various builtin types. The builtin base usually provides\r
+ * its own __dict__ descriptor, so we use that when we can.\r
+ */\r
+static PyTypeObject *\r
+get_builtin_base_with_dict(PyTypeObject *type)\r
+{\r
+ while (type->tp_base != NULL) {\r
+ if (type->tp_dictoffset != 0 &&\r
+ !(type->tp_flags & Py_TPFLAGS_HEAPTYPE))\r
+ return type;\r
+ type = type->tp_base;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+get_dict_descriptor(PyTypeObject *type)\r
+{\r
+ static PyObject *dict_str;\r
+ PyObject *descr;\r
+\r
+ if (dict_str == NULL) {\r
+ dict_str = PyString_InternFromString("__dict__");\r
+ if (dict_str == NULL)\r
+ return NULL;\r
+ }\r
+ descr = _PyType_Lookup(type, dict_str);\r
+ if (descr == NULL || !PyDescr_IsData(descr))\r
+ return NULL;\r
+\r
+ return descr;\r
+}\r
+\r
+static void\r
+raise_dict_descr_error(PyObject *obj)\r
+{\r
+ PyErr_Format(PyExc_TypeError,\r
+ "this __dict__ descriptor does not support "\r
+ "'%.200s' objects", obj->ob_type->tp_name);\r
+}\r
+\r
+static PyObject *\r
+subtype_dict(PyObject *obj, void *context)\r
+{\r
+ PyObject **dictptr;\r
+ PyObject *dict;\r
+ PyTypeObject *base;\r
+\r
+ base = get_builtin_base_with_dict(obj->ob_type);\r
+ if (base != NULL) {\r
+ descrgetfunc func;\r
+ PyObject *descr = get_dict_descriptor(base);\r
+ if (descr == NULL) {\r
+ raise_dict_descr_error(obj);\r
+ return NULL;\r
+ }\r
+ func = descr->ob_type->tp_descr_get;\r
+ if (func == NULL) {\r
+ raise_dict_descr_error(obj);\r
+ return NULL;\r
+ }\r
+ return func(descr, obj, (PyObject *)(obj->ob_type));\r
+ }\r
+\r
+ dictptr = _PyObject_GetDictPtr(obj);\r
+ if (dictptr == NULL) {\r
+ PyErr_SetString(PyExc_AttributeError,\r
+ "This object has no __dict__");\r
+ return NULL;\r
+ }\r
+ dict = *dictptr;\r
+ if (dict == NULL)\r
+ *dictptr = dict = PyDict_New();\r
+ Py_XINCREF(dict);\r
+ return dict;\r
+}\r
+\r
+static int\r
+subtype_setdict(PyObject *obj, PyObject *value, void *context)\r
+{\r
+ PyObject **dictptr;\r
+ PyObject *dict;\r
+ PyTypeObject *base;\r
+\r
+ base = get_builtin_base_with_dict(obj->ob_type);\r
+ if (base != NULL) {\r
+ descrsetfunc func;\r
+ PyObject *descr = get_dict_descriptor(base);\r
+ if (descr == NULL) {\r
+ raise_dict_descr_error(obj);\r
+ return -1;\r
+ }\r
+ func = descr->ob_type->tp_descr_set;\r
+ if (func == NULL) {\r
+ raise_dict_descr_error(obj);\r
+ return -1;\r
+ }\r
+ return func(descr, obj, value);\r
+ }\r
+\r
+ dictptr = _PyObject_GetDictPtr(obj);\r
+ if (dictptr == NULL) {\r
+ PyErr_SetString(PyExc_AttributeError,\r
+ "This object has no __dict__");\r
+ return -1;\r
+ }\r
+ if (value != NULL && !PyDict_Check(value)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__dict__ must be set to a dictionary, "\r
+ "not a '%.200s'", Py_TYPE(value)->tp_name);\r
+ return -1;\r
+ }\r
+ dict = *dictptr;\r
+ Py_XINCREF(value);\r
+ *dictptr = value;\r
+ Py_XDECREF(dict);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+subtype_getweakref(PyObject *obj, void *context)\r
+{\r
+ PyObject **weaklistptr;\r
+ PyObject *result;\r
+\r
+ if (Py_TYPE(obj)->tp_weaklistoffset == 0) {\r
+ PyErr_SetString(PyExc_AttributeError,\r
+ "This object has no __weakref__");\r
+ return NULL;\r
+ }\r
+ assert(Py_TYPE(obj)->tp_weaklistoffset > 0);\r
+ assert(Py_TYPE(obj)->tp_weaklistoffset + sizeof(PyObject *) <=\r
+ (size_t)(Py_TYPE(obj)->tp_basicsize));\r
+ weaklistptr = (PyObject **)\r
+ ((char *)obj + Py_TYPE(obj)->tp_weaklistoffset);\r
+ if (*weaklistptr == NULL)\r
+ result = Py_None;\r
+ else\r
+ result = *weaklistptr;\r
+ Py_INCREF(result);\r
+ return result;\r
+}\r
+\r
+/* Three variants on the subtype_getsets list. */\r
+\r
+static PyGetSetDef subtype_getsets_full[] = {\r
+ {"__dict__", subtype_dict, subtype_setdict,\r
+ PyDoc_STR("dictionary for instance variables (if defined)")},\r
+ {"__weakref__", subtype_getweakref, NULL,\r
+ PyDoc_STR("list of weak references to the object (if defined)")},\r
+ {0}\r
+};\r
+\r
+static PyGetSetDef subtype_getsets_dict_only[] = {\r
+ {"__dict__", subtype_dict, subtype_setdict,\r
+ PyDoc_STR("dictionary for instance variables (if defined)")},\r
+ {0}\r
+};\r
+\r
+static PyGetSetDef subtype_getsets_weakref_only[] = {\r
+ {"__weakref__", subtype_getweakref, NULL,\r
+ PyDoc_STR("list of weak references to the object (if defined)")},\r
+ {0}\r
+};\r
+\r
+static int\r
+valid_identifier(PyObject *s)\r
+{\r
+ unsigned char *p;\r
+ Py_ssize_t i, n;\r
+\r
+ if (!PyString_Check(s)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__slots__ items must be strings, not '%.200s'",\r
+ Py_TYPE(s)->tp_name);\r
+ return 0;\r
+ }\r
+ p = (unsigned char *) PyString_AS_STRING(s);\r
+ n = PyString_GET_SIZE(s);\r
+ /* We must reject an empty name. As a hack, we bump the\r
+ length to 1 so that the loop will balk on the trailing \0. */\r
+ if (n == 0)\r
+ n = 1;\r
+ for (i = 0; i < n; i++, p++) {\r
+ if (!(i == 0 ? isalpha(*p) : isalnum(*p)) && *p != '_') {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__slots__ must be identifiers");\r
+ return 0;\r
+ }\r
+ }\r
+ return 1;\r
+}\r
+\r
+#ifdef Py_USING_UNICODE\r
+/* Replace Unicode objects in slots. */\r
+\r
+static PyObject *\r
+_unicode_to_string(PyObject *slots, Py_ssize_t nslots)\r
+{\r
+ PyObject *tmp = NULL;\r
+ PyObject *slot_name, *new_name;\r
+ Py_ssize_t i;\r
+\r
+ for (i = 0; i < nslots; i++) {\r
+ if (PyUnicode_Check(slot_name = PyTuple_GET_ITEM(slots, i))) {\r
+ if (tmp == NULL) {\r
+ tmp = PySequence_List(slots);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ }\r
+ new_name = _PyUnicode_AsDefaultEncodedString(slot_name,\r
+ NULL);\r
+ if (new_name == NULL) {\r
+ Py_DECREF(tmp);\r
+ return NULL;\r
+ }\r
+ Py_INCREF(new_name);\r
+ PyList_SET_ITEM(tmp, i, new_name);\r
+ Py_DECREF(slot_name);\r
+ }\r
+ }\r
+ if (tmp != NULL) {\r
+ slots = PyList_AsTuple(tmp);\r
+ Py_DECREF(tmp);\r
+ }\r
+ return slots;\r
+}\r
+#endif\r
+\r
+/* Forward */\r
+static int\r
+object_init(PyObject *self, PyObject *args, PyObject *kwds);\r
+\r
+static int\r
+type_init(PyObject *cls, PyObject *args, PyObject *kwds)\r
+{\r
+ int res;\r
+\r
+ assert(args != NULL && PyTuple_Check(args));\r
+ assert(kwds == NULL || PyDict_Check(kwds));\r
+\r
+ if (kwds != NULL && PyDict_Check(kwds) && PyDict_Size(kwds) != 0) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "type.__init__() takes no keyword arguments");\r
+ return -1;\r
+ }\r
+\r
+ if (args != NULL && PyTuple_Check(args) &&\r
+ (PyTuple_GET_SIZE(args) != 1 && PyTuple_GET_SIZE(args) != 3)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "type.__init__() takes 1 or 3 arguments");\r
+ return -1;\r
+ }\r
+\r
+ /* Call object.__init__(self) now. */\r
+ /* XXX Could call super(type, cls).__init__() but what's the point? */\r
+ args = PyTuple_GetSlice(args, 0, 0);\r
+ res = object_init(cls, args, NULL);\r
+ Py_DECREF(args);\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *name, *bases, *dict;\r
+ static char *kwlist[] = {"name", "bases", "dict", 0};\r
+ PyObject *slots, *tmp, *newslots;\r
+ PyTypeObject *type, *base, *tmptype, *winner;\r
+ PyHeapTypeObject *et;\r
+ PyMemberDef *mp;\r
+ Py_ssize_t i, nbases, nslots, slotoffset, add_dict, add_weak;\r
+ int j, may_add_dict, may_add_weak;\r
+\r
+ assert(args != NULL && PyTuple_Check(args));\r
+ assert(kwds == NULL || PyDict_Check(kwds));\r
+\r
+ /* Special case: type(x) should return x->ob_type */\r
+ {\r
+ const Py_ssize_t nargs = PyTuple_GET_SIZE(args);\r
+ const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);\r
+\r
+ if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) {\r
+ PyObject *x = PyTuple_GET_ITEM(args, 0);\r
+ Py_INCREF(Py_TYPE(x));\r
+ return (PyObject *) Py_TYPE(x);\r
+ }\r
+\r
+ /* SF bug 475327 -- if that didn't trigger, we need 3\r
+ arguments. but PyArg_ParseTupleAndKeywords below may give\r
+ a msg saying type() needs exactly 3. */\r
+ if (nargs + nkwds != 3) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "type() takes 1 or 3 arguments");\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ /* Check arguments: (name, bases, dict) */\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "SO!O!:type", kwlist,\r
+ &name,\r
+ &PyTuple_Type, &bases,\r
+ &PyDict_Type, &dict))\r
+ return NULL;\r
+\r
+ /* Determine the proper metatype to deal with this,\r
+ and check for metatype conflicts while we're at it.\r
+ Note that if some other metatype wins to contract,\r
+ it's possible that its instances are not types. */\r
+ nbases = PyTuple_GET_SIZE(bases);\r
+ winner = metatype;\r
+ for (i = 0; i < nbases; i++) {\r
+ tmp = PyTuple_GET_ITEM(bases, i);\r
+ tmptype = tmp->ob_type;\r
+ if (tmptype == &PyClass_Type)\r
+ continue; /* Special case classic classes */\r
+ if (PyType_IsSubtype(winner, tmptype))\r
+ continue;\r
+ if (PyType_IsSubtype(tmptype, winner)) {\r
+ winner = tmptype;\r
+ continue;\r
+ }\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "metaclass conflict: "\r
+ "the metaclass of a derived class "\r
+ "must be a (non-strict) subclass "\r
+ "of the metaclasses of all its bases");\r
+ return NULL;\r
+ }\r
+ if (winner != metatype) {\r
+ if (winner->tp_new != type_new) /* Pass it to the winner */\r
+ return winner->tp_new(winner, args, kwds);\r
+ metatype = winner;\r
+ }\r
+\r
+ /* Adjust for empty tuple bases */\r
+ if (nbases == 0) {\r
+ bases = PyTuple_Pack(1, &PyBaseObject_Type);\r
+ if (bases == NULL)\r
+ return NULL;\r
+ nbases = 1;\r
+ }\r
+ else\r
+ Py_INCREF(bases);\r
+\r
+ /* XXX From here until type is allocated, "return NULL" leaks bases! */\r
+\r
+ /* Calculate best base, and check that all bases are type objects */\r
+ base = best_base(bases);\r
+ if (base == NULL) {\r
+ Py_DECREF(bases);\r
+ return NULL;\r
+ }\r
+ if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "type '%.100s' is not an acceptable base type",\r
+ base->tp_name);\r
+ Py_DECREF(bases);\r
+ return NULL;\r
+ }\r
+\r
+ /* Check for a __slots__ sequence variable in dict, and count it */\r
+ slots = PyDict_GetItemString(dict, "__slots__");\r
+ nslots = 0;\r
+ add_dict = 0;\r
+ add_weak = 0;\r
+ may_add_dict = base->tp_dictoffset == 0;\r
+ may_add_weak = base->tp_weaklistoffset == 0 && base->tp_itemsize == 0;\r
+ if (slots == NULL) {\r
+ if (may_add_dict) {\r
+ add_dict++;\r
+ }\r
+ if (may_add_weak) {\r
+ add_weak++;\r
+ }\r
+ }\r
+ else {\r
+ /* Have slots */\r
+\r
+ /* Make it into a tuple */\r
+ if (PyString_Check(slots) || PyUnicode_Check(slots))\r
+ slots = PyTuple_Pack(1, slots);\r
+ else\r
+ slots = PySequence_Tuple(slots);\r
+ if (slots == NULL) {\r
+ Py_DECREF(bases);\r
+ return NULL;\r
+ }\r
+ assert(PyTuple_Check(slots));\r
+\r
+ /* Are slots allowed? */\r
+ nslots = PyTuple_GET_SIZE(slots);\r
+ if (nslots > 0 && base->tp_itemsize != 0) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "nonempty __slots__ "\r
+ "not supported for subtype of '%s'",\r
+ base->tp_name);\r
+ bad_slots:\r
+ Py_DECREF(bases);\r
+ Py_DECREF(slots);\r
+ return NULL;\r
+ }\r
+\r
+#ifdef Py_USING_UNICODE\r
+ tmp = _unicode_to_string(slots, nslots);\r
+ if (tmp == NULL)\r
+ goto bad_slots;\r
+ if (tmp != slots) {\r
+ Py_DECREF(slots);\r
+ slots = tmp;\r
+ }\r
+#endif\r
+ /* Check for valid slot names and two special cases */\r
+ for (i = 0; i < nslots; i++) {\r
+ PyObject *tmp = PyTuple_GET_ITEM(slots, i);\r
+ char *s;\r
+ if (!valid_identifier(tmp))\r
+ goto bad_slots;\r
+ assert(PyString_Check(tmp));\r
+ s = PyString_AS_STRING(tmp);\r
+ if (strcmp(s, "__dict__") == 0) {\r
+ if (!may_add_dict || add_dict) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__dict__ slot disallowed: "\r
+ "we already got one");\r
+ goto bad_slots;\r
+ }\r
+ add_dict++;\r
+ }\r
+ if (strcmp(s, "__weakref__") == 0) {\r
+ if (!may_add_weak || add_weak) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__weakref__ slot disallowed: "\r
+ "either we already got one, "\r
+ "or __itemsize__ != 0");\r
+ goto bad_slots;\r
+ }\r
+ add_weak++;\r
+ }\r
+ }\r
+\r
+ /* Copy slots into a list, mangle names and sort them.\r
+ Sorted names are needed for __class__ assignment.\r
+ Convert them back to tuple at the end.\r
+ */\r
+ newslots = PyList_New(nslots - add_dict - add_weak);\r
+ if (newslots == NULL)\r
+ goto bad_slots;\r
+ for (i = j = 0; i < nslots; i++) {\r
+ char *s;\r
+ tmp = PyTuple_GET_ITEM(slots, i);\r
+ s = PyString_AS_STRING(tmp);\r
+ if ((add_dict && strcmp(s, "__dict__") == 0) ||\r
+ (add_weak && strcmp(s, "__weakref__") == 0))\r
+ continue;\r
+ tmp =_Py_Mangle(name, tmp);\r
+ if (!tmp) {\r
+ Py_DECREF(newslots);\r
+ goto bad_slots;\r
+ }\r
+ PyList_SET_ITEM(newslots, j, tmp);\r
+ j++;\r
+ }\r
+ assert(j == nslots - add_dict - add_weak);\r
+ nslots = j;\r
+ Py_DECREF(slots);\r
+ if (PyList_Sort(newslots) == -1) {\r
+ Py_DECREF(bases);\r
+ Py_DECREF(newslots);\r
+ return NULL;\r
+ }\r
+ slots = PyList_AsTuple(newslots);\r
+ Py_DECREF(newslots);\r
+ if (slots == NULL) {\r
+ Py_DECREF(bases);\r
+ return NULL;\r
+ }\r
+\r
+ /* Secondary bases may provide weakrefs or dict */\r
+ if (nbases > 1 &&\r
+ ((may_add_dict && !add_dict) ||\r
+ (may_add_weak && !add_weak))) {\r
+ for (i = 0; i < nbases; i++) {\r
+ tmp = PyTuple_GET_ITEM(bases, i);\r
+ if (tmp == (PyObject *)base)\r
+ continue; /* Skip primary base */\r
+ if (PyClass_Check(tmp)) {\r
+ /* Classic base class provides both */\r
+ if (may_add_dict && !add_dict)\r
+ add_dict++;\r
+ if (may_add_weak && !add_weak)\r
+ add_weak++;\r
+ break;\r
+ }\r
+ assert(PyType_Check(tmp));\r
+ tmptype = (PyTypeObject *)tmp;\r
+ if (may_add_dict && !add_dict &&\r
+ tmptype->tp_dictoffset != 0)\r
+ add_dict++;\r
+ if (may_add_weak && !add_weak &&\r
+ tmptype->tp_weaklistoffset != 0)\r
+ add_weak++;\r
+ if (may_add_dict && !add_dict)\r
+ continue;\r
+ if (may_add_weak && !add_weak)\r
+ continue;\r
+ /* Nothing more to check */\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* XXX From here until type is safely allocated,\r
+ "return NULL" may leak slots! */\r
+\r
+ /* Allocate the type object */\r
+ type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots);\r
+ if (type == NULL) {\r
+ Py_XDECREF(slots);\r
+ Py_DECREF(bases);\r
+ return NULL;\r
+ }\r
+\r
+ /* Keep name and slots alive in the extended type object */\r
+ et = (PyHeapTypeObject *)type;\r
+ Py_INCREF(name);\r
+ et->ht_name = name;\r
+ et->ht_slots = slots;\r
+\r
+ /* Initialize tp_flags */\r
+ type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE |\r
+ Py_TPFLAGS_BASETYPE;\r
+ if (base->tp_flags & Py_TPFLAGS_HAVE_GC)\r
+ type->tp_flags |= Py_TPFLAGS_HAVE_GC;\r
+ if (base->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER)\r
+ type->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;\r
+\r
+ /* It's a new-style number unless it specifically inherits any\r
+ old-style numeric behavior */\r
+ if ((base->tp_flags & Py_TPFLAGS_CHECKTYPES) ||\r
+ (base->tp_as_number == NULL))\r
+ type->tp_flags |= Py_TPFLAGS_CHECKTYPES;\r
+\r
+ /* Initialize essential fields */\r
+ type->tp_as_number = &et->as_number;\r
+ type->tp_as_sequence = &et->as_sequence;\r
+ type->tp_as_mapping = &et->as_mapping;\r
+ type->tp_as_buffer = &et->as_buffer;\r
+ type->tp_name = PyString_AS_STRING(name);\r
+\r
+ /* Set tp_base and tp_bases */\r
+ type->tp_bases = bases;\r
+ Py_INCREF(base);\r
+ type->tp_base = base;\r
+\r
+ /* Initialize tp_dict from passed-in dict */\r
+ type->tp_dict = dict = PyDict_Copy(dict);\r
+ if (dict == NULL) {\r
+ Py_DECREF(type);\r
+ return NULL;\r
+ }\r
+\r
+ /* Set __module__ in the dict */\r
+ if (PyDict_GetItemString(dict, "__module__") == NULL) {\r
+ tmp = PyEval_GetGlobals();\r
+ if (tmp != NULL) {\r
+ tmp = PyDict_GetItemString(tmp, "__name__");\r
+ if (tmp != NULL) {\r
+ if (PyDict_SetItemString(dict, "__module__",\r
+ tmp) < 0)\r
+ return NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Set tp_doc to a copy of dict['__doc__'], if the latter is there\r
+ and is a string. The __doc__ accessor will first look for tp_doc;\r
+ if that fails, it will still look into __dict__.\r
+ */\r
+ {\r
+ PyObject *doc = PyDict_GetItemString(dict, "__doc__");\r
+ if (doc != NULL && PyString_Check(doc)) {\r
+ const size_t n = (size_t)PyString_GET_SIZE(doc);\r
+ char *tp_doc = (char *)PyObject_MALLOC(n+1);\r
+ if (tp_doc == NULL) {\r
+ Py_DECREF(type);\r
+ return NULL;\r
+ }\r
+ memcpy(tp_doc, PyString_AS_STRING(doc), n+1);\r
+ type->tp_doc = tp_doc;\r
+ }\r
+ }\r
+\r
+ /* Special-case __new__: if it's a plain function,\r
+ make it a static function */\r
+ tmp = PyDict_GetItemString(dict, "__new__");\r
+ if (tmp != NULL && PyFunction_Check(tmp)) {\r
+ tmp = PyStaticMethod_New(tmp);\r
+ if (tmp == NULL) {\r
+ Py_DECREF(type);\r
+ return NULL;\r
+ }\r
+ PyDict_SetItemString(dict, "__new__", tmp);\r
+ Py_DECREF(tmp);\r
+ }\r
+\r
+ /* Add descriptors for custom slots from __slots__, or for __dict__ */\r
+ mp = PyHeapType_GET_MEMBERS(et);\r
+ slotoffset = base->tp_basicsize;\r
+ if (slots != NULL) {\r
+ for (i = 0; i < nslots; i++, mp++) {\r
+ mp->name = PyString_AS_STRING(\r
+ PyTuple_GET_ITEM(slots, i));\r
+ mp->type = T_OBJECT_EX;\r
+ mp->offset = slotoffset;\r
+\r
+ /* __dict__ and __weakref__ are already filtered out */\r
+ assert(strcmp(mp->name, "__dict__") != 0);\r
+ assert(strcmp(mp->name, "__weakref__") != 0);\r
+\r
+ slotoffset += sizeof(PyObject *);\r
+ }\r
+ }\r
+ if (add_dict) {\r
+ if (base->tp_itemsize)\r
+ type->tp_dictoffset = -(long)sizeof(PyObject *);\r
+ else\r
+ type->tp_dictoffset = slotoffset;\r
+ slotoffset += sizeof(PyObject *);\r
+ }\r
+ if (add_weak) {\r
+ assert(!base->tp_itemsize);\r
+ type->tp_weaklistoffset = slotoffset;\r
+ slotoffset += sizeof(PyObject *);\r
+ }\r
+ type->tp_basicsize = slotoffset;\r
+ type->tp_itemsize = base->tp_itemsize;\r
+ type->tp_members = PyHeapType_GET_MEMBERS(et);\r
+\r
+ if (type->tp_weaklistoffset && type->tp_dictoffset)\r
+ type->tp_getset = subtype_getsets_full;\r
+ else if (type->tp_weaklistoffset && !type->tp_dictoffset)\r
+ type->tp_getset = subtype_getsets_weakref_only;\r
+ else if (!type->tp_weaklistoffset && type->tp_dictoffset)\r
+ type->tp_getset = subtype_getsets_dict_only;\r
+ else\r
+ type->tp_getset = NULL;\r
+\r
+ /* Special case some slots */\r
+ if (type->tp_dictoffset != 0 || nslots > 0) {\r
+ if (base->tp_getattr == NULL && base->tp_getattro == NULL)\r
+ type->tp_getattro = PyObject_GenericGetAttr;\r
+ if (base->tp_setattr == NULL && base->tp_setattro == NULL)\r
+ type->tp_setattro = PyObject_GenericSetAttr;\r
+ }\r
+ type->tp_dealloc = subtype_dealloc;\r
+\r
+ /* Enable GC unless there are really no instance variables possible */\r
+ if (!(type->tp_basicsize == sizeof(PyObject) &&\r
+ type->tp_itemsize == 0))\r
+ type->tp_flags |= Py_TPFLAGS_HAVE_GC;\r
+\r
+ /* Always override allocation strategy to use regular heap */\r
+ type->tp_alloc = PyType_GenericAlloc;\r
+ if (type->tp_flags & Py_TPFLAGS_HAVE_GC) {\r
+ type->tp_free = PyObject_GC_Del;\r
+ type->tp_traverse = subtype_traverse;\r
+ type->tp_clear = subtype_clear;\r
+ }\r
+ else\r
+ type->tp_free = PyObject_Del;\r
+\r
+ /* Initialize the rest */\r
+ if (PyType_Ready(type) < 0) {\r
+ Py_DECREF(type);\r
+ return NULL;\r
+ }\r
+\r
+ /* Put the proper slots in place */\r
+ fixup_slot_dispatchers(type);\r
+\r
+ return (PyObject *)type;\r
+}\r
+\r
+/* Internal API to look for a name through the MRO.\r
+ This returns a borrowed reference, and doesn't set an exception! */\r
+PyObject *\r
+_PyType_Lookup(PyTypeObject *type, PyObject *name)\r
+{\r
+ Py_ssize_t i, n;\r
+ PyObject *mro, *res, *base, *dict;\r
+ unsigned int h;\r
+\r
+ if (MCACHE_CACHEABLE_NAME(name) &&\r
+ PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) {\r
+ /* fast path */\r
+ h = MCACHE_HASH_METHOD(type, name);\r
+ if (method_cache[h].version == type->tp_version_tag &&\r
+ method_cache[h].name == name)\r
+ return method_cache[h].value;\r
+ }\r
+\r
+ /* Look in tp_dict of types in MRO */\r
+ mro = type->tp_mro;\r
+\r
+ /* If mro is NULL, the type is either not yet initialized\r
+ by PyType_Ready(), or already cleared by type_clear().\r
+ Either way the safest thing to do is to return NULL. */\r
+ if (mro == NULL)\r
+ return NULL;\r
+\r
+ res = NULL;\r
+ assert(PyTuple_Check(mro));\r
+ n = PyTuple_GET_SIZE(mro);\r
+ for (i = 0; i < n; i++) {\r
+ base = PyTuple_GET_ITEM(mro, i);\r
+ if (PyClass_Check(base))\r
+ dict = ((PyClassObject *)base)->cl_dict;\r
+ else {\r
+ assert(PyType_Check(base));\r
+ dict = ((PyTypeObject *)base)->tp_dict;\r
+ }\r
+ assert(dict && PyDict_Check(dict));\r
+ res = PyDict_GetItem(dict, name);\r
+ if (res != NULL)\r
+ break;\r
+ }\r
+\r
+ if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(type)) {\r
+ h = MCACHE_HASH_METHOD(type, name);\r
+ method_cache[h].version = type->tp_version_tag;\r
+ method_cache[h].value = res; /* borrowed */\r
+ Py_INCREF(name);\r
+ Py_DECREF(method_cache[h].name);\r
+ method_cache[h].name = name;\r
+ }\r
+ return res;\r
+}\r
+\r
+/* This is similar to PyObject_GenericGetAttr(),\r
+ but uses _PyType_Lookup() instead of just looking in type->tp_dict. */\r
+static PyObject *\r
+type_getattro(PyTypeObject *type, PyObject *name)\r
+{\r
+ PyTypeObject *metatype = Py_TYPE(type);\r
+ PyObject *meta_attribute, *attribute;\r
+ descrgetfunc meta_get;\r
+\r
+ if (!PyString_Check(name)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "attribute name must be string, not '%.200s'",\r
+ name->ob_type->tp_name);\r
+ return NULL;\r
+ }\r
+\r
+ /* Initialize this type (we'll assume the metatype is initialized) */\r
+ if (type->tp_dict == NULL) {\r
+ if (PyType_Ready(type) < 0)\r
+ return NULL;\r
+ }\r
+\r
+ /* No readable descriptor found yet */\r
+ meta_get = NULL;\r
+\r
+ /* Look for the attribute in the metatype */\r
+ meta_attribute = _PyType_Lookup(metatype, name);\r
+\r
+ if (meta_attribute != NULL) {\r
+ meta_get = Py_TYPE(meta_attribute)->tp_descr_get;\r
+\r
+ if (meta_get != NULL && PyDescr_IsData(meta_attribute)) {\r
+ /* Data descriptors implement tp_descr_set to intercept\r
+ * writes. Assume the attribute is not overridden in\r
+ * type's tp_dict (and bases): call the descriptor now.\r
+ */\r
+ return meta_get(meta_attribute, (PyObject *)type,\r
+ (PyObject *)metatype);\r
+ }\r
+ Py_INCREF(meta_attribute);\r
+ }\r
+\r
+ /* No data descriptor found on metatype. Look in tp_dict of this\r
+ * type and its bases */\r
+ attribute = _PyType_Lookup(type, name);\r
+ if (attribute != NULL) {\r
+ /* Implement descriptor functionality, if any */\r
+ descrgetfunc local_get = Py_TYPE(attribute)->tp_descr_get;\r
+\r
+ Py_XDECREF(meta_attribute);\r
+\r
+ if (local_get != NULL) {\r
+ /* NULL 2nd argument indicates the descriptor was\r
+ * found on the target object itself (or a base) */\r
+ return local_get(attribute, (PyObject *)NULL,\r
+ (PyObject *)type);\r
+ }\r
+\r
+ Py_INCREF(attribute);\r
+ return attribute;\r
+ }\r
+\r
+ /* No attribute found in local __dict__ (or bases): use the\r
+ * descriptor from the metatype, if any */\r
+ if (meta_get != NULL) {\r
+ PyObject *res;\r
+ res = meta_get(meta_attribute, (PyObject *)type,\r
+ (PyObject *)metatype);\r
+ Py_DECREF(meta_attribute);\r
+ return res;\r
+ }\r
+\r
+ /* If an ordinary attribute was found on the metatype, return it now */\r
+ if (meta_attribute != NULL) {\r
+ return meta_attribute;\r
+ }\r
+\r
+ /* Give up */\r
+ PyErr_Format(PyExc_AttributeError,\r
+ "type object '%.50s' has no attribute '%.400s'",\r
+ type->tp_name, PyString_AS_STRING(name));\r
+ return NULL;\r
+}\r
+\r
+static int\r
+type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)\r
+{\r
+ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {\r
+ PyErr_Format(\r
+ PyExc_TypeError,\r
+ "can't set attributes of built-in/extension type '%s'",\r
+ type->tp_name);\r
+ return -1;\r
+ }\r
+ if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)\r
+ return -1;\r
+ return update_slot(type, name);\r
+}\r
+\r
+static void\r
+type_dealloc(PyTypeObject *type)\r
+{\r
+ PyHeapTypeObject *et;\r
+\r
+ /* Assert this is a heap-allocated type object */\r
+ assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);\r
+ _PyObject_GC_UNTRACK(type);\r
+ PyObject_ClearWeakRefs((PyObject *)type);\r
+ et = (PyHeapTypeObject *)type;\r
+ Py_XDECREF(type->tp_base);\r
+ Py_XDECREF(type->tp_dict);\r
+ Py_XDECREF(type->tp_bases);\r
+ Py_XDECREF(type->tp_mro);\r
+ Py_XDECREF(type->tp_cache);\r
+ Py_XDECREF(type->tp_subclasses);\r
+ /* A type's tp_doc is heap allocated, unlike the tp_doc slots\r
+ * of most other objects. It's okay to cast it to char *.\r
+ */\r
+ PyObject_Free((char *)type->tp_doc);\r
+ Py_XDECREF(et->ht_name);\r
+ Py_XDECREF(et->ht_slots);\r
+ Py_TYPE(type)->tp_free((PyObject *)type);\r
+}\r
+\r
+static PyObject *\r
+type_subclasses(PyTypeObject *type, PyObject *args_ignored)\r
+{\r
+ PyObject *list, *raw, *ref;\r
+ Py_ssize_t i, n;\r
+\r
+ list = PyList_New(0);\r
+ if (list == NULL)\r
+ return NULL;\r
+ raw = type->tp_subclasses;\r
+ if (raw == NULL)\r
+ return list;\r
+ assert(PyList_Check(raw));\r
+ n = PyList_GET_SIZE(raw);\r
+ for (i = 0; i < n; i++) {\r
+ ref = PyList_GET_ITEM(raw, i);\r
+ assert(PyWeakref_CheckRef(ref));\r
+ ref = PyWeakref_GET_OBJECT(ref);\r
+ if (ref != Py_None) {\r
+ if (PyList_Append(list, ref) < 0) {\r
+ Py_DECREF(list);\r
+ return NULL;\r
+ }\r
+ }\r
+ }\r
+ return list;\r
+}\r
+\r
+static PyMethodDef type_methods[] = {\r
+ {"mro", (PyCFunction)mro_external, METH_NOARGS,\r
+ PyDoc_STR("mro() -> list\nreturn a type's method resolution order")},\r
+ {"__subclasses__", (PyCFunction)type_subclasses, METH_NOARGS,\r
+ PyDoc_STR("__subclasses__() -> list of immediate subclasses")},\r
+ {"__instancecheck__", type___instancecheck__, METH_O,\r
+ PyDoc_STR("__instancecheck__() -> bool\ncheck if an object is an instance")},\r
+ {"__subclasscheck__", type___subclasscheck__, METH_O,\r
+ PyDoc_STR("__subclasscheck__() -> bool\ncheck if a class is a subclass")},\r
+ {0}\r
+};\r
+\r
+PyDoc_STRVAR(type_doc,\r
+"type(object) -> the object's type\n"\r
+"type(name, bases, dict) -> a new type");\r
+\r
+static int\r
+type_traverse(PyTypeObject *type, visitproc visit, void *arg)\r
+{\r
+ /* Because of type_is_gc(), the collector only calls this\r
+ for heaptypes. */\r
+ assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);\r
+\r
+ Py_VISIT(type->tp_dict);\r
+ Py_VISIT(type->tp_cache);\r
+ Py_VISIT(type->tp_mro);\r
+ Py_VISIT(type->tp_bases);\r
+ Py_VISIT(type->tp_base);\r
+\r
+ /* There's no need to visit type->tp_subclasses or\r
+ ((PyHeapTypeObject *)type)->ht_slots, because they can't be involved\r
+ in cycles; tp_subclasses is a list of weak references,\r
+ and slots is a tuple of strings. */\r
+\r
+ return 0;\r
+}\r
+\r
+static int\r
+type_clear(PyTypeObject *type)\r
+{\r
+ /* Because of type_is_gc(), the collector only calls this\r
+ for heaptypes. */\r
+ assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);\r
+\r
+ /* We need to invalidate the method cache carefully before clearing\r
+ the dict, so that other objects caught in a reference cycle\r
+ don't start calling destroyed methods.\r
+\r
+ Otherwise, the only field we need to clear is tp_mro, which is\r
+ part of a hard cycle (its first element is the class itself) that\r
+ won't be broken otherwise (it's a tuple and tuples don't have a\r
+ tp_clear handler). None of the other fields need to be\r
+ cleared, and here's why:\r
+\r
+ tp_cache:\r
+ Not used; if it were, it would be a dict.\r
+\r
+ tp_bases, tp_base:\r
+ If these are involved in a cycle, there must be at least\r
+ one other, mutable object in the cycle, e.g. a base\r
+ class's dict; the cycle will be broken that way.\r
+\r
+ tp_subclasses:\r
+ A list of weak references can't be part of a cycle; and\r
+ lists have their own tp_clear.\r
+\r
+ slots (in PyHeapTypeObject):\r
+ A tuple of strings can't be part of a cycle.\r
+ */\r
+\r
+ PyType_Modified(type);\r
+ if (type->tp_dict)\r
+ PyDict_Clear(type->tp_dict);\r
+ Py_CLEAR(type->tp_mro);\r
+\r
+ return 0;\r
+}\r
+\r
+static int\r
+type_is_gc(PyTypeObject *type)\r
+{\r
+ return type->tp_flags & Py_TPFLAGS_HEAPTYPE;\r
+}\r
+\r
+PyTypeObject PyType_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "type", /* tp_name */\r
+ sizeof(PyHeapTypeObject), /* tp_basicsize */\r
+ sizeof(PyMemberDef), /* tp_itemsize */\r
+ (destructor)type_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ (reprfunc)type_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)_Py_HashPointer, /* tp_hash */\r
+ (ternaryfunc)type_call, /* tp_call */\r
+ 0, /* tp_str */\r
+ (getattrofunc)type_getattro, /* tp_getattro */\r
+ (setattrofunc)type_setattro, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */\r
+ type_doc, /* tp_doc */\r
+ (traverseproc)type_traverse, /* tp_traverse */\r
+ (inquiry)type_clear, /* tp_clear */\r
+ type_richcompare, /* tp_richcompare */\r
+ offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ type_methods, /* tp_methods */\r
+ type_members, /* tp_members */\r
+ type_getsets, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */\r
+ type_init, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ type_new, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+ (inquiry)type_is_gc, /* tp_is_gc */\r
+};\r
+\r
+\r
+/* The base type of all types (eventually)... except itself. */\r
+\r
+/* You may wonder why object.__new__() only complains about arguments\r
+ when object.__init__() is not overridden, and vice versa.\r
+\r
+ Consider the use cases:\r
+\r
+ 1. When neither is overridden, we want to hear complaints about\r
+ excess (i.e., any) arguments, since their presence could\r
+ indicate there's a bug.\r
+\r
+ 2. When defining an Immutable type, we are likely to override only\r
+ __new__(), since __init__() is called too late to initialize an\r
+ Immutable object. Since __new__() defines the signature for the\r
+ type, it would be a pain to have to override __init__() just to\r
+ stop it from complaining about excess arguments.\r
+\r
+ 3. When defining a Mutable type, we are likely to override only\r
+ __init__(). So here the converse reasoning applies: we don't\r
+ want to have to override __new__() just to stop it from\r
+ complaining.\r
+\r
+ 4. When __init__() is overridden, and the subclass __init__() calls\r
+ object.__init__(), the latter should complain about excess\r
+ arguments; ditto for __new__().\r
+\r
+ Use cases 2 and 3 make it unattractive to unconditionally check for\r
+ excess arguments. The best solution that addresses all four use\r
+ cases is as follows: __init__() complains about excess arguments\r
+ unless __new__() is overridden and __init__() is not overridden\r
+ (IOW, if __init__() is overridden or __new__() is not overridden);\r
+ symmetrically, __new__() complains about excess arguments unless\r
+ __init__() is overridden and __new__() is not overridden\r
+ (IOW, if __new__() is overridden or __init__() is not overridden).\r
+\r
+ However, for backwards compatibility, this breaks too much code.\r
+ Therefore, in 2.6, we'll *warn* about excess arguments when both\r
+ methods are overridden; for all other cases we'll use the above\r
+ rules.\r
+\r
+*/\r
+\r
+/* Forward */\r
+static PyObject *\r
+object_new(PyTypeObject *type, PyObject *args, PyObject *kwds);\r
+\r
+static int\r
+excess_args(PyObject *args, PyObject *kwds)\r
+{\r
+ return PyTuple_GET_SIZE(args) ||\r
+ (kwds && PyDict_Check(kwds) && PyDict_Size(kwds));\r
+}\r
+\r
+static int\r
+object_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ int err = 0;\r
+ if (excess_args(args, kwds)) {\r
+ PyTypeObject *type = Py_TYPE(self);\r
+ if (type->tp_init != object_init &&\r
+ type->tp_new != object_new)\r
+ {\r
+ err = PyErr_WarnEx(PyExc_DeprecationWarning,\r
+ "object.__init__() takes no parameters",\r
+ 1);\r
+ }\r
+ else if (type->tp_init != object_init ||\r
+ type->tp_new == object_new)\r
+ {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "object.__init__() takes no parameters");\r
+ err = -1;\r
+ }\r
+ }\r
+ return err;\r
+}\r
+\r
+static PyObject *\r
+object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ int err = 0;\r
+ if (excess_args(args, kwds)) {\r
+ if (type->tp_new != object_new &&\r
+ type->tp_init != object_init)\r
+ {\r
+ err = PyErr_WarnEx(PyExc_DeprecationWarning,\r
+ "object() takes no parameters",\r
+ 1);\r
+ }\r
+ else if (type->tp_new != object_new ||\r
+ type->tp_init == object_init)\r
+ {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "object() takes no parameters");\r
+ err = -1;\r
+ }\r
+ }\r
+ if (err < 0)\r
+ return NULL;\r
+\r
+ if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) {\r
+ static PyObject *comma = NULL;\r
+ PyObject *abstract_methods = NULL;\r
+ PyObject *builtins;\r
+ PyObject *sorted;\r
+ PyObject *sorted_methods = NULL;\r
+ PyObject *joined = NULL;\r
+ const char *joined_str;\r
+\r
+ /* Compute ", ".join(sorted(type.__abstractmethods__))\r
+ into joined. */\r
+ abstract_methods = type_abstractmethods(type, NULL);\r
+ if (abstract_methods == NULL)\r
+ goto error;\r
+ builtins = PyEval_GetBuiltins();\r
+ if (builtins == NULL)\r
+ goto error;\r
+ sorted = PyDict_GetItemString(builtins, "sorted");\r
+ if (sorted == NULL)\r
+ goto error;\r
+ sorted_methods = PyObject_CallFunctionObjArgs(sorted,\r
+ abstract_methods,\r
+ NULL);\r
+ if (sorted_methods == NULL)\r
+ goto error;\r
+ if (comma == NULL) {\r
+ comma = PyString_InternFromString(", ");\r
+ if (comma == NULL)\r
+ goto error;\r
+ }\r
+ joined = PyObject_CallMethod(comma, "join",\r
+ "O", sorted_methods);\r
+ if (joined == NULL)\r
+ goto error;\r
+ joined_str = PyString_AsString(joined);\r
+ if (joined_str == NULL)\r
+ goto error;\r
+\r
+ PyErr_Format(PyExc_TypeError,\r
+ "Can't instantiate abstract class %s "\r
+ "with abstract methods %s",\r
+ type->tp_name,\r
+ joined_str);\r
+ error:\r
+ Py_XDECREF(joined);\r
+ Py_XDECREF(sorted_methods);\r
+ Py_XDECREF(abstract_methods);\r
+ return NULL;\r
+ }\r
+ return type->tp_alloc(type, 0);\r
+}\r
+\r
+static void\r
+object_dealloc(PyObject *self)\r
+{\r
+ Py_TYPE(self)->tp_free(self);\r
+}\r
+\r
+static PyObject *\r
+object_repr(PyObject *self)\r
+{\r
+ PyTypeObject *type;\r
+ PyObject *mod, *name, *rtn;\r
+\r
+ type = Py_TYPE(self);\r
+ mod = type_module(type, NULL);\r
+ if (mod == NULL)\r
+ PyErr_Clear();\r
+ else if (!PyString_Check(mod)) {\r
+ Py_DECREF(mod);\r
+ mod = NULL;\r
+ }\r
+ name = type_name(type, NULL);\r
+ if (name == NULL) {\r
+ Py_XDECREF(mod);\r
+ return NULL;\r
+ }\r
+ if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__"))\r
+ rtn = PyString_FromFormat("<%s.%s object at %p>",\r
+ PyString_AS_STRING(mod),\r
+ PyString_AS_STRING(name),\r
+ self);\r
+ else\r
+ rtn = PyString_FromFormat("<%s object at %p>",\r
+ type->tp_name, self);\r
+ Py_XDECREF(mod);\r
+ Py_DECREF(name);\r
+ return rtn;\r
+}\r
+\r
+static PyObject *\r
+object_str(PyObject *self)\r
+{\r
+ unaryfunc f;\r
+\r
+ f = Py_TYPE(self)->tp_repr;\r
+ if (f == NULL)\r
+ f = object_repr;\r
+ return f(self);\r
+}\r
+\r
+static PyObject *\r
+object_get_class(PyObject *self, void *closure)\r
+{\r
+ Py_INCREF(Py_TYPE(self));\r
+ return (PyObject *)(Py_TYPE(self));\r
+}\r
+\r
+static int\r
+equiv_structs(PyTypeObject *a, PyTypeObject *b)\r
+{\r
+ return a == b ||\r
+ (a != NULL &&\r
+ b != NULL &&\r
+ a->tp_basicsize == b->tp_basicsize &&\r
+ a->tp_itemsize == b->tp_itemsize &&\r
+ a->tp_dictoffset == b->tp_dictoffset &&\r
+ a->tp_weaklistoffset == b->tp_weaklistoffset &&\r
+ ((a->tp_flags & Py_TPFLAGS_HAVE_GC) ==\r
+ (b->tp_flags & Py_TPFLAGS_HAVE_GC)));\r
+}\r
+\r
+static int\r
+same_slots_added(PyTypeObject *a, PyTypeObject *b)\r
+{\r
+ PyTypeObject *base = a->tp_base;\r
+ Py_ssize_t size;\r
+ PyObject *slots_a, *slots_b;\r
+\r
+ assert(base == b->tp_base);\r
+ size = base->tp_basicsize;\r
+ if (a->tp_dictoffset == size && b->tp_dictoffset == size)\r
+ size += sizeof(PyObject *);\r
+ if (a->tp_weaklistoffset == size && b->tp_weaklistoffset == size)\r
+ size += sizeof(PyObject *);\r
+\r
+ /* Check slots compliance */\r
+ slots_a = ((PyHeapTypeObject *)a)->ht_slots;\r
+ slots_b = ((PyHeapTypeObject *)b)->ht_slots;\r
+ if (slots_a && slots_b) {\r
+ if (PyObject_Compare(slots_a, slots_b) != 0)\r
+ return 0;\r
+ size += sizeof(PyObject *) * PyTuple_GET_SIZE(slots_a);\r
+ }\r
+ return size == a->tp_basicsize && size == b->tp_basicsize;\r
+}\r
+\r
+static int\r
+compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, char* attr)\r
+{\r
+ PyTypeObject *newbase, *oldbase;\r
+\r
+ if (newto->tp_dealloc != oldto->tp_dealloc ||\r
+ newto->tp_free != oldto->tp_free)\r
+ {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s assignment: "\r
+ "'%s' deallocator differs from '%s'",\r
+ attr,\r
+ newto->tp_name,\r
+ oldto->tp_name);\r
+ return 0;\r
+ }\r
+ newbase = newto;\r
+ oldbase = oldto;\r
+ while (equiv_structs(newbase, newbase->tp_base))\r
+ newbase = newbase->tp_base;\r
+ while (equiv_structs(oldbase, oldbase->tp_base))\r
+ oldbase = oldbase->tp_base;\r
+ if (newbase != oldbase &&\r
+ (newbase->tp_base != oldbase->tp_base ||\r
+ !same_slots_added(newbase, oldbase))) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s assignment: "\r
+ "'%s' object layout differs from '%s'",\r
+ attr,\r
+ newto->tp_name,\r
+ oldto->tp_name);\r
+ return 0;\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+static int\r
+object_set_class(PyObject *self, PyObject *value, void *closure)\r
+{\r
+ PyTypeObject *oldto = Py_TYPE(self);\r
+ PyTypeObject *newto;\r
+\r
+ if (value == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "can't delete __class__ attribute");\r
+ return -1;\r
+ }\r
+ if (!PyType_Check(value)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__class__ must be set to new-style class, not '%s' object",\r
+ Py_TYPE(value)->tp_name);\r
+ return -1;\r
+ }\r
+ newto = (PyTypeObject *)value;\r
+ if (!(newto->tp_flags & Py_TPFLAGS_HEAPTYPE) ||\r
+ !(oldto->tp_flags & Py_TPFLAGS_HEAPTYPE))\r
+ {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__class__ assignment: only for heap types");\r
+ return -1;\r
+ }\r
+ if (compatible_for_assignment(newto, oldto, "__class__")) {\r
+ Py_INCREF(newto);\r
+ Py_TYPE(self) = newto;\r
+ Py_DECREF(oldto);\r
+ return 0;\r
+ }\r
+ else {\r
+ return -1;\r
+ }\r
+}\r
+\r
+static PyGetSetDef object_getsets[] = {\r
+ {"__class__", object_get_class, object_set_class,\r
+ PyDoc_STR("the object's class")},\r
+ {0}\r
+};\r
+\r
+\r
+/* Stuff to implement __reduce_ex__ for pickle protocols >= 2.\r
+ We fall back to helpers in copy_reg for:\r
+ - pickle protocols < 2\r
+ - calculating the list of slot names (done only once per class)\r
+ - the __newobj__ function (which is used as a token but never called)\r
+*/\r
+\r
+static PyObject *\r
+import_copyreg(void)\r
+{\r
+ static PyObject *copyreg_str;\r
+\r
+ if (!copyreg_str) {\r
+ copyreg_str = PyString_InternFromString("copy_reg");\r
+ if (copyreg_str == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ return PyImport_Import(copyreg_str);\r
+}\r
+\r
+static PyObject *\r
+slotnames(PyObject *cls)\r
+{\r
+ PyObject *clsdict;\r
+ PyObject *copyreg;\r
+ PyObject *slotnames;\r
+\r
+ if (!PyType_Check(cls)) {\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+ }\r
+\r
+ clsdict = ((PyTypeObject *)cls)->tp_dict;\r
+ slotnames = PyDict_GetItemString(clsdict, "__slotnames__");\r
+ if (slotnames != NULL && PyList_Check(slotnames)) {\r
+ Py_INCREF(slotnames);\r
+ return slotnames;\r
+ }\r
+\r
+ copyreg = import_copyreg();\r
+ if (copyreg == NULL)\r
+ return NULL;\r
+\r
+ slotnames = PyObject_CallMethod(copyreg, "_slotnames", "O", cls);\r
+ Py_DECREF(copyreg);\r
+ if (slotnames != NULL &&\r
+ slotnames != Py_None &&\r
+ !PyList_Check(slotnames))\r
+ {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "copy_reg._slotnames didn't return a list or None");\r
+ Py_DECREF(slotnames);\r
+ slotnames = NULL;\r
+ }\r
+\r
+ return slotnames;\r
+}\r
+\r
+static PyObject *\r
+reduce_2(PyObject *obj)\r
+{\r
+ PyObject *cls, *getnewargs;\r
+ PyObject *args = NULL, *args2 = NULL;\r
+ PyObject *getstate = NULL, *state = NULL, *names = NULL;\r
+ PyObject *slots = NULL, *listitems = NULL, *dictitems = NULL;\r
+ PyObject *copyreg = NULL, *newobj = NULL, *res = NULL;\r
+ Py_ssize_t i, n;\r
+\r
+ cls = PyObject_GetAttrString(obj, "__class__");\r
+ if (cls == NULL)\r
+ return NULL;\r
+\r
+ getnewargs = PyObject_GetAttrString(obj, "__getnewargs__");\r
+ if (getnewargs != NULL) {\r
+ args = PyObject_CallObject(getnewargs, NULL);\r
+ Py_DECREF(getnewargs);\r
+ if (args != NULL && !PyTuple_Check(args)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__getnewargs__ should return a tuple, "\r
+ "not '%.200s'", Py_TYPE(args)->tp_name);\r
+ goto end;\r
+ }\r
+ }\r
+ else {\r
+ PyErr_Clear();\r
+ args = PyTuple_New(0);\r
+ }\r
+ if (args == NULL)\r
+ goto end;\r
+\r
+ getstate = PyObject_GetAttrString(obj, "__getstate__");\r
+ if (getstate != NULL) {\r
+ state = PyObject_CallObject(getstate, NULL);\r
+ Py_DECREF(getstate);\r
+ if (state == NULL)\r
+ goto end;\r
+ }\r
+ else {\r
+ PyErr_Clear();\r
+ state = PyObject_GetAttrString(obj, "__dict__");\r
+ if (state == NULL) {\r
+ PyErr_Clear();\r
+ state = Py_None;\r
+ Py_INCREF(state);\r
+ }\r
+ names = slotnames(cls);\r
+ if (names == NULL)\r
+ goto end;\r
+ if (names != Py_None) {\r
+ assert(PyList_Check(names));\r
+ slots = PyDict_New();\r
+ if (slots == NULL)\r
+ goto end;\r
+ n = 0;\r
+ /* Can't pre-compute the list size; the list\r
+ is stored on the class so accessible to other\r
+ threads, which may be run by DECREF */\r
+ for (i = 0; i < PyList_GET_SIZE(names); i++) {\r
+ PyObject *name, *value;\r
+ name = PyList_GET_ITEM(names, i);\r
+ value = PyObject_GetAttr(obj, name);\r
+ if (value == NULL)\r
+ PyErr_Clear();\r
+ else {\r
+ int err = PyDict_SetItem(slots, name,\r
+ value);\r
+ Py_DECREF(value);\r
+ if (err)\r
+ goto end;\r
+ n++;\r
+ }\r
+ }\r
+ if (n) {\r
+ state = Py_BuildValue("(NO)", state, slots);\r
+ if (state == NULL)\r
+ goto end;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!PyList_Check(obj)) {\r
+ listitems = Py_None;\r
+ Py_INCREF(listitems);\r
+ }\r
+ else {\r
+ listitems = PyObject_GetIter(obj);\r
+ if (listitems == NULL)\r
+ goto end;\r
+ }\r
+\r
+ if (!PyDict_Check(obj)) {\r
+ dictitems = Py_None;\r
+ Py_INCREF(dictitems);\r
+ }\r
+ else {\r
+ dictitems = PyObject_CallMethod(obj, "iteritems", "");\r
+ if (dictitems == NULL)\r
+ goto end;\r
+ }\r
+\r
+ copyreg = import_copyreg();\r
+ if (copyreg == NULL)\r
+ goto end;\r
+ newobj = PyObject_GetAttrString(copyreg, "__newobj__");\r
+ if (newobj == NULL)\r
+ goto end;\r
+\r
+ n = PyTuple_GET_SIZE(args);\r
+ args2 = PyTuple_New(n+1);\r
+ if (args2 == NULL)\r
+ goto end;\r
+ PyTuple_SET_ITEM(args2, 0, cls);\r
+ cls = NULL;\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *v = PyTuple_GET_ITEM(args, i);\r
+ Py_INCREF(v);\r
+ PyTuple_SET_ITEM(args2, i+1, v);\r
+ }\r
+\r
+ res = PyTuple_Pack(5, newobj, args2, state, listitems, dictitems);\r
+\r
+ end:\r
+ Py_XDECREF(cls);\r
+ Py_XDECREF(args);\r
+ Py_XDECREF(args2);\r
+ Py_XDECREF(slots);\r
+ Py_XDECREF(state);\r
+ Py_XDECREF(names);\r
+ Py_XDECREF(listitems);\r
+ Py_XDECREF(dictitems);\r
+ Py_XDECREF(copyreg);\r
+ Py_XDECREF(newobj);\r
+ return res;\r
+}\r
+\r
+/*\r
+ * There were two problems when object.__reduce__ and object.__reduce_ex__\r
+ * were implemented in the same function:\r
+ * - trying to pickle an object with a custom __reduce__ method that\r
+ * fell back to object.__reduce__ in certain circumstances led to\r
+ * infinite recursion at Python level and eventual RuntimeError.\r
+ * - Pickling objects that lied about their type by overwriting the\r
+ * __class__ descriptor could lead to infinite recursion at C level\r
+ * and eventual segfault.\r
+ *\r
+ * Because of backwards compatibility, the two methods still have to\r
+ * behave in the same way, even if this is not required by the pickle\r
+ * protocol. This common functionality was moved to the _common_reduce\r
+ * function.\r
+ */\r
+static PyObject *\r
+_common_reduce(PyObject *self, int proto)\r
+{\r
+ PyObject *copyreg, *res;\r
+\r
+ if (proto >= 2)\r
+ return reduce_2(self);\r
+\r
+ copyreg = import_copyreg();\r
+ if (!copyreg)\r
+ return NULL;\r
+\r
+ res = PyEval_CallMethod(copyreg, "_reduce_ex", "(Oi)", self, proto);\r
+ Py_DECREF(copyreg);\r
+\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+object_reduce(PyObject *self, PyObject *args)\r
+{\r
+ int proto = 0;\r
+\r
+ if (!PyArg_ParseTuple(args, "|i:__reduce__", &proto))\r
+ return NULL;\r
+\r
+ return _common_reduce(self, proto);\r
+}\r
+\r
+static PyObject *\r
+object_reduce_ex(PyObject *self, PyObject *args)\r
+{\r
+ PyObject *reduce, *res;\r
+ int proto = 0;\r
+\r
+ if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto))\r
+ return NULL;\r
+\r
+ reduce = PyObject_GetAttrString(self, "__reduce__");\r
+ if (reduce == NULL)\r
+ PyErr_Clear();\r
+ else {\r
+ PyObject *cls, *clsreduce, *objreduce;\r
+ int override;\r
+ cls = PyObject_GetAttrString(self, "__class__");\r
+ if (cls == NULL) {\r
+ Py_DECREF(reduce);\r
+ return NULL;\r
+ }\r
+ clsreduce = PyObject_GetAttrString(cls, "__reduce__");\r
+ Py_DECREF(cls);\r
+ if (clsreduce == NULL) {\r
+ Py_DECREF(reduce);\r
+ return NULL;\r
+ }\r
+ objreduce = PyDict_GetItemString(PyBaseObject_Type.tp_dict,\r
+ "__reduce__");\r
+ override = (clsreduce != objreduce);\r
+ Py_DECREF(clsreduce);\r
+ if (override) {\r
+ res = PyObject_CallObject(reduce, NULL);\r
+ Py_DECREF(reduce);\r
+ return res;\r
+ }\r
+ else\r
+ Py_DECREF(reduce);\r
+ }\r
+\r
+ return _common_reduce(self, proto);\r
+}\r
+\r
+static PyObject *\r
+object_subclasshook(PyObject *cls, PyObject *args)\r
+{\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+}\r
+\r
+PyDoc_STRVAR(object_subclasshook_doc,\r
+"Abstract classes can override this to customize issubclass().\n"\r
+"\n"\r
+"This is invoked early on by abc.ABCMeta.__subclasscheck__().\n"\r
+"It should return True, False or NotImplemented. If it returns\n"\r
+"NotImplemented, the normal algorithm is used. Otherwise, it\n"\r
+"overrides the normal algorithm (and the outcome is cached).\n");\r
+\r
+/*\r
+ from PEP 3101, this code implements:\r
+\r
+ class object:\r
+ def __format__(self, format_spec):\r
+ if isinstance(format_spec, str):\r
+ return format(str(self), format_spec)\r
+ elif isinstance(format_spec, unicode):\r
+ return format(unicode(self), format_spec)\r
+*/\r
+static PyObject *\r
+object_format(PyObject *self, PyObject *args)\r
+{\r
+ PyObject *format_spec;\r
+ PyObject *self_as_str = NULL;\r
+ PyObject *result = NULL;\r
+ Py_ssize_t format_len;\r
+\r
+ if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))\r
+ return NULL;\r
+#ifdef Py_USING_UNICODE\r
+ if (PyUnicode_Check(format_spec)) {\r
+ format_len = PyUnicode_GET_SIZE(format_spec);\r
+ self_as_str = PyObject_Unicode(self);\r
+ } else if (PyString_Check(format_spec)) {\r
+#else\r
+ if (PyString_Check(format_spec)) {\r
+#endif\r
+ format_len = PyString_GET_SIZE(format_spec);\r
+ self_as_str = PyObject_Str(self);\r
+ } else {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "argument to __format__ must be unicode or str");\r
+ return NULL;\r
+ }\r
+\r
+ if (self_as_str != NULL) {\r
+ /* Issue 7994: If we're converting to a string, we\r
+ should reject format specifications */\r
+ if (format_len > 0) {\r
+ if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,\r
+ "object.__format__ with a non-empty format "\r
+ "string is deprecated", 1) < 0) {\r
+ goto done;\r
+ }\r
+ /* Eventually this will become an error:\r
+ PyErr_Format(PyExc_TypeError,\r
+ "non-empty format string passed to object.__format__");\r
+ goto done;\r
+ */\r
+ }\r
+ result = PyObject_Format(self_as_str, format_spec);\r
+ }\r
+\r
+done:\r
+ Py_XDECREF(self_as_str);\r
+\r
+ return result;\r
+}\r
+\r
+static PyObject *\r
+object_sizeof(PyObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t res, isize;\r
+\r
+ res = 0;\r
+ isize = self->ob_type->tp_itemsize;\r
+ if (isize > 0)\r
+ res = Py_SIZE(self) * isize;\r
+ res += self->ob_type->tp_basicsize;\r
+\r
+ return PyInt_FromSsize_t(res);\r
+}\r
+\r
+static PyMethodDef object_methods[] = {\r
+ {"__reduce_ex__", object_reduce_ex, METH_VARARGS,\r
+ PyDoc_STR("helper for pickle")},\r
+ {"__reduce__", object_reduce, METH_VARARGS,\r
+ PyDoc_STR("helper for pickle")},\r
+ {"__subclasshook__", object_subclasshook, METH_CLASS | METH_VARARGS,\r
+ object_subclasshook_doc},\r
+ {"__format__", object_format, METH_VARARGS,\r
+ PyDoc_STR("default object formatter")},\r
+ {"__sizeof__", object_sizeof, METH_NOARGS,\r
+ PyDoc_STR("__sizeof__() -> int\nsize of object in memory, in bytes")},\r
+ {0}\r
+};\r
+\r
+\r
+PyTypeObject PyBaseObject_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "object", /* tp_name */\r
+ sizeof(PyObject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ object_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ object_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ (hashfunc)_Py_HashPointer, /* tp_hash */\r
+ 0, /* tp_call */\r
+ object_str, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ PyObject_GenericSetAttr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ PyDoc_STR("The most base type"), /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ object_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ object_getsets, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ object_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ object_new, /* tp_new */\r
+ PyObject_Del, /* tp_free */\r
+};\r
+\r
+\r
+/* Initialize the __dict__ in a type object */\r
+\r
+static int\r
+add_methods(PyTypeObject *type, PyMethodDef *meth)\r
+{\r
+ PyObject *dict = type->tp_dict;\r
+\r
+ for (; meth->ml_name != NULL; meth++) {\r
+ PyObject *descr;\r
+ int err;\r
+ if (PyDict_GetItemString(dict, meth->ml_name) &&\r
+ !(meth->ml_flags & METH_COEXIST))\r
+ continue;\r
+ if (meth->ml_flags & METH_CLASS) {\r
+ if (meth->ml_flags & METH_STATIC) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "method cannot be both class and static");\r
+ return -1;\r
+ }\r
+ descr = PyDescr_NewClassMethod(type, meth);\r
+ }\r
+ else if (meth->ml_flags & METH_STATIC) {\r
+ PyObject *cfunc = PyCFunction_New(meth, NULL);\r
+ if (cfunc == NULL)\r
+ return -1;\r
+ descr = PyStaticMethod_New(cfunc);\r
+ Py_DECREF(cfunc);\r
+ }\r
+ else {\r
+ descr = PyDescr_NewMethod(type, meth);\r
+ }\r
+ if (descr == NULL)\r
+ return -1;\r
+ err = PyDict_SetItemString(dict, meth->ml_name, descr);\r
+ Py_DECREF(descr);\r
+ if (err < 0)\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+add_members(PyTypeObject *type, PyMemberDef *memb)\r
+{\r
+ PyObject *dict = type->tp_dict;\r
+\r
+ for (; memb->name != NULL; memb++) {\r
+ PyObject *descr;\r
+ if (PyDict_GetItemString(dict, memb->name))\r
+ continue;\r
+ descr = PyDescr_NewMember(type, memb);\r
+ if (descr == NULL)\r
+ return -1;\r
+ if (PyDict_SetItemString(dict, memb->name, descr) < 0)\r
+ return -1;\r
+ Py_DECREF(descr);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int\r
+add_getset(PyTypeObject *type, PyGetSetDef *gsp)\r
+{\r
+ PyObject *dict = type->tp_dict;\r
+\r
+ for (; gsp->name != NULL; gsp++) {\r
+ PyObject *descr;\r
+ if (PyDict_GetItemString(dict, gsp->name))\r
+ continue;\r
+ descr = PyDescr_NewGetSet(type, gsp);\r
+\r
+ if (descr == NULL)\r
+ return -1;\r
+ if (PyDict_SetItemString(dict, gsp->name, descr) < 0)\r
+ return -1;\r
+ Py_DECREF(descr);\r
+ }\r
+ return 0;\r
+}\r
+\r
+#define BUFFER_FLAGS (Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER)\r
+\r
+static void\r
+inherit_special(PyTypeObject *type, PyTypeObject *base)\r
+{\r
+ Py_ssize_t oldsize, newsize;\r
+\r
+ /* Special flag magic */\r
+ if (!type->tp_as_buffer && base->tp_as_buffer) {\r
+ type->tp_flags &= ~BUFFER_FLAGS;\r
+ type->tp_flags |=\r
+ base->tp_flags & BUFFER_FLAGS;\r
+ }\r
+ if (!type->tp_as_sequence && base->tp_as_sequence) {\r
+ type->tp_flags &= ~Py_TPFLAGS_HAVE_SEQUENCE_IN;\r
+ type->tp_flags |= base->tp_flags & Py_TPFLAGS_HAVE_SEQUENCE_IN;\r
+ }\r
+ if ((type->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS) !=\r
+ (base->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS)) {\r
+ if ((!type->tp_as_number && base->tp_as_number) ||\r
+ (!type->tp_as_sequence && base->tp_as_sequence)) {\r
+ type->tp_flags &= ~Py_TPFLAGS_HAVE_INPLACEOPS;\r
+ if (!type->tp_as_number && !type->tp_as_sequence) {\r
+ type->tp_flags |= base->tp_flags &\r
+ Py_TPFLAGS_HAVE_INPLACEOPS;\r
+ }\r
+ }\r
+ /* Wow */\r
+ }\r
+ if (!type->tp_as_number && base->tp_as_number) {\r
+ type->tp_flags &= ~Py_TPFLAGS_CHECKTYPES;\r
+ type->tp_flags |= base->tp_flags & Py_TPFLAGS_CHECKTYPES;\r
+ }\r
+\r
+ /* Copying basicsize is connected to the GC flags */\r
+ oldsize = base->tp_basicsize;\r
+ newsize = type->tp_basicsize ? type->tp_basicsize : oldsize;\r
+ if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC) &&\r
+ (base->tp_flags & Py_TPFLAGS_HAVE_GC) &&\r
+ (type->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE/*GC slots exist*/) &&\r
+ (!type->tp_traverse && !type->tp_clear)) {\r
+ type->tp_flags |= Py_TPFLAGS_HAVE_GC;\r
+ if (type->tp_traverse == NULL)\r
+ type->tp_traverse = base->tp_traverse;\r
+ if (type->tp_clear == NULL)\r
+ type->tp_clear = base->tp_clear;\r
+ }\r
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) {\r
+ /* The condition below could use some explanation.\r
+ It appears that tp_new is not inherited for static types\r
+ whose base class is 'object'; this seems to be a precaution\r
+ so that old extension types don't suddenly become\r
+ callable (object.__new__ wouldn't insure the invariants\r
+ that the extension type's own factory function ensures).\r
+ Heap types, of course, are under our control, so they do\r
+ inherit tp_new; static extension types that specify some\r
+ other built-in type as the default are considered\r
+ new-style-aware so they also inherit object.__new__. */\r
+ if (base != &PyBaseObject_Type ||\r
+ (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {\r
+ if (type->tp_new == NULL)\r
+ type->tp_new = base->tp_new;\r
+ }\r
+ }\r
+ type->tp_basicsize = newsize;\r
+\r
+ /* Copy other non-function slots */\r
+\r
+#undef COPYVAL\r
+#define COPYVAL(SLOT) \\r
+ if (type->SLOT == 0) type->SLOT = base->SLOT\r
+\r
+ COPYVAL(tp_itemsize);\r
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_WEAKREFS) {\r
+ COPYVAL(tp_weaklistoffset);\r
+ }\r
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) {\r
+ COPYVAL(tp_dictoffset);\r
+ }\r
+\r
+ /* Setup fast subclass flags */\r
+ if (PyType_IsSubtype(base, (PyTypeObject*)PyExc_BaseException))\r
+ type->tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS;\r
+ else if (PyType_IsSubtype(base, &PyType_Type))\r
+ type->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS;\r
+ else if (PyType_IsSubtype(base, &PyInt_Type))\r
+ type->tp_flags |= Py_TPFLAGS_INT_SUBCLASS;\r
+ else if (PyType_IsSubtype(base, &PyLong_Type))\r
+ type->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;\r
+ else if (PyType_IsSubtype(base, &PyString_Type))\r
+ type->tp_flags |= Py_TPFLAGS_STRING_SUBCLASS;\r
+#ifdef Py_USING_UNICODE\r
+ else if (PyType_IsSubtype(base, &PyUnicode_Type))\r
+ type->tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS;\r
+#endif\r
+ else if (PyType_IsSubtype(base, &PyTuple_Type))\r
+ type->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS;\r
+ else if (PyType_IsSubtype(base, &PyList_Type))\r
+ type->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS;\r
+ else if (PyType_IsSubtype(base, &PyDict_Type))\r
+ type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;\r
+}\r
+\r
+static int\r
+overrides_name(PyTypeObject *type, char *name)\r
+{\r
+ PyObject *dict = type->tp_dict;\r
+\r
+ assert(dict != NULL);\r
+ if (PyDict_GetItemString(dict, name) != NULL) {\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+#define OVERRIDES_HASH(x) overrides_name(x, "__hash__")\r
+#define OVERRIDES_EQ(x) overrides_name(x, "__eq__")\r
+\r
+static void\r
+inherit_slots(PyTypeObject *type, PyTypeObject *base)\r
+{\r
+ PyTypeObject *basebase;\r
+\r
+#undef SLOTDEFINED\r
+#undef COPYSLOT\r
+#undef COPYNUM\r
+#undef COPYSEQ\r
+#undef COPYMAP\r
+#undef COPYBUF\r
+\r
+#define SLOTDEFINED(SLOT) \\r
+ (base->SLOT != 0 && \\r
+ (basebase == NULL || base->SLOT != basebase->SLOT))\r
+\r
+#define COPYSLOT(SLOT) \\r
+ if (!type->SLOT && SLOTDEFINED(SLOT)) type->SLOT = base->SLOT\r
+\r
+#define COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT)\r
+#define COPYSEQ(SLOT) COPYSLOT(tp_as_sequence->SLOT)\r
+#define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT)\r
+#define COPYBUF(SLOT) COPYSLOT(tp_as_buffer->SLOT)\r
+\r
+ /* This won't inherit indirect slots (from tp_as_number etc.)\r
+ if type doesn't provide the space. */\r
+\r
+ if (type->tp_as_number != NULL && base->tp_as_number != NULL) {\r
+ basebase = base->tp_base;\r
+ if (basebase->tp_as_number == NULL)\r
+ basebase = NULL;\r
+ COPYNUM(nb_add);\r
+ COPYNUM(nb_subtract);\r
+ COPYNUM(nb_multiply);\r
+ COPYNUM(nb_divide);\r
+ COPYNUM(nb_remainder);\r
+ COPYNUM(nb_divmod);\r
+ COPYNUM(nb_power);\r
+ COPYNUM(nb_negative);\r
+ COPYNUM(nb_positive);\r
+ COPYNUM(nb_absolute);\r
+ COPYNUM(nb_nonzero);\r
+ COPYNUM(nb_invert);\r
+ COPYNUM(nb_lshift);\r
+ COPYNUM(nb_rshift);\r
+ COPYNUM(nb_and);\r
+ COPYNUM(nb_xor);\r
+ COPYNUM(nb_or);\r
+ COPYNUM(nb_coerce);\r
+ COPYNUM(nb_int);\r
+ COPYNUM(nb_long);\r
+ COPYNUM(nb_float);\r
+ COPYNUM(nb_oct);\r
+ COPYNUM(nb_hex);\r
+ COPYNUM(nb_inplace_add);\r
+ COPYNUM(nb_inplace_subtract);\r
+ COPYNUM(nb_inplace_multiply);\r
+ COPYNUM(nb_inplace_divide);\r
+ COPYNUM(nb_inplace_remainder);\r
+ COPYNUM(nb_inplace_power);\r
+ COPYNUM(nb_inplace_lshift);\r
+ COPYNUM(nb_inplace_rshift);\r
+ COPYNUM(nb_inplace_and);\r
+ COPYNUM(nb_inplace_xor);\r
+ COPYNUM(nb_inplace_or);\r
+ if (base->tp_flags & Py_TPFLAGS_CHECKTYPES) {\r
+ COPYNUM(nb_true_divide);\r
+ COPYNUM(nb_floor_divide);\r
+ COPYNUM(nb_inplace_true_divide);\r
+ COPYNUM(nb_inplace_floor_divide);\r
+ }\r
+ if (base->tp_flags & Py_TPFLAGS_HAVE_INDEX) {\r
+ COPYNUM(nb_index);\r
+ }\r
+ }\r
+\r
+ if (type->tp_as_sequence != NULL && base->tp_as_sequence != NULL) {\r
+ basebase = base->tp_base;\r
+ if (basebase->tp_as_sequence == NULL)\r
+ basebase = NULL;\r
+ COPYSEQ(sq_length);\r
+ COPYSEQ(sq_concat);\r
+ COPYSEQ(sq_repeat);\r
+ COPYSEQ(sq_item);\r
+ COPYSEQ(sq_slice);\r
+ COPYSEQ(sq_ass_item);\r
+ COPYSEQ(sq_ass_slice);\r
+ COPYSEQ(sq_contains);\r
+ COPYSEQ(sq_inplace_concat);\r
+ COPYSEQ(sq_inplace_repeat);\r
+ }\r
+\r
+ if (type->tp_as_mapping != NULL && base->tp_as_mapping != NULL) {\r
+ basebase = base->tp_base;\r
+ if (basebase->tp_as_mapping == NULL)\r
+ basebase = NULL;\r
+ COPYMAP(mp_length);\r
+ COPYMAP(mp_subscript);\r
+ COPYMAP(mp_ass_subscript);\r
+ }\r
+\r
+ if (type->tp_as_buffer != NULL && base->tp_as_buffer != NULL) {\r
+ basebase = base->tp_base;\r
+ if (basebase->tp_as_buffer == NULL)\r
+ basebase = NULL;\r
+ COPYBUF(bf_getreadbuffer);\r
+ COPYBUF(bf_getwritebuffer);\r
+ COPYBUF(bf_getsegcount);\r
+ COPYBUF(bf_getcharbuffer);\r
+ COPYBUF(bf_getbuffer);\r
+ COPYBUF(bf_releasebuffer);\r
+ }\r
+\r
+ basebase = base->tp_base;\r
+\r
+ COPYSLOT(tp_dealloc);\r
+ COPYSLOT(tp_print);\r
+ if (type->tp_getattr == NULL && type->tp_getattro == NULL) {\r
+ type->tp_getattr = base->tp_getattr;\r
+ type->tp_getattro = base->tp_getattro;\r
+ }\r
+ if (type->tp_setattr == NULL && type->tp_setattro == NULL) {\r
+ type->tp_setattr = base->tp_setattr;\r
+ type->tp_setattro = base->tp_setattro;\r
+ }\r
+ /* tp_compare see tp_richcompare */\r
+ COPYSLOT(tp_repr);\r
+ /* tp_hash see tp_richcompare */\r
+ COPYSLOT(tp_call);\r
+ COPYSLOT(tp_str);\r
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) {\r
+ if (type->tp_compare == NULL &&\r
+ type->tp_richcompare == NULL &&\r
+ type->tp_hash == NULL)\r
+ {\r
+ type->tp_compare = base->tp_compare;\r
+ type->tp_richcompare = base->tp_richcompare;\r
+ type->tp_hash = base->tp_hash;\r
+ /* Check for changes to inherited methods in Py3k*/\r
+ if (Py_Py3kWarningFlag) {\r
+ if (base->tp_hash &&\r
+ (base->tp_hash != PyObject_HashNotImplemented) &&\r
+ !OVERRIDES_HASH(type)) {\r
+ if (OVERRIDES_EQ(type)) {\r
+ if (PyErr_WarnPy3k("Overriding "\r
+ "__eq__ blocks inheritance "\r
+ "of __hash__ in 3.x",\r
+ 1) < 0)\r
+ /* XXX This isn't right. If the warning is turned\r
+ into an exception, we should be communicating\r
+ the error back to the caller, but figuring out\r
+ how to clean up in that case is tricky. See\r
+ issue 8627 for more. */\r
+ PyErr_Clear();\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ COPYSLOT(tp_compare);\r
+ }\r
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_ITER) {\r
+ COPYSLOT(tp_iter);\r
+ COPYSLOT(tp_iternext);\r
+ }\r
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) {\r
+ COPYSLOT(tp_descr_get);\r
+ COPYSLOT(tp_descr_set);\r
+ COPYSLOT(tp_dictoffset);\r
+ COPYSLOT(tp_init);\r
+ COPYSLOT(tp_alloc);\r
+ COPYSLOT(tp_is_gc);\r
+ if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) ==\r
+ (base->tp_flags & Py_TPFLAGS_HAVE_GC)) {\r
+ /* They agree about gc. */\r
+ COPYSLOT(tp_free);\r
+ }\r
+ else if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) &&\r
+ type->tp_free == NULL &&\r
+ base->tp_free == _PyObject_Del) {\r
+ /* A bit of magic to plug in the correct default\r
+ * tp_free function when a derived class adds gc,\r
+ * didn't define tp_free, and the base uses the\r
+ * default non-gc tp_free.\r
+ */\r
+ type->tp_free = PyObject_GC_Del;\r
+ }\r
+ /* else they didn't agree about gc, and there isn't something\r
+ * obvious to be done -- the type is on its own.\r
+ */\r
+ }\r
+}\r
+\r
+static int add_operators(PyTypeObject *);\r
+\r
+int\r
+PyType_Ready(PyTypeObject *type)\r
+{\r
+ PyObject *dict, *bases;\r
+ PyTypeObject *base;\r
+ Py_ssize_t i, n;\r
+\r
+ if (type->tp_flags & Py_TPFLAGS_READY) {\r
+ assert(type->tp_dict != NULL);\r
+ return 0;\r
+ }\r
+ assert((type->tp_flags & Py_TPFLAGS_READYING) == 0);\r
+\r
+ type->tp_flags |= Py_TPFLAGS_READYING;\r
+\r
+#ifdef Py_TRACE_REFS\r
+ /* PyType_Ready is the closest thing we have to a choke point\r
+ * for type objects, so is the best place I can think of to try\r
+ * to get type objects into the doubly-linked list of all objects.\r
+ * Still, not all type objects go thru PyType_Ready.\r
+ */\r
+ _Py_AddToAllObjects((PyObject *)type, 0);\r
+#endif\r
+\r
+ /* Initialize tp_base (defaults to BaseObject unless that's us) */\r
+ base = type->tp_base;\r
+ if (base == NULL && type != &PyBaseObject_Type) {\r
+ base = type->tp_base = &PyBaseObject_Type;\r
+ Py_INCREF(base);\r
+ }\r
+\r
+ /* Now the only way base can still be NULL is if type is\r
+ * &PyBaseObject_Type.\r
+ */\r
+\r
+ /* Initialize the base class */\r
+ if (base && base->tp_dict == NULL) {\r
+ if (PyType_Ready(base) < 0)\r
+ goto error;\r
+ }\r
+\r
+ /* Initialize ob_type if NULL. This means extensions that want to be\r
+ compilable separately on Windows can call PyType_Ready() instead of\r
+ initializing the ob_type field of their type objects. */\r
+ /* The test for base != NULL is really unnecessary, since base is only\r
+ NULL when type is &PyBaseObject_Type, and we know its ob_type is\r
+ not NULL (it's initialized to &PyType_Type). But coverity doesn't\r
+ know that. */\r
+ if (Py_TYPE(type) == NULL && base != NULL)\r
+ Py_TYPE(type) = Py_TYPE(base);\r
+\r
+ /* Initialize tp_bases */\r
+ bases = type->tp_bases;\r
+ if (bases == NULL) {\r
+ if (base == NULL)\r
+ bases = PyTuple_New(0);\r
+ else\r
+ bases = PyTuple_Pack(1, base);\r
+ if (bases == NULL)\r
+ goto error;\r
+ type->tp_bases = bases;\r
+ }\r
+\r
+ /* Initialize tp_dict */\r
+ dict = type->tp_dict;\r
+ if (dict == NULL) {\r
+ dict = PyDict_New();\r
+ if (dict == NULL)\r
+ goto error;\r
+ type->tp_dict = dict;\r
+ }\r
+\r
+ /* Add type-specific descriptors to tp_dict */\r
+ if (add_operators(type) < 0)\r
+ goto error;\r
+ if (type->tp_methods != NULL) {\r
+ if (add_methods(type, type->tp_methods) < 0)\r
+ goto error;\r
+ }\r
+ if (type->tp_members != NULL) {\r
+ if (add_members(type, type->tp_members) < 0)\r
+ goto error;\r
+ }\r
+ if (type->tp_getset != NULL) {\r
+ if (add_getset(type, type->tp_getset) < 0)\r
+ goto error;\r
+ }\r
+\r
+ /* Calculate method resolution order */\r
+ if (mro_internal(type) < 0) {\r
+ goto error;\r
+ }\r
+\r
+ /* Inherit special flags from dominant base */\r
+ if (type->tp_base != NULL)\r
+ inherit_special(type, type->tp_base);\r
+\r
+ /* Initialize tp_dict properly */\r
+ bases = type->tp_mro;\r
+ assert(bases != NULL);\r
+ assert(PyTuple_Check(bases));\r
+ n = PyTuple_GET_SIZE(bases);\r
+ for (i = 1; i < n; i++) {\r
+ PyObject *b = PyTuple_GET_ITEM(bases, i);\r
+ if (PyType_Check(b))\r
+ inherit_slots(type, (PyTypeObject *)b);\r
+ }\r
+\r
+ /* All bases of statically allocated type should be statically allocated */\r
+ if (Py_Py3kWarningFlag && !(type->tp_flags & Py_TPFLAGS_HEAPTYPE))\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *b = PyTuple_GET_ITEM(bases, i);\r
+ if (PyType_Check(b) &&\r
+ (((PyTypeObject *)b)->tp_flags & Py_TPFLAGS_HEAPTYPE)) {\r
+ char buf[300];\r
+ PyOS_snprintf(buf, sizeof(buf),\r
+ "type '%.100s' is not dynamically allocated but "\r
+ "its base type '%.100s' is dynamically allocated",\r
+ type->tp_name, ((PyTypeObject *)b)->tp_name);\r
+ if (PyErr_WarnPy3k(buf, 1) < 0)\r
+ goto error;\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* Sanity check for tp_free. */\r
+ if (PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) &&\r
+ (type->tp_free == NULL || type->tp_free == PyObject_Del)) {\r
+ /* This base class needs to call tp_free, but doesn't have\r
+ * one, or its tp_free is for non-gc'ed objects.\r
+ */\r
+ PyErr_Format(PyExc_TypeError, "type '%.100s' participates in "\r
+ "gc and is a base type but has inappropriate "\r
+ "tp_free slot",\r
+ type->tp_name);\r
+ goto error;\r
+ }\r
+\r
+ /* if the type dictionary doesn't contain a __doc__, set it from\r
+ the tp_doc slot.\r
+ */\r
+ if (PyDict_GetItemString(type->tp_dict, "__doc__") == NULL) {\r
+ if (type->tp_doc != NULL) {\r
+ PyObject *doc = PyString_FromString(type->tp_doc);\r
+ if (doc == NULL)\r
+ goto error;\r
+ PyDict_SetItemString(type->tp_dict, "__doc__", doc);\r
+ Py_DECREF(doc);\r
+ } else {\r
+ PyDict_SetItemString(type->tp_dict,\r
+ "__doc__", Py_None);\r
+ }\r
+ }\r
+\r
+ /* Some more special stuff */\r
+ base = type->tp_base;\r
+ if (base != NULL) {\r
+ if (type->tp_as_number == NULL)\r
+ type->tp_as_number = base->tp_as_number;\r
+ if (type->tp_as_sequence == NULL)\r
+ type->tp_as_sequence = base->tp_as_sequence;\r
+ if (type->tp_as_mapping == NULL)\r
+ type->tp_as_mapping = base->tp_as_mapping;\r
+ if (type->tp_as_buffer == NULL)\r
+ type->tp_as_buffer = base->tp_as_buffer;\r
+ }\r
+\r
+ /* Link into each base class's list of subclasses */\r
+ bases = type->tp_bases;\r
+ n = PyTuple_GET_SIZE(bases);\r
+ for (i = 0; i < n; i++) {\r
+ PyObject *b = PyTuple_GET_ITEM(bases, i);\r
+ if (PyType_Check(b) &&\r
+ add_subclass((PyTypeObject *)b, type) < 0)\r
+ goto error;\r
+ }\r
+\r
+ /* All done -- set the ready flag */\r
+ assert(type->tp_dict != NULL);\r
+ type->tp_flags =\r
+ (type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY;\r
+ return 0;\r
+\r
+ error:\r
+ type->tp_flags &= ~Py_TPFLAGS_READYING;\r
+ return -1;\r
+}\r
+\r
+static int\r
+add_subclass(PyTypeObject *base, PyTypeObject *type)\r
+{\r
+ Py_ssize_t i;\r
+ int result;\r
+ PyObject *list, *ref, *newobj;\r
+\r
+ list = base->tp_subclasses;\r
+ if (list == NULL) {\r
+ base->tp_subclasses = list = PyList_New(0);\r
+ if (list == NULL)\r
+ return -1;\r
+ }\r
+ assert(PyList_Check(list));\r
+ newobj = PyWeakref_NewRef((PyObject *)type, NULL);\r
+ i = PyList_GET_SIZE(list);\r
+ while (--i >= 0) {\r
+ ref = PyList_GET_ITEM(list, i);\r
+ assert(PyWeakref_CheckRef(ref));\r
+ if (PyWeakref_GET_OBJECT(ref) == Py_None)\r
+ return PyList_SetItem(list, i, newobj);\r
+ }\r
+ result = PyList_Append(list, newobj);\r
+ Py_DECREF(newobj);\r
+ return result;\r
+}\r
+\r
+static void\r
+remove_subclass(PyTypeObject *base, PyTypeObject *type)\r
+{\r
+ Py_ssize_t i;\r
+ PyObject *list, *ref;\r
+\r
+ list = base->tp_subclasses;\r
+ if (list == NULL) {\r
+ return;\r
+ }\r
+ assert(PyList_Check(list));\r
+ i = PyList_GET_SIZE(list);\r
+ while (--i >= 0) {\r
+ ref = PyList_GET_ITEM(list, i);\r
+ assert(PyWeakref_CheckRef(ref));\r
+ if (PyWeakref_GET_OBJECT(ref) == (PyObject*)type) {\r
+ /* this can't fail, right? */\r
+ PySequence_DelItem(list, i);\r
+ return;\r
+ }\r
+ }\r
+}\r
+\r
+static int\r
+check_num_args(PyObject *ob, int n)\r
+{\r
+ if (!PyTuple_CheckExact(ob)) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "PyArg_UnpackTuple() argument list is not a tuple");\r
+ return 0;\r
+ }\r
+ if (n == PyTuple_GET_SIZE(ob))\r
+ return 1;\r
+ PyErr_Format(\r
+ PyExc_TypeError,\r
+ "expected %d arguments, got %zd", n, PyTuple_GET_SIZE(ob));\r
+ return 0;\r
+}\r
+\r
+/* Generic wrappers for overloadable 'operators' such as __getitem__ */\r
+\r
+/* There's a wrapper *function* for each distinct function typedef used\r
+ for type object slots (e.g. binaryfunc, ternaryfunc, etc.). There's a\r
+ wrapper *table* for each distinct operation (e.g. __len__, __add__).\r
+ Most tables have only one entry; the tables for binary operators have two\r
+ entries, one regular and one with reversed arguments. */\r
+\r
+static PyObject *\r
+wrap_lenfunc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ lenfunc func = (lenfunc)wrapped;\r
+ Py_ssize_t res;\r
+\r
+ if (!check_num_args(args, 0))\r
+ return NULL;\r
+ res = (*func)(self);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ return PyInt_FromLong((long)res);\r
+}\r
+\r
+static PyObject *\r
+wrap_inquirypred(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ inquiry func = (inquiry)wrapped;\r
+ int res;\r
+\r
+ if (!check_num_args(args, 0))\r
+ return NULL;\r
+ res = (*func)(self);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ return PyBool_FromLong((long)res);\r
+}\r
+\r
+static PyObject *\r
+wrap_binaryfunc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ binaryfunc func = (binaryfunc)wrapped;\r
+ PyObject *other;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ other = PyTuple_GET_ITEM(args, 0);\r
+ return (*func)(self, other);\r
+}\r
+\r
+static PyObject *\r
+wrap_binaryfunc_l(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ binaryfunc func = (binaryfunc)wrapped;\r
+ PyObject *other;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ other = PyTuple_GET_ITEM(args, 0);\r
+ if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&\r
+ !PyType_IsSubtype(other->ob_type, self->ob_type)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ return (*func)(self, other);\r
+}\r
+\r
+static PyObject *\r
+wrap_binaryfunc_r(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ binaryfunc func = (binaryfunc)wrapped;\r
+ PyObject *other;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ other = PyTuple_GET_ITEM(args, 0);\r
+ if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&\r
+ !PyType_IsSubtype(other->ob_type, self->ob_type)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ return (*func)(other, self);\r
+}\r
+\r
+static PyObject *\r
+wrap_coercefunc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ coercion func = (coercion)wrapped;\r
+ PyObject *other, *res;\r
+ int ok;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ other = PyTuple_GET_ITEM(args, 0);\r
+ ok = func(&self, &other);\r
+ if (ok < 0)\r
+ return NULL;\r
+ if (ok > 0) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ res = PyTuple_New(2);\r
+ if (res == NULL) {\r
+ Py_DECREF(self);\r
+ Py_DECREF(other);\r
+ return NULL;\r
+ }\r
+ PyTuple_SET_ITEM(res, 0, self);\r
+ PyTuple_SET_ITEM(res, 1, other);\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+wrap_ternaryfunc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ ternaryfunc func = (ternaryfunc)wrapped;\r
+ PyObject *other;\r
+ PyObject *third = Py_None;\r
+\r
+ /* Note: This wrapper only works for __pow__() */\r
+\r
+ if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third))\r
+ return NULL;\r
+ return (*func)(self, other, third);\r
+}\r
+\r
+static PyObject *\r
+wrap_ternaryfunc_r(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ ternaryfunc func = (ternaryfunc)wrapped;\r
+ PyObject *other;\r
+ PyObject *third = Py_None;\r
+\r
+ /* Note: This wrapper only works for __pow__() */\r
+\r
+ if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third))\r
+ return NULL;\r
+ return (*func)(other, self, third);\r
+}\r
+\r
+static PyObject *\r
+wrap_unaryfunc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ unaryfunc func = (unaryfunc)wrapped;\r
+\r
+ if (!check_num_args(args, 0))\r
+ return NULL;\r
+ return (*func)(self);\r
+}\r
+\r
+static PyObject *\r
+wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ ssizeargfunc func = (ssizeargfunc)wrapped;\r
+ PyObject* o;\r
+ Py_ssize_t i;\r
+\r
+ if (!PyArg_UnpackTuple(args, "", 1, 1, &o))\r
+ return NULL;\r
+ i = PyNumber_AsSsize_t(o, PyExc_OverflowError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ return (*func)(self, i);\r
+}\r
+\r
+static Py_ssize_t\r
+getindex(PyObject *self, PyObject *arg)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ i = PyNumber_AsSsize_t(arg, PyExc_OverflowError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return -1;\r
+ if (i < 0) {\r
+ PySequenceMethods *sq = Py_TYPE(self)->tp_as_sequence;\r
+ if (sq && sq->sq_length) {\r
+ Py_ssize_t n = (*sq->sq_length)(self);\r
+ if (n < 0)\r
+ return -1;\r
+ i += n;\r
+ }\r
+ }\r
+ return i;\r
+}\r
+\r
+static PyObject *\r
+wrap_sq_item(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ ssizeargfunc func = (ssizeargfunc)wrapped;\r
+ PyObject *arg;\r
+ Py_ssize_t i;\r
+\r
+ if (PyTuple_GET_SIZE(args) == 1) {\r
+ arg = PyTuple_GET_ITEM(args, 0);\r
+ i = getindex(self, arg);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ return (*func)(self, i);\r
+ }\r
+ check_num_args(args, 1);\r
+ assert(PyErr_Occurred());\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+wrap_ssizessizeargfunc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ ssizessizeargfunc func = (ssizessizeargfunc)wrapped;\r
+ Py_ssize_t i, j;\r
+\r
+ if (!PyArg_ParseTuple(args, "nn", &i, &j))\r
+ return NULL;\r
+ return (*func)(self, i, j);\r
+}\r
+\r
+static PyObject *\r
+wrap_sq_setitem(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ ssizeobjargproc func = (ssizeobjargproc)wrapped;\r
+ Py_ssize_t i;\r
+ int res;\r
+ PyObject *arg, *value;\r
+\r
+ if (!PyArg_UnpackTuple(args, "", 2, 2, &arg, &value))\r
+ return NULL;\r
+ i = getindex(self, arg);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ res = (*func)(self, i, value);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+wrap_sq_delitem(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ ssizeobjargproc func = (ssizeobjargproc)wrapped;\r
+ Py_ssize_t i;\r
+ int res;\r
+ PyObject *arg;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ arg = PyTuple_GET_ITEM(args, 0);\r
+ i = getindex(self, arg);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ res = (*func)(self, i, NULL);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+wrap_ssizessizeobjargproc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped;\r
+ Py_ssize_t i, j;\r
+ int res;\r
+ PyObject *value;\r
+\r
+ if (!PyArg_ParseTuple(args, "nnO", &i, &j, &value))\r
+ return NULL;\r
+ res = (*func)(self, i, j, value);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+wrap_delslice(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped;\r
+ Py_ssize_t i, j;\r
+ int res;\r
+\r
+ if (!PyArg_ParseTuple(args, "nn", &i, &j))\r
+ return NULL;\r
+ res = (*func)(self, i, j, NULL);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+/* XXX objobjproc is a misnomer; should be objargpred */\r
+static PyObject *\r
+wrap_objobjproc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ objobjproc func = (objobjproc)wrapped;\r
+ int res;\r
+ PyObject *value;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ value = PyTuple_GET_ITEM(args, 0);\r
+ res = (*func)(self, value);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ else\r
+ return PyBool_FromLong(res);\r
+}\r
+\r
+static PyObject *\r
+wrap_objobjargproc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ objobjargproc func = (objobjargproc)wrapped;\r
+ int res;\r
+ PyObject *key, *value;\r
+\r
+ if (!PyArg_UnpackTuple(args, "", 2, 2, &key, &value))\r
+ return NULL;\r
+ res = (*func)(self, key, value);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+wrap_delitem(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ objobjargproc func = (objobjargproc)wrapped;\r
+ int res;\r
+ PyObject *key;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ key = PyTuple_GET_ITEM(args, 0);\r
+ res = (*func)(self, key, NULL);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+wrap_cmpfunc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ cmpfunc func = (cmpfunc)wrapped;\r
+ int res;\r
+ PyObject *other;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ other = PyTuple_GET_ITEM(args, 0);\r
+ if (Py_TYPE(other)->tp_compare != func &&\r
+ !PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self))) {\r
+ PyErr_Format(\r
+ PyExc_TypeError,\r
+ "%s.__cmp__(x,y) requires y to be a '%s', not a '%s'",\r
+ Py_TYPE(self)->tp_name,\r
+ Py_TYPE(self)->tp_name,\r
+ Py_TYPE(other)->tp_name);\r
+ return NULL;\r
+ }\r
+ res = (*func)(self, other);\r
+ if (PyErr_Occurred())\r
+ return NULL;\r
+ return PyInt_FromLong((long)res);\r
+}\r
+\r
+/* Helper to check for object.__setattr__ or __delattr__ applied to a type.\r
+ This is called the Carlo Verre hack after its discoverer. */\r
+static int\r
+hackcheck(PyObject *self, setattrofunc func, char *what)\r
+{\r
+ PyTypeObject *type = Py_TYPE(self);\r
+ while (type && type->tp_flags & Py_TPFLAGS_HEAPTYPE)\r
+ type = type->tp_base;\r
+ /* If type is NULL now, this is a really weird type.\r
+ In the spirit of backwards compatibility (?), just shut up. */\r
+ if (type && type->tp_setattro != func) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "can't apply this %s to %s object",\r
+ what,\r
+ type->tp_name);\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+static PyObject *\r
+wrap_setattr(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ setattrofunc func = (setattrofunc)wrapped;\r
+ int res;\r
+ PyObject *name, *value;\r
+\r
+ if (!PyArg_UnpackTuple(args, "", 2, 2, &name, &value))\r
+ return NULL;\r
+ if (!hackcheck(self, func, "__setattr__"))\r
+ return NULL;\r
+ res = (*func)(self, name, value);\r
+ if (res < 0)\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+wrap_delattr(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ setattrofunc func = (setattrofunc)wrapped;\r
+ int res;\r
+ PyObject *name;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ name = PyTuple_GET_ITEM(args, 0);\r
+ if (!hackcheck(self, func, "__delattr__"))\r
+ return NULL;\r
+ res = (*func)(self, name, NULL);\r
+ if (res < 0)\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+wrap_hashfunc(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ hashfunc func = (hashfunc)wrapped;\r
+ long res;\r
+\r
+ if (!check_num_args(args, 0))\r
+ return NULL;\r
+ res = (*func)(self);\r
+ if (res == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ return PyInt_FromLong(res);\r
+}\r
+\r
+static PyObject *\r
+wrap_call(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds)\r
+{\r
+ ternaryfunc func = (ternaryfunc)wrapped;\r
+\r
+ return (*func)(self, args, kwds);\r
+}\r
+\r
+static PyObject *\r
+wrap_richcmpfunc(PyObject *self, PyObject *args, void *wrapped, int op)\r
+{\r
+ richcmpfunc func = (richcmpfunc)wrapped;\r
+ PyObject *other;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ other = PyTuple_GET_ITEM(args, 0);\r
+ return (*func)(self, other, op);\r
+}\r
+\r
+#undef RICHCMP_WRAPPER\r
+#define RICHCMP_WRAPPER(NAME, OP) \\r
+static PyObject * \\r
+richcmp_##NAME(PyObject *self, PyObject *args, void *wrapped) \\r
+{ \\r
+ return wrap_richcmpfunc(self, args, wrapped, OP); \\r
+}\r
+\r
+RICHCMP_WRAPPER(lt, Py_LT)\r
+RICHCMP_WRAPPER(le, Py_LE)\r
+RICHCMP_WRAPPER(eq, Py_EQ)\r
+RICHCMP_WRAPPER(ne, Py_NE)\r
+RICHCMP_WRAPPER(gt, Py_GT)\r
+RICHCMP_WRAPPER(ge, Py_GE)\r
+\r
+static PyObject *\r
+wrap_next(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ unaryfunc func = (unaryfunc)wrapped;\r
+ PyObject *res;\r
+\r
+ if (!check_num_args(args, 0))\r
+ return NULL;\r
+ res = (*func)(self);\r
+ if (res == NULL && !PyErr_Occurred())\r
+ PyErr_SetNone(PyExc_StopIteration);\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+wrap_descr_get(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ descrgetfunc func = (descrgetfunc)wrapped;\r
+ PyObject *obj;\r
+ PyObject *type = NULL;\r
+\r
+ if (!PyArg_UnpackTuple(args, "", 1, 2, &obj, &type))\r
+ return NULL;\r
+ if (obj == Py_None)\r
+ obj = NULL;\r
+ if (type == Py_None)\r
+ type = NULL;\r
+ if (type == NULL &&obj == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__get__(None, None) is invalid");\r
+ return NULL;\r
+ }\r
+ return (*func)(self, obj, type);\r
+}\r
+\r
+static PyObject *\r
+wrap_descr_set(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ descrsetfunc func = (descrsetfunc)wrapped;\r
+ PyObject *obj, *value;\r
+ int ret;\r
+\r
+ if (!PyArg_UnpackTuple(args, "", 2, 2, &obj, &value))\r
+ return NULL;\r
+ ret = (*func)(self, obj, value);\r
+ if (ret < 0)\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+wrap_descr_delete(PyObject *self, PyObject *args, void *wrapped)\r
+{\r
+ descrsetfunc func = (descrsetfunc)wrapped;\r
+ PyObject *obj;\r
+ int ret;\r
+\r
+ if (!check_num_args(args, 1))\r
+ return NULL;\r
+ obj = PyTuple_GET_ITEM(args, 0);\r
+ ret = (*func)(self, obj, NULL);\r
+ if (ret < 0)\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+wrap_init(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds)\r
+{\r
+ initproc func = (initproc)wrapped;\r
+\r
+ if (func(self, args, kwds) < 0)\r
+ return NULL;\r
+ Py_INCREF(Py_None);\r
+ return Py_None;\r
+}\r
+\r
+static PyObject *\r
+tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ PyTypeObject *type, *subtype, *staticbase;\r
+ PyObject *arg0, *res;\r
+\r
+ if (self == NULL || !PyType_Check(self))\r
+ Py_FatalError("__new__() called with non-type 'self'");\r
+ type = (PyTypeObject *)self;\r
+ if (!PyTuple_Check(args) || PyTuple_GET_SIZE(args) < 1) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s.__new__(): not enough arguments",\r
+ type->tp_name);\r
+ return NULL;\r
+ }\r
+ arg0 = PyTuple_GET_ITEM(args, 0);\r
+ if (!PyType_Check(arg0)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s.__new__(X): X is not a type object (%s)",\r
+ type->tp_name,\r
+ Py_TYPE(arg0)->tp_name);\r
+ return NULL;\r
+ }\r
+ subtype = (PyTypeObject *)arg0;\r
+ if (!PyType_IsSubtype(subtype, type)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s.__new__(%s): %s is not a subtype of %s",\r
+ type->tp_name,\r
+ subtype->tp_name,\r
+ subtype->tp_name,\r
+ type->tp_name);\r
+ return NULL;\r
+ }\r
+\r
+ /* Check that the use doesn't do something silly and unsafe like\r
+ object.__new__(dict). To do this, we check that the\r
+ most derived base that's not a heap type is this type. */\r
+ staticbase = subtype;\r
+ while (staticbase && (staticbase->tp_flags & Py_TPFLAGS_HEAPTYPE))\r
+ staticbase = staticbase->tp_base;\r
+ /* If staticbase is NULL now, it is a really weird type.\r
+ In the spirit of backwards compatibility (?), just shut up. */\r
+ if (staticbase && staticbase->tp_new != type->tp_new) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s.__new__(%s) is not safe, use %s.__new__()",\r
+ type->tp_name,\r
+ subtype->tp_name,\r
+ staticbase->tp_name);\r
+ return NULL;\r
+ }\r
+\r
+ args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));\r
+ if (args == NULL)\r
+ return NULL;\r
+ res = type->tp_new(subtype, args, kwds);\r
+ Py_DECREF(args);\r
+ return res;\r
+}\r
+\r
+static struct PyMethodDef tp_new_methoddef[] = {\r
+ {"__new__", (PyCFunction)tp_new_wrapper, METH_VARARGS|METH_KEYWORDS,\r
+ PyDoc_STR("T.__new__(S, ...) -> "\r
+ "a new object with type S, a subtype of T")},\r
+ {0}\r
+};\r
+\r
+static int\r
+add_tp_new_wrapper(PyTypeObject *type)\r
+{\r
+ PyObject *func;\r
+\r
+ if (PyDict_GetItemString(type->tp_dict, "__new__") != NULL)\r
+ return 0;\r
+ func = PyCFunction_New(tp_new_methoddef, (PyObject *)type);\r
+ if (func == NULL)\r
+ return -1;\r
+ if (PyDict_SetItemString(type->tp_dict, "__new__", func)) {\r
+ Py_DECREF(func);\r
+ return -1;\r
+ }\r
+ Py_DECREF(func);\r
+ return 0;\r
+}\r
+\r
+/* Slot wrappers that call the corresponding __foo__ slot. See comments\r
+ below at override_slots() for more explanation. */\r
+\r
+#define SLOT0(FUNCNAME, OPSTR) \\r
+static PyObject * \\r
+FUNCNAME(PyObject *self) \\r
+{ \\r
+ static PyObject *cache_str; \\r
+ return call_method(self, OPSTR, &cache_str, "()"); \\r
+}\r
+\r
+#define SLOT1(FUNCNAME, OPSTR, ARG1TYPE, ARGCODES) \\r
+static PyObject * \\r
+FUNCNAME(PyObject *self, ARG1TYPE arg1) \\r
+{ \\r
+ static PyObject *cache_str; \\r
+ return call_method(self, OPSTR, &cache_str, "(" ARGCODES ")", arg1); \\r
+}\r
+\r
+/* Boolean helper for SLOT1BINFULL().\r
+ right.__class__ is a nontrivial subclass of left.__class__. */\r
+static int\r
+method_is_overloaded(PyObject *left, PyObject *right, char *name)\r
+{\r
+ PyObject *a, *b;\r
+ int ok;\r
+\r
+ b = PyObject_GetAttrString((PyObject *)(Py_TYPE(right)), name);\r
+ if (b == NULL) {\r
+ PyErr_Clear();\r
+ /* If right doesn't have it, it's not overloaded */\r
+ return 0;\r
+ }\r
+\r
+ a = PyObject_GetAttrString((PyObject *)(Py_TYPE(left)), name);\r
+ if (a == NULL) {\r
+ PyErr_Clear();\r
+ Py_DECREF(b);\r
+ /* If right has it but left doesn't, it's overloaded */\r
+ return 1;\r
+ }\r
+\r
+ ok = PyObject_RichCompareBool(a, b, Py_NE);\r
+ Py_DECREF(a);\r
+ Py_DECREF(b);\r
+ if (ok < 0) {\r
+ PyErr_Clear();\r
+ return 0;\r
+ }\r
+\r
+ return ok;\r
+}\r
+\r
+\r
+#define SLOT1BINFULL(FUNCNAME, TESTFUNC, SLOTNAME, OPSTR, ROPSTR) \\r
+static PyObject * \\r
+FUNCNAME(PyObject *self, PyObject *other) \\r
+{ \\r
+ static PyObject *cache_str, *rcache_str; \\r
+ int do_other = Py_TYPE(self) != Py_TYPE(other) && \\r
+ Py_TYPE(other)->tp_as_number != NULL && \\r
+ Py_TYPE(other)->tp_as_number->SLOTNAME == TESTFUNC; \\r
+ if (Py_TYPE(self)->tp_as_number != NULL && \\r
+ Py_TYPE(self)->tp_as_number->SLOTNAME == TESTFUNC) { \\r
+ PyObject *r; \\r
+ if (do_other && \\r
+ PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self)) && \\r
+ method_is_overloaded(self, other, ROPSTR)) { \\r
+ r = call_maybe( \\r
+ other, ROPSTR, &rcache_str, "(O)", self); \\r
+ if (r != Py_NotImplemented) \\r
+ return r; \\r
+ Py_DECREF(r); \\r
+ do_other = 0; \\r
+ } \\r
+ r = call_maybe( \\r
+ self, OPSTR, &cache_str, "(O)", other); \\r
+ if (r != Py_NotImplemented || \\r
+ Py_TYPE(other) == Py_TYPE(self)) \\r
+ return r; \\r
+ Py_DECREF(r); \\r
+ } \\r
+ if (do_other) { \\r
+ return call_maybe( \\r
+ other, ROPSTR, &rcache_str, "(O)", self); \\r
+ } \\r
+ Py_INCREF(Py_NotImplemented); \\r
+ return Py_NotImplemented; \\r
+}\r
+\r
+#define SLOT1BIN(FUNCNAME, SLOTNAME, OPSTR, ROPSTR) \\r
+ SLOT1BINFULL(FUNCNAME, FUNCNAME, SLOTNAME, OPSTR, ROPSTR)\r
+\r
+#define SLOT2(FUNCNAME, OPSTR, ARG1TYPE, ARG2TYPE, ARGCODES) \\r
+static PyObject * \\r
+FUNCNAME(PyObject *self, ARG1TYPE arg1, ARG2TYPE arg2) \\r
+{ \\r
+ static PyObject *cache_str; \\r
+ return call_method(self, OPSTR, &cache_str, \\r
+ "(" ARGCODES ")", arg1, arg2); \\r
+}\r
+\r
+static Py_ssize_t\r
+slot_sq_length(PyObject *self)\r
+{\r
+ static PyObject *len_str;\r
+ PyObject *res = call_method(self, "__len__", &len_str, "()");\r
+ Py_ssize_t len;\r
+\r
+ if (res == NULL)\r
+ return -1;\r
+ len = PyInt_AsSsize_t(res);\r
+ Py_DECREF(res);\r
+ if (len < 0) {\r
+ if (!PyErr_Occurred())\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "__len__() should return >= 0");\r
+ return -1;\r
+ }\r
+ return len;\r
+}\r
+\r
+/* Super-optimized version of slot_sq_item.\r
+ Other slots could do the same... */\r
+static PyObject *\r
+slot_sq_item(PyObject *self, Py_ssize_t i)\r
+{\r
+ static PyObject *getitem_str;\r
+ PyObject *func, *args = NULL, *ival = NULL, *retval = NULL;\r
+ descrgetfunc f;\r
+\r
+ if (getitem_str == NULL) {\r
+ getitem_str = PyString_InternFromString("__getitem__");\r
+ if (getitem_str == NULL)\r
+ return NULL;\r
+ }\r
+ func = _PyType_Lookup(Py_TYPE(self), getitem_str);\r
+ if (func != NULL) {\r
+ if ((f = Py_TYPE(func)->tp_descr_get) == NULL)\r
+ Py_INCREF(func);\r
+ else {\r
+ func = f(func, self, (PyObject *)(Py_TYPE(self)));\r
+ if (func == NULL) {\r
+ return NULL;\r
+ }\r
+ }\r
+ ival = PyInt_FromSsize_t(i);\r
+ if (ival != NULL) {\r
+ args = PyTuple_New(1);\r
+ if (args != NULL) {\r
+ PyTuple_SET_ITEM(args, 0, ival);\r
+ retval = PyObject_Call(func, args, NULL);\r
+ Py_XDECREF(args);\r
+ Py_XDECREF(func);\r
+ return retval;\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ PyErr_SetObject(PyExc_AttributeError, getitem_str);\r
+ }\r
+ Py_XDECREF(args);\r
+ Py_XDECREF(ival);\r
+ Py_XDECREF(func);\r
+ return NULL;\r
+}\r
+\r
+static PyObject*\r
+slot_sq_slice(PyObject *self, Py_ssize_t i, Py_ssize_t j)\r
+{\r
+ static PyObject *getslice_str;\r
+\r
+ if (PyErr_WarnPy3k("in 3.x, __getslice__ has been removed; "\r
+ "use __getitem__", 1) < 0)\r
+ return NULL;\r
+ return call_method(self, "__getslice__", &getslice_str,\r
+ "nn", i, j);\r
+}\r
+\r
+static int\r
+slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value)\r
+{\r
+ PyObject *res;\r
+ static PyObject *delitem_str, *setitem_str;\r
+\r
+ if (value == NULL)\r
+ res = call_method(self, "__delitem__", &delitem_str,\r
+ "(n)", index);\r
+ else\r
+ res = call_method(self, "__setitem__", &setitem_str,\r
+ "(nO)", index, value);\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static int\r
+slot_sq_ass_slice(PyObject *self, Py_ssize_t i, Py_ssize_t j, PyObject *value)\r
+{\r
+ PyObject *res;\r
+ static PyObject *delslice_str, *setslice_str;\r
+\r
+ if (value == NULL) {\r
+ if (PyErr_WarnPy3k("in 3.x, __delslice__ has been removed; "\r
+ "use __delitem__", 1) < 0)\r
+ return -1;\r
+ res = call_method(self, "__delslice__", &delslice_str,\r
+ "(nn)", i, j);\r
+ }\r
+ else {\r
+ if (PyErr_WarnPy3k("in 3.x, __setslice__ has been removed; "\r
+ "use __setitem__", 1) < 0)\r
+ return -1;\r
+ res = call_method(self, "__setslice__", &setslice_str,\r
+ "(nnO)", i, j, value);\r
+ }\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static int\r
+slot_sq_contains(PyObject *self, PyObject *value)\r
+{\r
+ PyObject *func, *res, *args;\r
+ int result = -1;\r
+\r
+ static PyObject *contains_str;\r
+\r
+ func = lookup_maybe(self, "__contains__", &contains_str);\r
+ if (func != NULL) {\r
+ args = PyTuple_Pack(1, value);\r
+ if (args == NULL)\r
+ res = NULL;\r
+ else {\r
+ res = PyObject_Call(func, args, NULL);\r
+ Py_DECREF(args);\r
+ }\r
+ Py_DECREF(func);\r
+ if (res != NULL) {\r
+ result = PyObject_IsTrue(res);\r
+ Py_DECREF(res);\r
+ }\r
+ }\r
+ else if (! PyErr_Occurred()) {\r
+ /* Possible results: -1 and 1 */\r
+ result = (int)_PySequence_IterSearch(self, value,\r
+ PY_ITERSEARCH_CONTAINS);\r
+ }\r
+ return result;\r
+}\r
+\r
+#define slot_mp_length slot_sq_length\r
+\r
+SLOT1(slot_mp_subscript, "__getitem__", PyObject *, "O")\r
+\r
+static int\r
+slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)\r
+{\r
+ PyObject *res;\r
+ static PyObject *delitem_str, *setitem_str;\r
+\r
+ if (value == NULL)\r
+ res = call_method(self, "__delitem__", &delitem_str,\r
+ "(O)", key);\r
+ else\r
+ res = call_method(self, "__setitem__", &setitem_str,\r
+ "(OO)", key, value);\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+SLOT1BIN(slot_nb_add, nb_add, "__add__", "__radd__")\r
+SLOT1BIN(slot_nb_subtract, nb_subtract, "__sub__", "__rsub__")\r
+SLOT1BIN(slot_nb_multiply, nb_multiply, "__mul__", "__rmul__")\r
+SLOT1BIN(slot_nb_divide, nb_divide, "__div__", "__rdiv__")\r
+SLOT1BIN(slot_nb_remainder, nb_remainder, "__mod__", "__rmod__")\r
+SLOT1BIN(slot_nb_divmod, nb_divmod, "__divmod__", "__rdivmod__")\r
+\r
+static PyObject *slot_nb_power(PyObject *, PyObject *, PyObject *);\r
+\r
+SLOT1BINFULL(slot_nb_power_binary, slot_nb_power,\r
+ nb_power, "__pow__", "__rpow__")\r
+\r
+static PyObject *\r
+slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus)\r
+{\r
+ static PyObject *pow_str;\r
+\r
+ if (modulus == Py_None)\r
+ return slot_nb_power_binary(self, other);\r
+ /* Three-arg power doesn't use __rpow__. But ternary_op\r
+ can call this when the second argument's type uses\r
+ slot_nb_power, so check before calling self.__pow__. */\r
+ if (Py_TYPE(self)->tp_as_number != NULL &&\r
+ Py_TYPE(self)->tp_as_number->nb_power == slot_nb_power) {\r
+ return call_method(self, "__pow__", &pow_str,\r
+ "(OO)", other, modulus);\r
+ }\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+}\r
+\r
+SLOT0(slot_nb_negative, "__neg__")\r
+SLOT0(slot_nb_positive, "__pos__")\r
+SLOT0(slot_nb_absolute, "__abs__")\r
+\r
+static int\r
+slot_nb_nonzero(PyObject *self)\r
+{\r
+ PyObject *func, *args;\r
+ static PyObject *nonzero_str, *len_str;\r
+ int result = -1;\r
+ int using_len = 0;\r
+\r
+ func = lookup_maybe(self, "__nonzero__", &nonzero_str);\r
+ if (func == NULL) {\r
+ if (PyErr_Occurred())\r
+ return -1;\r
+ func = lookup_maybe(self, "__len__", &len_str);\r
+ if (func == NULL)\r
+ return PyErr_Occurred() ? -1 : 1;\r
+ using_len = 1;\r
+ }\r
+ args = PyTuple_New(0);\r
+ if (args != NULL) {\r
+ PyObject *temp = PyObject_Call(func, args, NULL);\r
+ Py_DECREF(args);\r
+ if (temp != NULL) {\r
+ if (PyInt_CheckExact(temp) || PyBool_Check(temp))\r
+ result = PyObject_IsTrue(temp);\r
+ else {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s should return "\r
+ "bool or int, returned %s",\r
+ (using_len ? "__len__"\r
+ : "__nonzero__"),\r
+ temp->ob_type->tp_name);\r
+ result = -1;\r
+ }\r
+ Py_DECREF(temp);\r
+ }\r
+ }\r
+ Py_DECREF(func);\r
+ return result;\r
+}\r
+\r
+\r
+static PyObject *\r
+slot_nb_index(PyObject *self)\r
+{\r
+ static PyObject *index_str;\r
+ return call_method(self, "__index__", &index_str, "()");\r
+}\r
+\r
+\r
+SLOT0(slot_nb_invert, "__invert__")\r
+SLOT1BIN(slot_nb_lshift, nb_lshift, "__lshift__", "__rlshift__")\r
+SLOT1BIN(slot_nb_rshift, nb_rshift, "__rshift__", "__rrshift__")\r
+SLOT1BIN(slot_nb_and, nb_and, "__and__", "__rand__")\r
+SLOT1BIN(slot_nb_xor, nb_xor, "__xor__", "__rxor__")\r
+SLOT1BIN(slot_nb_or, nb_or, "__or__", "__ror__")\r
+\r
+static int\r
+slot_nb_coerce(PyObject **a, PyObject **b)\r
+{\r
+ static PyObject *coerce_str;\r
+ PyObject *self = *a, *other = *b;\r
+\r
+ if (self->ob_type->tp_as_number != NULL &&\r
+ self->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {\r
+ PyObject *r;\r
+ r = call_maybe(\r
+ self, "__coerce__", &coerce_str, "(O)", other);\r
+ if (r == NULL)\r
+ return -1;\r
+ if (r == Py_NotImplemented) {\r
+ Py_DECREF(r);\r
+ }\r
+ else {\r
+ if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__coerce__ didn't return a 2-tuple");\r
+ Py_DECREF(r);\r
+ return -1;\r
+ }\r
+ *a = PyTuple_GET_ITEM(r, 0);\r
+ Py_INCREF(*a);\r
+ *b = PyTuple_GET_ITEM(r, 1);\r
+ Py_INCREF(*b);\r
+ Py_DECREF(r);\r
+ return 0;\r
+ }\r
+ }\r
+ if (other->ob_type->tp_as_number != NULL &&\r
+ other->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {\r
+ PyObject *r;\r
+ r = call_maybe(\r
+ other, "__coerce__", &coerce_str, "(O)", self);\r
+ if (r == NULL)\r
+ return -1;\r
+ if (r == Py_NotImplemented) {\r
+ Py_DECREF(r);\r
+ return 1;\r
+ }\r
+ if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "__coerce__ didn't return a 2-tuple");\r
+ Py_DECREF(r);\r
+ return -1;\r
+ }\r
+ *a = PyTuple_GET_ITEM(r, 1);\r
+ Py_INCREF(*a);\r
+ *b = PyTuple_GET_ITEM(r, 0);\r
+ Py_INCREF(*b);\r
+ Py_DECREF(r);\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+SLOT0(slot_nb_int, "__int__")\r
+SLOT0(slot_nb_long, "__long__")\r
+SLOT0(slot_nb_float, "__float__")\r
+SLOT0(slot_nb_oct, "__oct__")\r
+SLOT0(slot_nb_hex, "__hex__")\r
+SLOT1(slot_nb_inplace_add, "__iadd__", PyObject *, "O")\r
+SLOT1(slot_nb_inplace_subtract, "__isub__", PyObject *, "O")\r
+SLOT1(slot_nb_inplace_multiply, "__imul__", PyObject *, "O")\r
+SLOT1(slot_nb_inplace_divide, "__idiv__", PyObject *, "O")\r
+SLOT1(slot_nb_inplace_remainder, "__imod__", PyObject *, "O")\r
+/* Can't use SLOT1 here, because nb_inplace_power is ternary */\r
+static PyObject *\r
+slot_nb_inplace_power(PyObject *self, PyObject * arg1, PyObject *arg2)\r
+{\r
+ static PyObject *cache_str;\r
+ return call_method(self, "__ipow__", &cache_str, "(" "O" ")", arg1);\r
+}\r
+SLOT1(slot_nb_inplace_lshift, "__ilshift__", PyObject *, "O")\r
+SLOT1(slot_nb_inplace_rshift, "__irshift__", PyObject *, "O")\r
+SLOT1(slot_nb_inplace_and, "__iand__", PyObject *, "O")\r
+SLOT1(slot_nb_inplace_xor, "__ixor__", PyObject *, "O")\r
+SLOT1(slot_nb_inplace_or, "__ior__", PyObject *, "O")\r
+SLOT1BIN(slot_nb_floor_divide, nb_floor_divide,\r
+ "__floordiv__", "__rfloordiv__")\r
+SLOT1BIN(slot_nb_true_divide, nb_true_divide, "__truediv__", "__rtruediv__")\r
+SLOT1(slot_nb_inplace_floor_divide, "__ifloordiv__", PyObject *, "O")\r
+SLOT1(slot_nb_inplace_true_divide, "__itruediv__", PyObject *, "O")\r
+\r
+static int\r
+half_compare(PyObject *self, PyObject *other)\r
+{\r
+ PyObject *func, *args, *res;\r
+ static PyObject *cmp_str;\r
+ Py_ssize_t c;\r
+\r
+ func = lookup_method(self, "__cmp__", &cmp_str);\r
+ if (func == NULL) {\r
+ PyErr_Clear();\r
+ }\r
+ else {\r
+ args = PyTuple_Pack(1, other);\r
+ if (args == NULL)\r
+ res = NULL;\r
+ else {\r
+ res = PyObject_Call(func, args, NULL);\r
+ Py_DECREF(args);\r
+ }\r
+ Py_DECREF(func);\r
+ if (res != Py_NotImplemented) {\r
+ if (res == NULL)\r
+ return -2;\r
+ c = PyInt_AsLong(res);\r
+ Py_DECREF(res);\r
+ if (c == -1 && PyErr_Occurred())\r
+ return -2;\r
+ return (c < 0) ? -1 : (c > 0) ? 1 : 0;\r
+ }\r
+ Py_DECREF(res);\r
+ }\r
+ return 2;\r
+}\r
+\r
+/* This slot is published for the benefit of try_3way_compare in object.c */\r
+int\r
+_PyObject_SlotCompare(PyObject *self, PyObject *other)\r
+{\r
+ int c;\r
+\r
+ if (Py_TYPE(self)->tp_compare == _PyObject_SlotCompare) {\r
+ c = half_compare(self, other);\r
+ if (c <= 1)\r
+ return c;\r
+ }\r
+ if (Py_TYPE(other)->tp_compare == _PyObject_SlotCompare) {\r
+ c = half_compare(other, self);\r
+ if (c < -1)\r
+ return -2;\r
+ if (c <= 1)\r
+ return -c;\r
+ }\r
+ return (void *)self < (void *)other ? -1 :\r
+ (void *)self > (void *)other ? 1 : 0;\r
+}\r
+\r
+static PyObject *\r
+slot_tp_repr(PyObject *self)\r
+{\r
+ PyObject *func, *res;\r
+ static PyObject *repr_str;\r
+\r
+ func = lookup_method(self, "__repr__", &repr_str);\r
+ if (func != NULL) {\r
+ res = PyEval_CallObject(func, NULL);\r
+ Py_DECREF(func);\r
+ return res;\r
+ }\r
+ PyErr_Clear();\r
+ return PyString_FromFormat("<%s object at %p>",\r
+ Py_TYPE(self)->tp_name, self);\r
+}\r
+\r
+static PyObject *\r
+slot_tp_str(PyObject *self)\r
+{\r
+ PyObject *func, *res;\r
+ static PyObject *str_str;\r
+\r
+ func = lookup_method(self, "__str__", &str_str);\r
+ if (func != NULL) {\r
+ res = PyEval_CallObject(func, NULL);\r
+ Py_DECREF(func);\r
+ return res;\r
+ }\r
+ else {\r
+ PyErr_Clear();\r
+ return slot_tp_repr(self);\r
+ }\r
+}\r
+\r
+static long\r
+slot_tp_hash(PyObject *self)\r
+{\r
+ PyObject *func;\r
+ static PyObject *hash_str, *eq_str, *cmp_str;\r
+ long h;\r
+\r
+ func = lookup_method(self, "__hash__", &hash_str);\r
+\r
+ if (func != NULL && func != Py_None) {\r
+ PyObject *res = PyEval_CallObject(func, NULL);\r
+ Py_DECREF(func);\r
+ if (res == NULL)\r
+ return -1;\r
+ if (PyLong_Check(res))\r
+ h = PyLong_Type.tp_hash(res);\r
+ else\r
+ h = PyInt_AsLong(res);\r
+ Py_DECREF(res);\r
+ }\r
+ else {\r
+ Py_XDECREF(func); /* may be None */\r
+ PyErr_Clear();\r
+ func = lookup_method(self, "__eq__", &eq_str);\r
+ if (func == NULL) {\r
+ PyErr_Clear();\r
+ func = lookup_method(self, "__cmp__", &cmp_str);\r
+ }\r
+ if (func != NULL) {\r
+ Py_DECREF(func);\r
+ return PyObject_HashNotImplemented(self);\r
+ }\r
+ PyErr_Clear();\r
+ h = _Py_HashPointer((void *)self);\r
+ }\r
+ if (h == -1 && !PyErr_Occurred())\r
+ h = -2;\r
+ return h;\r
+}\r
+\r
+static PyObject *\r
+slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ static PyObject *call_str;\r
+ PyObject *meth = lookup_method(self, "__call__", &call_str);\r
+ PyObject *res;\r
+\r
+ if (meth == NULL)\r
+ return NULL;\r
+\r
+ res = PyObject_Call(meth, args, kwds);\r
+\r
+ Py_DECREF(meth);\r
+ return res;\r
+}\r
+\r
+/* There are two slot dispatch functions for tp_getattro.\r
+\r
+ - slot_tp_getattro() is used when __getattribute__ is overridden\r
+ but no __getattr__ hook is present;\r
+\r
+ - slot_tp_getattr_hook() is used when a __getattr__ hook is present.\r
+\r
+ The code in update_one_slot() always installs slot_tp_getattr_hook(); this\r
+ detects the absence of __getattr__ and then installs the simpler slot if\r
+ necessary. */\r
+\r
+static PyObject *\r
+slot_tp_getattro(PyObject *self, PyObject *name)\r
+{\r
+ static PyObject *getattribute_str = NULL;\r
+ return call_method(self, "__getattribute__", &getattribute_str,\r
+ "(O)", name);\r
+}\r
+\r
+static PyObject *\r
+call_attribute(PyObject *self, PyObject *attr, PyObject *name)\r
+{\r
+ PyObject *res, *descr = NULL;\r
+ descrgetfunc f = Py_TYPE(attr)->tp_descr_get;\r
+\r
+ if (f != NULL) {\r
+ descr = f(attr, self, (PyObject *)(Py_TYPE(self)));\r
+ if (descr == NULL)\r
+ return NULL;\r
+ else\r
+ attr = descr;\r
+ }\r
+ res = PyObject_CallFunctionObjArgs(attr, name, NULL);\r
+ Py_XDECREF(descr);\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+slot_tp_getattr_hook(PyObject *self, PyObject *name)\r
+{\r
+ PyTypeObject *tp = Py_TYPE(self);\r
+ PyObject *getattr, *getattribute, *res;\r
+ static PyObject *getattribute_str = NULL;\r
+ static PyObject *getattr_str = NULL;\r
+\r
+ if (getattr_str == NULL) {\r
+ getattr_str = PyString_InternFromString("__getattr__");\r
+ if (getattr_str == NULL)\r
+ return NULL;\r
+ }\r
+ if (getattribute_str == NULL) {\r
+ getattribute_str =\r
+ PyString_InternFromString("__getattribute__");\r
+ if (getattribute_str == NULL)\r
+ return NULL;\r
+ }\r
+ /* speed hack: we could use lookup_maybe, but that would resolve the\r
+ method fully for each attribute lookup for classes with\r
+ __getattr__, even when the attribute is present. So we use\r
+ _PyType_Lookup and create the method only when needed, with\r
+ call_attribute. */\r
+ getattr = _PyType_Lookup(tp, getattr_str);\r
+ if (getattr == NULL) {\r
+ /* No __getattr__ hook: use a simpler dispatcher */\r
+ tp->tp_getattro = slot_tp_getattro;\r
+ return slot_tp_getattro(self, name);\r
+ }\r
+ Py_INCREF(getattr);\r
+ /* speed hack: we could use lookup_maybe, but that would resolve the\r
+ method fully for each attribute lookup for classes with\r
+ __getattr__, even when self has the default __getattribute__\r
+ method. So we use _PyType_Lookup and create the method only when\r
+ needed, with call_attribute. */\r
+ getattribute = _PyType_Lookup(tp, getattribute_str);\r
+ if (getattribute == NULL ||\r
+ (Py_TYPE(getattribute) == &PyWrapperDescr_Type &&\r
+ ((PyWrapperDescrObject *)getattribute)->d_wrapped ==\r
+ (void *)PyObject_GenericGetAttr))\r
+ res = PyObject_GenericGetAttr(self, name);\r
+ else {\r
+ Py_INCREF(getattribute);\r
+ res = call_attribute(self, getattribute, name);\r
+ Py_DECREF(getattribute);\r
+ }\r
+ if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {\r
+ PyErr_Clear();\r
+ res = call_attribute(self, getattr, name);\r
+ }\r
+ Py_DECREF(getattr);\r
+ return res;\r
+}\r
+\r
+static int\r
+slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value)\r
+{\r
+ PyObject *res;\r
+ static PyObject *delattr_str, *setattr_str;\r
+\r
+ if (value == NULL)\r
+ res = call_method(self, "__delattr__", &delattr_str,\r
+ "(O)", name);\r
+ else\r
+ res = call_method(self, "__setattr__", &setattr_str,\r
+ "(OO)", name, value);\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static char *name_op[] = {\r
+ "__lt__",\r
+ "__le__",\r
+ "__eq__",\r
+ "__ne__",\r
+ "__gt__",\r
+ "__ge__",\r
+};\r
+\r
+static PyObject *\r
+half_richcompare(PyObject *self, PyObject *other, int op)\r
+{\r
+ PyObject *func, *args, *res;\r
+ static PyObject *op_str[6];\r
+\r
+ func = lookup_method(self, name_op[op], &op_str[op]);\r
+ if (func == NULL) {\r
+ PyErr_Clear();\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ args = PyTuple_Pack(1, other);\r
+ if (args == NULL)\r
+ res = NULL;\r
+ else {\r
+ res = PyObject_Call(func, args, NULL);\r
+ Py_DECREF(args);\r
+ }\r
+ Py_DECREF(func);\r
+ return res;\r
+}\r
+\r
+static PyObject *\r
+slot_tp_richcompare(PyObject *self, PyObject *other, int op)\r
+{\r
+ PyObject *res;\r
+\r
+ if (Py_TYPE(self)->tp_richcompare == slot_tp_richcompare) {\r
+ res = half_richcompare(self, other, op);\r
+ if (res != Py_NotImplemented)\r
+ return res;\r
+ Py_DECREF(res);\r
+ }\r
+ if (Py_TYPE(other)->tp_richcompare == slot_tp_richcompare) {\r
+ res = half_richcompare(other, self, _Py_SwappedOp[op]);\r
+ if (res != Py_NotImplemented) {\r
+ return res;\r
+ }\r
+ Py_DECREF(res);\r
+ }\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+}\r
+\r
+static PyObject *\r
+slot_tp_iter(PyObject *self)\r
+{\r
+ PyObject *func, *res;\r
+ static PyObject *iter_str, *getitem_str;\r
+\r
+ func = lookup_method(self, "__iter__", &iter_str);\r
+ if (func != NULL) {\r
+ PyObject *args;\r
+ args = res = PyTuple_New(0);\r
+ if (args != NULL) {\r
+ res = PyObject_Call(func, args, NULL);\r
+ Py_DECREF(args);\r
+ }\r
+ Py_DECREF(func);\r
+ return res;\r
+ }\r
+ PyErr_Clear();\r
+ func = lookup_method(self, "__getitem__", &getitem_str);\r
+ if (func == NULL) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "'%.200s' object is not iterable",\r
+ Py_TYPE(self)->tp_name);\r
+ return NULL;\r
+ }\r
+ Py_DECREF(func);\r
+ return PySeqIter_New(self);\r
+}\r
+\r
+static PyObject *\r
+slot_tp_iternext(PyObject *self)\r
+{\r
+ static PyObject *next_str;\r
+ return call_method(self, "next", &next_str, "()");\r
+}\r
+\r
+static PyObject *\r
+slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type)\r
+{\r
+ PyTypeObject *tp = Py_TYPE(self);\r
+ PyObject *get;\r
+ static PyObject *get_str = NULL;\r
+\r
+ if (get_str == NULL) {\r
+ get_str = PyString_InternFromString("__get__");\r
+ if (get_str == NULL)\r
+ return NULL;\r
+ }\r
+ get = _PyType_Lookup(tp, get_str);\r
+ if (get == NULL) {\r
+ /* Avoid further slowdowns */\r
+ if (tp->tp_descr_get == slot_tp_descr_get)\r
+ tp->tp_descr_get = NULL;\r
+ Py_INCREF(self);\r
+ return self;\r
+ }\r
+ if (obj == NULL)\r
+ obj = Py_None;\r
+ if (type == NULL)\r
+ type = Py_None;\r
+ return PyObject_CallFunctionObjArgs(get, self, obj, type, NULL);\r
+}\r
+\r
+static int\r
+slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value)\r
+{\r
+ PyObject *res;\r
+ static PyObject *del_str, *set_str;\r
+\r
+ if (value == NULL)\r
+ res = call_method(self, "__delete__", &del_str,\r
+ "(O)", target);\r
+ else\r
+ res = call_method(self, "__set__", &set_str,\r
+ "(OO)", target, value);\r
+ if (res == NULL)\r
+ return -1;\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static int\r
+slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ static PyObject *init_str;\r
+ PyObject *meth = lookup_method(self, "__init__", &init_str);\r
+ PyObject *res;\r
+\r
+ if (meth == NULL)\r
+ return -1;\r
+ res = PyObject_Call(meth, args, kwds);\r
+ Py_DECREF(meth);\r
+ if (res == NULL)\r
+ return -1;\r
+ if (res != Py_None) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "__init__() should return None, not '%.200s'",\r
+ Py_TYPE(res)->tp_name);\r
+ Py_DECREF(res);\r
+ return -1;\r
+ }\r
+ Py_DECREF(res);\r
+ return 0;\r
+}\r
+\r
+static PyObject *\r
+slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ static PyObject *new_str;\r
+ PyObject *func;\r
+ PyObject *newargs, *x;\r
+ Py_ssize_t i, n;\r
+\r
+ if (new_str == NULL) {\r
+ new_str = PyString_InternFromString("__new__");\r
+ if (new_str == NULL)\r
+ return NULL;\r
+ }\r
+ func = PyObject_GetAttr((PyObject *)type, new_str);\r
+ if (func == NULL)\r
+ return NULL;\r
+ assert(PyTuple_Check(args));\r
+ n = PyTuple_GET_SIZE(args);\r
+ newargs = PyTuple_New(n+1);\r
+ if (newargs == NULL)\r
+ return NULL;\r
+ Py_INCREF(type);\r
+ PyTuple_SET_ITEM(newargs, 0, (PyObject *)type);\r
+ for (i = 0; i < n; i++) {\r
+ x = PyTuple_GET_ITEM(args, i);\r
+ Py_INCREF(x);\r
+ PyTuple_SET_ITEM(newargs, i+1, x);\r
+ }\r
+ x = PyObject_Call(func, newargs, kwds);\r
+ Py_DECREF(newargs);\r
+ Py_DECREF(func);\r
+ return x;\r
+}\r
+\r
+static void\r
+slot_tp_del(PyObject *self)\r
+{\r
+ static PyObject *del_str = NULL;\r
+ PyObject *del, *res;\r
+ PyObject *error_type, *error_value, *error_traceback;\r
+\r
+ /* Temporarily resurrect the object. */\r
+ assert(self->ob_refcnt == 0);\r
+ self->ob_refcnt = 1;\r
+\r
+ /* Save the current exception, if any. */\r
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);\r
+\r
+ /* Execute __del__ method, if any. */\r
+ del = lookup_maybe(self, "__del__", &del_str);\r
+ if (del != NULL) {\r
+ res = PyEval_CallObject(del, NULL);\r
+ if (res == NULL)\r
+ PyErr_WriteUnraisable(del);\r
+ else\r
+ Py_DECREF(res);\r
+ Py_DECREF(del);\r
+ }\r
+\r
+ /* Restore the saved exception. */\r
+ PyErr_Restore(error_type, error_value, error_traceback);\r
+\r
+ /* Undo the temporary resurrection; can't use DECREF here, it would\r
+ * cause a recursive call.\r
+ */\r
+ assert(self->ob_refcnt > 0);\r
+ if (--self->ob_refcnt == 0)\r
+ return; /* this is the normal path out */\r
+\r
+ /* __del__ resurrected it! Make it look like the original Py_DECREF\r
+ * never happened.\r
+ */\r
+ {\r
+ Py_ssize_t refcnt = self->ob_refcnt;\r
+ _Py_NewReference(self);\r
+ self->ob_refcnt = refcnt;\r
+ }\r
+ assert(!PyType_IS_GC(Py_TYPE(self)) ||\r
+ _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);\r
+ /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so\r
+ * we need to undo that. */\r
+ _Py_DEC_REFTOTAL;\r
+ /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object\r
+ * chain, so no more to do there.\r
+ * If COUNT_ALLOCS, the original decref bumped tp_frees, and\r
+ * _Py_NewReference bumped tp_allocs: both of those need to be\r
+ * undone.\r
+ */\r
+#ifdef COUNT_ALLOCS\r
+ --Py_TYPE(self)->tp_frees;\r
+ --Py_TYPE(self)->tp_allocs;\r
+#endif\r
+}\r
+\r
+\r
+/*\r
+Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper functions.\r
+\r
+The table is ordered by offsets relative to the 'PyHeapTypeObject' structure,\r
+which incorporates the additional structures used for numbers, sequences and\r
+mappings. Note that multiple names may map to the same slot (e.g. __eq__,\r
+__ne__ etc. all map to tp_richcompare) and one name may map to multiple slots\r
+(e.g. __str__ affects tp_str as well as tp_repr). The table is terminated with\r
+an all-zero entry. (This table is further initialized in init_slotdefs().)\r
+*/\r
+\r
+typedef struct wrapperbase slotdef;\r
+\r
+#undef TPSLOT\r
+#undef FLSLOT\r
+#undef ETSLOT\r
+#undef SQSLOT\r
+#undef MPSLOT\r
+#undef NBSLOT\r
+#undef UNSLOT\r
+#undef IBSLOT\r
+#undef BINSLOT\r
+#undef RBINSLOT\r
+\r
+#define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \\r
+ {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \\r
+ PyDoc_STR(DOC)}\r
+#define FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS) \\r
+ {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \\r
+ PyDoc_STR(DOC), FLAGS}\r
+#define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \\r
+ {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \\r
+ PyDoc_STR(DOC)}\r
+#define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \\r
+ ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC)\r
+#define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \\r
+ ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER, DOC)\r
+#define NBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \\r
+ ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, DOC)\r
+#define UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \\r
+ ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \\r
+ "x." NAME "() <==> " DOC)\r
+#define IBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \\r
+ ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \\r
+ "x." NAME "(y) <==> x" DOC "y")\r
+#define BINSLOT(NAME, SLOT, FUNCTION, DOC) \\r
+ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \\r
+ "x." NAME "(y) <==> x" DOC "y")\r
+#define RBINSLOT(NAME, SLOT, FUNCTION, DOC) \\r
+ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \\r
+ "x." NAME "(y) <==> y" DOC "x")\r
+#define BINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \\r
+ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \\r
+ "x." NAME "(y) <==> " DOC)\r
+#define RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \\r
+ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \\r
+ "x." NAME "(y) <==> " DOC)\r
+\r
+static slotdef slotdefs[] = {\r
+ TPSLOT("__str__", tp_print, NULL, NULL, ""),\r
+ TPSLOT("__repr__", tp_print, NULL, NULL, ""),\r
+ TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""),\r
+ TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),\r
+ TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""),\r
+ TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""),\r
+ TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc,\r
+ "x.__cmp__(y) <==> cmp(x,y)"),\r
+ TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc,\r
+ "x.__repr__() <==> repr(x)"),\r
+ TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc,\r
+ "x.__hash__() <==> hash(x)"),\r
+ FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call,\r
+ "x.__call__(...) <==> x(...)", PyWrapperFlag_KEYWORDS),\r
+ TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc,\r
+ "x.__str__() <==> str(x)"),\r
+ TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook,\r
+ wrap_binaryfunc, "x.__getattribute__('name') <==> x.name"),\r
+ TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""),\r
+ TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr,\r
+ "x.__setattr__('name', value) <==> x.name = value"),\r
+ TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr,\r
+ "x.__delattr__('name') <==> del x.name"),\r
+ TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt,\r
+ "x.__lt__(y) <==> x<y"),\r
+ TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le,\r
+ "x.__le__(y) <==> x<=y"),\r
+ TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq,\r
+ "x.__eq__(y) <==> x==y"),\r
+ TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne,\r
+ "x.__ne__(y) <==> x!=y"),\r
+ TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt,\r
+ "x.__gt__(y) <==> x>y"),\r
+ TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge,\r
+ "x.__ge__(y) <==> x>=y"),\r
+ TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc,\r
+ "x.__iter__() <==> iter(x)"),\r
+ TPSLOT("next", tp_iternext, slot_tp_iternext, wrap_next,\r
+ "x.next() -> the next value, or raise StopIteration"),\r
+ TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get,\r
+ "descr.__get__(obj[, type]) -> value"),\r
+ TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set,\r
+ "descr.__set__(obj, value)"),\r
+ TPSLOT("__delete__", tp_descr_set, slot_tp_descr_set,\r
+ wrap_descr_delete, "descr.__delete__(obj)"),\r
+ FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)wrap_init,\r
+ "x.__init__(...) initializes x; "\r
+ "see help(type(x)) for signature",\r
+ PyWrapperFlag_KEYWORDS),\r
+ TPSLOT("__new__", tp_new, slot_tp_new, NULL, ""),\r
+ TPSLOT("__del__", tp_del, slot_tp_del, NULL, ""),\r
+ BINSLOT("__add__", nb_add, slot_nb_add,\r
+ "+"),\r
+ RBINSLOT("__radd__", nb_add, slot_nb_add,\r
+ "+"),\r
+ BINSLOT("__sub__", nb_subtract, slot_nb_subtract,\r
+ "-"),\r
+ RBINSLOT("__rsub__", nb_subtract, slot_nb_subtract,\r
+ "-"),\r
+ BINSLOT("__mul__", nb_multiply, slot_nb_multiply,\r
+ "*"),\r
+ RBINSLOT("__rmul__", nb_multiply, slot_nb_multiply,\r
+ "*"),\r
+ BINSLOT("__div__", nb_divide, slot_nb_divide,\r
+ "/"),\r
+ RBINSLOT("__rdiv__", nb_divide, slot_nb_divide,\r
+ "/"),\r
+ BINSLOT("__mod__", nb_remainder, slot_nb_remainder,\r
+ "%"),\r
+ RBINSLOT("__rmod__", nb_remainder, slot_nb_remainder,\r
+ "%"),\r
+ BINSLOTNOTINFIX("__divmod__", nb_divmod, slot_nb_divmod,\r
+ "divmod(x, y)"),\r
+ RBINSLOTNOTINFIX("__rdivmod__", nb_divmod, slot_nb_divmod,\r
+ "divmod(y, x)"),\r
+ NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc,\r
+ "x.__pow__(y[, z]) <==> pow(x, y[, z])"),\r
+ NBSLOT("__rpow__", nb_power, slot_nb_power, wrap_ternaryfunc_r,\r
+ "y.__rpow__(x[, z]) <==> pow(x, y[, z])"),\r
+ UNSLOT("__neg__", nb_negative, slot_nb_negative, wrap_unaryfunc, "-x"),\r
+ UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+x"),\r
+ UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc,\r
+ "abs(x)"),\r
+ UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_inquirypred,\r
+ "x != 0"),\r
+ UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"),\r
+ BINSLOT("__lshift__", nb_lshift, slot_nb_lshift, "<<"),\r
+ RBINSLOT("__rlshift__", nb_lshift, slot_nb_lshift, "<<"),\r
+ BINSLOT("__rshift__", nb_rshift, slot_nb_rshift, ">>"),\r
+ RBINSLOT("__rrshift__", nb_rshift, slot_nb_rshift, ">>"),\r
+ BINSLOT("__and__", nb_and, slot_nb_and, "&"),\r
+ RBINSLOT("__rand__", nb_and, slot_nb_and, "&"),\r
+ BINSLOT("__xor__", nb_xor, slot_nb_xor, "^"),\r
+ RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"),\r
+ BINSLOT("__or__", nb_or, slot_nb_or, "|"),\r
+ RBINSLOT("__ror__", nb_or, slot_nb_or, "|"),\r
+ NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc,\r
+ "x.__coerce__(y) <==> coerce(x, y)"),\r
+ UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc,\r
+ "int(x)"),\r
+ UNSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc,\r
+ "long(x)"),\r
+ UNSLOT("__float__", nb_float, slot_nb_float, wrap_unaryfunc,\r
+ "float(x)"),\r
+ UNSLOT("__oct__", nb_oct, slot_nb_oct, wrap_unaryfunc,\r
+ "oct(x)"),\r
+ UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc,\r
+ "hex(x)"),\r
+ IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,\r
+ wrap_binaryfunc, "+="),\r
+ IBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract,\r
+ wrap_binaryfunc, "-="),\r
+ IBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply,\r
+ wrap_binaryfunc, "*="),\r
+ IBSLOT("__idiv__", nb_inplace_divide, slot_nb_inplace_divide,\r
+ wrap_binaryfunc, "/="),\r
+ IBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder,\r
+ wrap_binaryfunc, "%="),\r
+ IBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power,\r
+ wrap_binaryfunc, "**="),\r
+ IBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift,\r
+ wrap_binaryfunc, "<<="),\r
+ IBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift,\r
+ wrap_binaryfunc, ">>="),\r
+ IBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and,\r
+ wrap_binaryfunc, "&="),\r
+ IBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor,\r
+ wrap_binaryfunc, "^="),\r
+ IBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or,\r
+ wrap_binaryfunc, "|="),\r
+ BINSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide, "//"),\r
+ RBINSLOT("__rfloordiv__", nb_floor_divide, slot_nb_floor_divide, "//"),\r
+ BINSLOT("__truediv__", nb_true_divide, slot_nb_true_divide, "/"),\r
+ RBINSLOT("__rtruediv__", nb_true_divide, slot_nb_true_divide, "/"),\r
+ IBSLOT("__ifloordiv__", nb_inplace_floor_divide,\r
+ slot_nb_inplace_floor_divide, wrap_binaryfunc, "//="),\r
+ IBSLOT("__itruediv__", nb_inplace_true_divide,\r
+ slot_nb_inplace_true_divide, wrap_binaryfunc, "/="),\r
+ NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc,\r
+ "x[y:z] <==> x[y.__index__():z.__index__()]"),\r
+ MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc,\r
+ "x.__len__() <==> len(x)"),\r
+ MPSLOT("__getitem__", mp_subscript, slot_mp_subscript,\r
+ wrap_binaryfunc,\r
+ "x.__getitem__(y) <==> x[y]"),\r
+ MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript,\r
+ wrap_objobjargproc,\r
+ "x.__setitem__(i, y) <==> x[i]=y"),\r
+ MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript,\r
+ wrap_delitem,\r
+ "x.__delitem__(y) <==> del x[y]"),\r
+ SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,\r
+ "x.__len__() <==> len(x)"),\r
+ /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.\r
+ The logic in abstract.c always falls back to nb_add/nb_multiply in\r
+ this case. Defining both the nb_* and the sq_* slots to call the\r
+ user-defined methods has unexpected side-effects, as shown by\r
+ test_descr.notimplemented() */\r
+ SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc,\r
+ "x.__add__(y) <==> x+y"),\r
+ SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc,\r
+ "x.__mul__(n) <==> x*n"),\r
+ SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc,\r
+ "x.__rmul__(n) <==> n*x"),\r
+ SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item,\r
+ "x.__getitem__(y) <==> x[y]"),\r
+ SQSLOT("__getslice__", sq_slice, slot_sq_slice, wrap_ssizessizeargfunc,\r
+ "x.__getslice__(i, j) <==> x[i:j]\n\\r
+ \n\\r
+ Use of negative indices is not supported."),\r
+ SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem,\r
+ "x.__setitem__(i, y) <==> x[i]=y"),\r
+ SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem,\r
+ "x.__delitem__(y) <==> del x[y]"),\r
+ SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice,\r
+ wrap_ssizessizeobjargproc,\r
+ "x.__setslice__(i, j, y) <==> x[i:j]=y\n\\r
+ \n\\r
+ Use of negative indices is not supported."),\r
+ SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice,\r
+ "x.__delslice__(i, j) <==> del x[i:j]\n\\r
+ \n\\r
+ Use of negative indices is not supported."),\r
+ SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc,\r
+ "x.__contains__(y) <==> y in x"),\r
+ SQSLOT("__iadd__", sq_inplace_concat, NULL,\r
+ wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"),\r
+ SQSLOT("__imul__", sq_inplace_repeat, NULL,\r
+ wrap_indexargfunc, "x.__imul__(y) <==> x*=y"),\r
+ {NULL}\r
+};\r
+\r
+/* Given a type pointer and an offset gotten from a slotdef entry, return a\r
+ pointer to the actual slot. This is not quite the same as simply adding\r
+ the offset to the type pointer, since it takes care to indirect through the\r
+ proper indirection pointer (as_buffer, etc.); it returns NULL if the\r
+ indirection pointer is NULL. */\r
+static void **\r
+slotptr(PyTypeObject *type, int ioffset)\r
+{\r
+ char *ptr;\r
+ long offset = ioffset;\r
+\r
+ /* Note: this depends on the order of the members of PyHeapTypeObject! */\r
+ assert(offset >= 0);\r
+ assert((size_t)offset < offsetof(PyHeapTypeObject, as_buffer));\r
+ if ((size_t)offset >= offsetof(PyHeapTypeObject, as_sequence)) {\r
+ ptr = (char *)type->tp_as_sequence;\r
+ offset -= offsetof(PyHeapTypeObject, as_sequence);\r
+ }\r
+ else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_mapping)) {\r
+ ptr = (char *)type->tp_as_mapping;\r
+ offset -= offsetof(PyHeapTypeObject, as_mapping);\r
+ }\r
+ else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_number)) {\r
+ ptr = (char *)type->tp_as_number;\r
+ offset -= offsetof(PyHeapTypeObject, as_number);\r
+ }\r
+ else {\r
+ ptr = (char *)type;\r
+ }\r
+ if (ptr != NULL)\r
+ ptr += offset;\r
+ return (void **)ptr;\r
+}\r
+\r
+/* Length of array of slotdef pointers used to store slots with the\r
+ same __name__. There should be at most MAX_EQUIV-1 slotdef entries with\r
+ the same __name__, for any __name__. Since that's a static property, it is\r
+ appropriate to declare fixed-size arrays for this. */\r
+#define MAX_EQUIV 10\r
+\r
+/* Return a slot pointer for a given name, but ONLY if the attribute has\r
+ exactly one slot function. The name must be an interned string. */\r
+static void **\r
+resolve_slotdups(PyTypeObject *type, PyObject *name)\r
+{\r
+ /* XXX Maybe this could be optimized more -- but is it worth it? */\r
+\r
+ /* pname and ptrs act as a little cache */\r
+ static PyObject *pname;\r
+ static slotdef *ptrs[MAX_EQUIV];\r
+ slotdef *p, **pp;\r
+ void **res, **ptr;\r
+\r
+ if (pname != name) {\r
+ /* Collect all slotdefs that match name into ptrs. */\r
+ pname = name;\r
+ pp = ptrs;\r
+ for (p = slotdefs; p->name_strobj; p++) {\r
+ if (p->name_strobj == name)\r
+ *pp++ = p;\r
+ }\r
+ *pp = NULL;\r
+ }\r
+\r
+ /* Look in all matching slots of the type; if exactly one of these has\r
+ a filled-in slot, return its value. Otherwise return NULL. */\r
+ res = NULL;\r
+ for (pp = ptrs; *pp; pp++) {\r
+ ptr = slotptr(type, (*pp)->offset);\r
+ if (ptr == NULL || *ptr == NULL)\r
+ continue;\r
+ if (res != NULL)\r
+ return NULL;\r
+ res = ptr;\r
+ }\r
+ return res;\r
+}\r
+\r
+/* Common code for update_slots_callback() and fixup_slot_dispatchers(). This\r
+ does some incredibly complex thinking and then sticks something into the\r
+ slot. (It sees if the adjacent slotdefs for the same slot have conflicting\r
+ interests, and then stores a generic wrapper or a specific function into\r
+ the slot.) Return a pointer to the next slotdef with a different offset,\r
+ because that's convenient for fixup_slot_dispatchers(). */\r
+static slotdef *\r
+update_one_slot(PyTypeObject *type, slotdef *p)\r
+{\r
+ PyObject *descr;\r
+ PyWrapperDescrObject *d;\r
+ void *generic = NULL, *specific = NULL;\r
+ int use_generic = 0;\r
+ int offset = p->offset;\r
+ void **ptr = slotptr(type, offset);\r
+\r
+ if (ptr == NULL) {\r
+ do {\r
+ ++p;\r
+ } while (p->offset == offset);\r
+ return p;\r
+ }\r
+ do {\r
+ descr = _PyType_Lookup(type, p->name_strobj);\r
+ if (descr == NULL) {\r
+ if (ptr == (void**)&type->tp_iternext) {\r
+ specific = _PyObject_NextNotImplemented;\r
+ }\r
+ continue;\r
+ }\r
+ if (Py_TYPE(descr) == &PyWrapperDescr_Type &&\r
+ ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) {\r
+ void **tptr = resolve_slotdups(type, p->name_strobj);\r
+ if (tptr == NULL || tptr == ptr)\r
+ generic = p->function;\r
+ d = (PyWrapperDescrObject *)descr;\r
+ if (d->d_base->wrapper == p->wrapper &&\r
+ PyType_IsSubtype(type, d->d_type))\r
+ {\r
+ if (specific == NULL ||\r
+ specific == d->d_wrapped)\r
+ specific = d->d_wrapped;\r
+ else\r
+ use_generic = 1;\r
+ }\r
+ }\r
+ else if (Py_TYPE(descr) == &PyCFunction_Type &&\r
+ PyCFunction_GET_FUNCTION(descr) ==\r
+ (PyCFunction)tp_new_wrapper &&\r
+ ptr == (void**)&type->tp_new)\r
+ {\r
+ /* The __new__ wrapper is not a wrapper descriptor,\r
+ so must be special-cased differently.\r
+ If we don't do this, creating an instance will\r
+ always use slot_tp_new which will look up\r
+ __new__ in the MRO which will call tp_new_wrapper\r
+ which will look through the base classes looking\r
+ for a static base and call its tp_new (usually\r
+ PyType_GenericNew), after performing various\r
+ sanity checks and constructing a new argument\r
+ list. Cut all that nonsense short -- this speeds\r
+ up instance creation tremendously. */\r
+ specific = (void *)type->tp_new;\r
+ /* XXX I'm not 100% sure that there isn't a hole\r
+ in this reasoning that requires additional\r
+ sanity checks. I'll buy the first person to\r
+ point out a bug in this reasoning a beer. */\r
+ }\r
+ else if (descr == Py_None &&\r
+ ptr == (void**)&type->tp_hash) {\r
+ /* We specifically allow __hash__ to be set to None\r
+ to prevent inheritance of the default\r
+ implementation from object.__hash__ */\r
+ specific = PyObject_HashNotImplemented;\r
+ }\r
+ else {\r
+ use_generic = 1;\r
+ generic = p->function;\r
+ }\r
+ } while ((++p)->offset == offset);\r
+ if (specific && !use_generic)\r
+ *ptr = specific;\r
+ else\r
+ *ptr = generic;\r
+ return p;\r
+}\r
+\r
+/* In the type, update the slots whose slotdefs are gathered in the pp array.\r
+ This is a callback for update_subclasses(). */\r
+static int\r
+update_slots_callback(PyTypeObject *type, void *data)\r
+{\r
+ slotdef **pp = (slotdef **)data;\r
+\r
+ for (; *pp; pp++)\r
+ update_one_slot(type, *pp);\r
+ return 0;\r
+}\r
+\r
+/* Initialize the slotdefs table by adding interned string objects for the\r
+ names and sorting the entries. */\r
+static void\r
+init_slotdefs(void)\r
+{\r
+ slotdef *p;\r
+ static int initialized = 0;\r
+\r
+ if (initialized)\r
+ return;\r
+ for (p = slotdefs; p->name; p++) {\r
+ /* Slots must be ordered by their offset in the PyHeapTypeObject. */\r
+ assert(!p[1].name || p->offset <= p[1].offset);\r
+ p->name_strobj = PyString_InternFromString(p->name);\r
+ if (!p->name_strobj)\r
+ Py_FatalError("Out of memory interning slotdef names");\r
+ }\r
+ initialized = 1;\r
+}\r
+\r
+/* Update the slots after assignment to a class (type) attribute. */\r
+static int\r
+update_slot(PyTypeObject *type, PyObject *name)\r
+{\r
+ slotdef *ptrs[MAX_EQUIV];\r
+ slotdef *p;\r
+ slotdef **pp;\r
+ int offset;\r
+\r
+ /* Clear the VALID_VERSION flag of 'type' and all its\r
+ subclasses. This could possibly be unified with the\r
+ update_subclasses() recursion below, but carefully:\r
+ they each have their own conditions on which to stop\r
+ recursing into subclasses. */\r
+ PyType_Modified(type);\r
+\r
+ init_slotdefs();\r
+ pp = ptrs;\r
+ for (p = slotdefs; p->name; p++) {\r
+ /* XXX assume name is interned! */\r
+ if (p->name_strobj == name)\r
+ *pp++ = p;\r
+ }\r
+ *pp = NULL;\r
+ for (pp = ptrs; *pp; pp++) {\r
+ p = *pp;\r
+ offset = p->offset;\r
+ while (p > slotdefs && (p-1)->offset == offset)\r
+ --p;\r
+ *pp = p;\r
+ }\r
+ if (ptrs[0] == NULL)\r
+ return 0; /* Not an attribute that affects any slots */\r
+ return update_subclasses(type, name,\r
+ update_slots_callback, (void *)ptrs);\r
+}\r
+\r
+/* Store the proper functions in the slot dispatches at class (type)\r
+ definition time, based upon which operations the class overrides in its\r
+ dict. */\r
+static void\r
+fixup_slot_dispatchers(PyTypeObject *type)\r
+{\r
+ slotdef *p;\r
+\r
+ init_slotdefs();\r
+ for (p = slotdefs; p->name; )\r
+ p = update_one_slot(type, p);\r
+}\r
+\r
+static void\r
+update_all_slots(PyTypeObject* type)\r
+{\r
+ slotdef *p;\r
+\r
+ init_slotdefs();\r
+ for (p = slotdefs; p->name; p++) {\r
+ /* update_slot returns int but can't actually fail */\r
+ update_slot(type, p->name_strobj);\r
+ }\r
+}\r
+\r
+/* recurse_down_subclasses() and update_subclasses() are mutually\r
+ recursive functions to call a callback for all subclasses,\r
+ but refraining from recursing into subclasses that define 'name'. */\r
+\r
+static int\r
+update_subclasses(PyTypeObject *type, PyObject *name,\r
+ update_callback callback, void *data)\r
+{\r
+ if (callback(type, data) < 0)\r
+ return -1;\r
+ return recurse_down_subclasses(type, name, callback, data);\r
+}\r
+\r
+static int\r
+recurse_down_subclasses(PyTypeObject *type, PyObject *name,\r
+ update_callback callback, void *data)\r
+{\r
+ PyTypeObject *subclass;\r
+ PyObject *ref, *subclasses, *dict;\r
+ Py_ssize_t i, n;\r
+\r
+ subclasses = type->tp_subclasses;\r
+ if (subclasses == NULL)\r
+ return 0;\r
+ assert(PyList_Check(subclasses));\r
+ n = PyList_GET_SIZE(subclasses);\r
+ for (i = 0; i < n; i++) {\r
+ ref = PyList_GET_ITEM(subclasses, i);\r
+ assert(PyWeakref_CheckRef(ref));\r
+ subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref);\r
+ assert(subclass != NULL);\r
+ if ((PyObject *)subclass == Py_None)\r
+ continue;\r
+ assert(PyType_Check(subclass));\r
+ /* Avoid recursing down into unaffected classes */\r
+ dict = subclass->tp_dict;\r
+ if (dict != NULL && PyDict_Check(dict) &&\r
+ PyDict_GetItem(dict, name) != NULL)\r
+ continue;\r
+ if (update_subclasses(subclass, name, callback, data) < 0)\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+/* This function is called by PyType_Ready() to populate the type's\r
+ dictionary with method descriptors for function slots. For each\r
+ function slot (like tp_repr) that's defined in the type, one or more\r
+ corresponding descriptors are added in the type's tp_dict dictionary\r
+ under the appropriate name (like __repr__). Some function slots\r
+ cause more than one descriptor to be added (for example, the nb_add\r
+ slot adds both __add__ and __radd__ descriptors) and some function\r
+ slots compete for the same descriptor (for example both sq_item and\r
+ mp_subscript generate a __getitem__ descriptor).\r
+\r
+ In the latter case, the first slotdef entry encountered wins. Since\r
+ slotdef entries are sorted by the offset of the slot in the\r
+ PyHeapTypeObject, this gives us some control over disambiguating\r
+ between competing slots: the members of PyHeapTypeObject are listed\r
+ from most general to least general, so the most general slot is\r
+ preferred. In particular, because as_mapping comes before as_sequence,\r
+ for a type that defines both mp_subscript and sq_item, mp_subscript\r
+ wins.\r
+\r
+ This only adds new descriptors and doesn't overwrite entries in\r
+ tp_dict that were previously defined. The descriptors contain a\r
+ reference to the C function they must call, so that it's safe if they\r
+ are copied into a subtype's __dict__ and the subtype has a different\r
+ C function in its slot -- calling the method defined by the\r
+ descriptor will call the C function that was used to create it,\r
+ rather than the C function present in the slot when it is called.\r
+ (This is important because a subtype may have a C function in the\r
+ slot that calls the method from the dictionary, and we want to avoid\r
+ infinite recursion here.) */\r
+\r
+static int\r
+add_operators(PyTypeObject *type)\r
+{\r
+ PyObject *dict = type->tp_dict;\r
+ slotdef *p;\r
+ PyObject *descr;\r
+ void **ptr;\r
+\r
+ init_slotdefs();\r
+ for (p = slotdefs; p->name; p++) {\r
+ if (p->wrapper == NULL)\r
+ continue;\r
+ ptr = slotptr(type, p->offset);\r
+ if (!ptr || !*ptr)\r
+ continue;\r
+ if (PyDict_GetItem(dict, p->name_strobj))\r
+ continue;\r
+ if (*ptr == PyObject_HashNotImplemented) {\r
+ /* Classes may prevent the inheritance of the tp_hash\r
+ slot by storing PyObject_HashNotImplemented in it. Make it\r
+ visible as a None value for the __hash__ attribute. */\r
+ if (PyDict_SetItem(dict, p->name_strobj, Py_None) < 0)\r
+ return -1;\r
+ }\r
+ else {\r
+ descr = PyDescr_NewWrapper(type, p, *ptr);\r
+ if (descr == NULL)\r
+ return -1;\r
+ if (PyDict_SetItem(dict, p->name_strobj, descr) < 0)\r
+ return -1;\r
+ Py_DECREF(descr);\r
+ }\r
+ }\r
+ if (type->tp_new != NULL) {\r
+ if (add_tp_new_wrapper(type) < 0)\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+\r
+/* Cooperative 'super' */\r
+\r
+typedef struct {\r
+ PyObject_HEAD\r
+ PyTypeObject *type;\r
+ PyObject *obj;\r
+ PyTypeObject *obj_type;\r
+} superobject;\r
+\r
+static PyMemberDef super_members[] = {\r
+ {"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY,\r
+ "the class invoking super()"},\r
+ {"__self__", T_OBJECT, offsetof(superobject, obj), READONLY,\r
+ "the instance invoking super(); may be None"},\r
+ {"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY,\r
+ "the type of the instance invoking super(); may be None"},\r
+ {0}\r
+};\r
+\r
+static void\r
+super_dealloc(PyObject *self)\r
+{\r
+ superobject *su = (superobject *)self;\r
+\r
+ _PyObject_GC_UNTRACK(self);\r
+ Py_XDECREF(su->obj);\r
+ Py_XDECREF(su->type);\r
+ Py_XDECREF(su->obj_type);\r
+ Py_TYPE(self)->tp_free(self);\r
+}\r
+\r
+static PyObject *\r
+super_repr(PyObject *self)\r
+{\r
+ superobject *su = (superobject *)self;\r
+\r
+ if (su->obj_type)\r
+ return PyString_FromFormat(\r
+ "<super: <class '%s'>, <%s object>>",\r
+ su->type ? su->type->tp_name : "NULL",\r
+ su->obj_type->tp_name);\r
+ else\r
+ return PyString_FromFormat(\r
+ "<super: <class '%s'>, NULL>",\r
+ su->type ? su->type->tp_name : "NULL");\r
+}\r
+\r
+static PyObject *\r
+super_getattro(PyObject *self, PyObject *name)\r
+{\r
+ superobject *su = (superobject *)self;\r
+ int skip = su->obj_type == NULL;\r
+\r
+ if (!skip) {\r
+ /* We want __class__ to return the class of the super object\r
+ (i.e. super, or a subclass), not the class of su->obj. */\r
+ skip = (PyString_Check(name) &&\r
+ PyString_GET_SIZE(name) == 9 &&\r
+ strcmp(PyString_AS_STRING(name), "__class__") == 0);\r
+ }\r
+\r
+ if (!skip) {\r
+ PyObject *mro, *res, *tmp, *dict;\r
+ PyTypeObject *starttype;\r
+ descrgetfunc f;\r
+ Py_ssize_t i, n;\r
+\r
+ starttype = su->obj_type;\r
+ mro = starttype->tp_mro;\r
+\r
+ if (mro == NULL)\r
+ n = 0;\r
+ else {\r
+ assert(PyTuple_Check(mro));\r
+ n = PyTuple_GET_SIZE(mro);\r
+ }\r
+ for (i = 0; i < n; i++) {\r
+ if ((PyObject *)(su->type) == PyTuple_GET_ITEM(mro, i))\r
+ break;\r
+ }\r
+ i++;\r
+ res = NULL;\r
+ for (; i < n; i++) {\r
+ tmp = PyTuple_GET_ITEM(mro, i);\r
+ if (PyType_Check(tmp))\r
+ dict = ((PyTypeObject *)tmp)->tp_dict;\r
+ else if (PyClass_Check(tmp))\r
+ dict = ((PyClassObject *)tmp)->cl_dict;\r
+ else\r
+ continue;\r
+ res = PyDict_GetItem(dict, name);\r
+ if (res != NULL) {\r
+ Py_INCREF(res);\r
+ f = Py_TYPE(res)->tp_descr_get;\r
+ if (f != NULL) {\r
+ tmp = f(res,\r
+ /* Only pass 'obj' param if\r
+ this is instance-mode super\r
+ (See SF ID #743627)\r
+ */\r
+ (su->obj == (PyObject *)\r
+ su->obj_type\r
+ ? (PyObject *)NULL\r
+ : su->obj),\r
+ (PyObject *)starttype);\r
+ Py_DECREF(res);\r
+ res = tmp;\r
+ }\r
+ return res;\r
+ }\r
+ }\r
+ }\r
+ return PyObject_GenericGetAttr(self, name);\r
+}\r
+\r
+static PyTypeObject *\r
+supercheck(PyTypeObject *type, PyObject *obj)\r
+{\r
+ /* Check that a super() call makes sense. Return a type object.\r
+\r
+ obj can be a new-style class, or an instance of one:\r
+\r
+ - If it is a class, it must be a subclass of 'type'. This case is\r
+ used for class methods; the return value is obj.\r
+\r
+ - If it is an instance, it must be an instance of 'type'. This is\r
+ the normal case; the return value is obj.__class__.\r
+\r
+ But... when obj is an instance, we want to allow for the case where\r
+ Py_TYPE(obj) is not a subclass of type, but obj.__class__ is!\r
+ This will allow using super() with a proxy for obj.\r
+ */\r
+\r
+ /* Check for first bullet above (special case) */\r
+ if (PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, type)) {\r
+ Py_INCREF(obj);\r
+ return (PyTypeObject *)obj;\r
+ }\r
+\r
+ /* Normal case */\r
+ if (PyType_IsSubtype(Py_TYPE(obj), type)) {\r
+ Py_INCREF(Py_TYPE(obj));\r
+ return Py_TYPE(obj);\r
+ }\r
+ else {\r
+ /* Try the slow way */\r
+ static PyObject *class_str = NULL;\r
+ PyObject *class_attr;\r
+\r
+ if (class_str == NULL) {\r
+ class_str = PyString_FromString("__class__");\r
+ if (class_str == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ class_attr = PyObject_GetAttr(obj, class_str);\r
+\r
+ if (class_attr != NULL &&\r
+ PyType_Check(class_attr) &&\r
+ (PyTypeObject *)class_attr != Py_TYPE(obj))\r
+ {\r
+ int ok = PyType_IsSubtype(\r
+ (PyTypeObject *)class_attr, type);\r
+ if (ok)\r
+ return (PyTypeObject *)class_attr;\r
+ }\r
+\r
+ if (class_attr == NULL)\r
+ PyErr_Clear();\r
+ else\r
+ Py_DECREF(class_attr);\r
+ }\r
+\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "super(type, obj): "\r
+ "obj must be an instance or subtype of type");\r
+ return NULL;\r
+}\r
+\r
+static PyObject *\r
+super_descr_get(PyObject *self, PyObject *obj, PyObject *type)\r
+{\r
+ superobject *su = (superobject *)self;\r
+ superobject *newobj;\r
+\r
+ if (obj == NULL || obj == Py_None || su->obj != NULL) {\r
+ /* Not binding to an object, or already bound */\r
+ Py_INCREF(self);\r
+ return self;\r
+ }\r
+ if (Py_TYPE(su) != &PySuper_Type)\r
+ /* If su is an instance of a (strict) subclass of super,\r
+ call its type */\r
+ return PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(su),\r
+ su->type, obj, NULL);\r
+ else {\r
+ /* Inline the common case */\r
+ PyTypeObject *obj_type = supercheck(su->type, obj);\r
+ if (obj_type == NULL)\r
+ return NULL;\r
+ newobj = (superobject *)PySuper_Type.tp_new(&PySuper_Type,\r
+ NULL, NULL);\r
+ if (newobj == NULL)\r
+ return NULL;\r
+ Py_INCREF(su->type);\r
+ Py_INCREF(obj);\r
+ newobj->type = su->type;\r
+ newobj->obj = obj;\r
+ newobj->obj_type = obj_type;\r
+ return (PyObject *)newobj;\r
+ }\r
+}\r
+\r
+static int\r
+super_init(PyObject *self, PyObject *args, PyObject *kwds)\r
+{\r
+ superobject *su = (superobject *)self;\r
+ PyTypeObject *type;\r
+ PyObject *obj = NULL;\r
+ PyTypeObject *obj_type = NULL;\r
+\r
+ if (!_PyArg_NoKeywords("super", kwds))\r
+ return -1;\r
+ if (!PyArg_ParseTuple(args, "O!|O:super", &PyType_Type, &type, &obj))\r
+ return -1;\r
+ if (obj == Py_None)\r
+ obj = NULL;\r
+ if (obj != NULL) {\r
+ obj_type = supercheck(type, obj);\r
+ if (obj_type == NULL)\r
+ return -1;\r
+ Py_INCREF(obj);\r
+ }\r
+ Py_INCREF(type);\r
+ su->type = type;\r
+ su->obj = obj;\r
+ su->obj_type = obj_type;\r
+ return 0;\r
+}\r
+\r
+PyDoc_STRVAR(super_doc,\r
+"super(type, obj) -> bound super object; requires isinstance(obj, type)\n"\r
+"super(type) -> unbound super object\n"\r
+"super(type, type2) -> bound super object; requires issubclass(type2, type)\n"\r
+"Typical use to call a cooperative superclass method:\n"\r
+"class C(B):\n"\r
+" def meth(self, arg):\n"\r
+" super(C, self).meth(arg)");\r
+\r
+static int\r
+super_traverse(PyObject *self, visitproc visit, void *arg)\r
+{\r
+ superobject *su = (superobject *)self;\r
+\r
+ Py_VISIT(su->obj);\r
+ Py_VISIT(su->type);\r
+ Py_VISIT(su->obj_type);\r
+\r
+ return 0;\r
+}\r
+\r
+PyTypeObject PySuper_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "super", /* tp_name */\r
+ sizeof(superobject), /* tp_basicsize */\r
+ 0, /* tp_itemsize */\r
+ /* methods */\r
+ super_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ super_repr, /* tp_repr */\r
+ 0, /* tp_as_number */\r
+ 0, /* tp_as_sequence */\r
+ 0, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ 0, /* tp_str */\r
+ super_getattro, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
+ Py_TPFLAGS_BASETYPE, /* tp_flags */\r
+ super_doc, /* tp_doc */\r
+ super_traverse, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ 0, /* tp_methods */\r
+ super_members, /* tp_members */\r
+ 0, /* tp_getset */\r
+ 0, /* tp_base */\r
+ 0, /* tp_dict */\r
+ super_descr_get, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ super_init, /* tp_init */\r
+ PyType_GenericAlloc, /* tp_alloc */\r
+ PyType_GenericNew, /* tp_new */\r
+ PyObject_GC_Del, /* tp_free */\r
+};\r
--- /dev/null
+/*\r
+ Unicode character type helpers.\r
+\r
+ Written by Marc-Andre Lemburg (mal@lemburg.com).\r
+ Modified for Python 2.0 by Fredrik Lundh (fredrik@pythonware.com)\r
+\r
+ Copyright (c) Corporation for National Research Initiatives.\r
+\r
+*/\r
+\r
+#include "Python.h"\r
+#include "unicodeobject.h"\r
+\r
+#define ALPHA_MASK 0x01\r
+#define DECIMAL_MASK 0x02\r
+#define DIGIT_MASK 0x04\r
+#define LOWER_MASK 0x08\r
+#define LINEBREAK_MASK 0x10\r
+#define SPACE_MASK 0x20\r
+#define TITLE_MASK 0x40\r
+#define UPPER_MASK 0x80\r
+#define NODELTA_MASK 0x100\r
+#define NUMERIC_MASK 0x200\r
+\r
+typedef struct {\r
+ const Py_UNICODE upper;\r
+ const Py_UNICODE lower;\r
+ const Py_UNICODE title;\r
+ const unsigned char decimal;\r
+ const unsigned char digit;\r
+ const unsigned short flags;\r
+} _PyUnicode_TypeRecord;\r
+\r
+#include "unicodetype_db.h"\r
+\r
+static const _PyUnicode_TypeRecord *\r
+gettyperecord(Py_UNICODE code)\r
+{\r
+ int index;\r
+\r
+#ifdef Py_UNICODE_WIDE\r
+ if (code >= 0x110000)\r
+ index = 0;\r
+ else\r
+#endif\r
+ {\r
+ index = index1[(code>>SHIFT)];\r
+ index = index2[(index<<SHIFT)+(code&((1<<SHIFT)-1))];\r
+ }\r
+\r
+ return &_PyUnicode_TypeRecords[index];\r
+}\r
+\r
+/* Returns the titlecase Unicode characters corresponding to ch or just\r
+ ch if no titlecase mapping is known. */\r
+\r
+Py_UNICODE _PyUnicode_ToTitlecase(register Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+ int delta = ctype->title;\r
+\r
+ if (ctype->flags & NODELTA_MASK)\r
+ return delta;\r
+\r
+ if (delta >= 32768)\r
+ delta -= 65536;\r
+\r
+ return ch + delta;\r
+}\r
+\r
+/* Returns 1 for Unicode characters having the category 'Lt', 0\r
+ otherwise. */\r
+\r
+int _PyUnicode_IsTitlecase(Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+\r
+ return (ctype->flags & TITLE_MASK) != 0;\r
+}\r
+\r
+/* Returns the integer decimal (0-9) for Unicode characters having\r
+ this property, -1 otherwise. */\r
+\r
+int _PyUnicode_ToDecimalDigit(Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+\r
+ return (ctype->flags & DECIMAL_MASK) ? ctype->decimal : -1;\r
+}\r
+\r
+int _PyUnicode_IsDecimalDigit(Py_UNICODE ch)\r
+{\r
+ if (_PyUnicode_ToDecimalDigit(ch) < 0)\r
+ return 0;\r
+ return 1;\r
+}\r
+\r
+/* Returns the integer digit (0-9) for Unicode characters having\r
+ this property, -1 otherwise. */\r
+\r
+int _PyUnicode_ToDigit(Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+\r
+ return (ctype->flags & DIGIT_MASK) ? ctype->digit : -1;\r
+}\r
+\r
+int _PyUnicode_IsDigit(Py_UNICODE ch)\r
+{\r
+ if (_PyUnicode_ToDigit(ch) < 0)\r
+ return 0;\r
+ return 1;\r
+}\r
+\r
+/* Returns the numeric value as double for Unicode characters having\r
+ this property, -1.0 otherwise. */\r
+\r
+int _PyUnicode_IsNumeric(Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+\r
+ return (ctype->flags & NUMERIC_MASK) != 0;\r
+}\r
+\r
+#ifndef WANT_WCTYPE_FUNCTIONS\r
+\r
+/* Returns 1 for Unicode characters having the category 'Ll', 0\r
+ otherwise. */\r
+\r
+int _PyUnicode_IsLowercase(Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+\r
+ return (ctype->flags & LOWER_MASK) != 0;\r
+}\r
+\r
+/* Returns 1 for Unicode characters having the category 'Lu', 0\r
+ otherwise. */\r
+\r
+int _PyUnicode_IsUppercase(Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+\r
+ return (ctype->flags & UPPER_MASK) != 0;\r
+}\r
+\r
+/* Returns the uppercase Unicode characters corresponding to ch or just\r
+ ch if no uppercase mapping is known. */\r
+\r
+Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+ int delta = ctype->upper;\r
+ if (ctype->flags & NODELTA_MASK)\r
+ return delta;\r
+ if (delta >= 32768)\r
+ delta -= 65536;\r
+ return ch + delta;\r
+}\r
+\r
+/* Returns the lowercase Unicode characters corresponding to ch or just\r
+ ch if no lowercase mapping is known. */\r
+\r
+Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+ int delta = ctype->lower;\r
+ if (ctype->flags & NODELTA_MASK)\r
+ return delta;\r
+ if (delta >= 32768)\r
+ delta -= 65536;\r
+ return ch + delta;\r
+}\r
+\r
+/* Returns 1 for Unicode characters having the category 'Ll', 'Lu', 'Lt',\r
+ 'Lo' or 'Lm', 0 otherwise. */\r
+\r
+int _PyUnicode_IsAlpha(Py_UNICODE ch)\r
+{\r
+ const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);\r
+\r
+ return (ctype->flags & ALPHA_MASK) != 0;\r
+}\r
+\r
+#else\r
+\r
+/* Export the interfaces using the wchar_t type for portability\r
+ reasons: */\r
+\r
+int _PyUnicode_IsLowercase(Py_UNICODE ch)\r
+{\r
+ return iswlower(ch);\r
+}\r
+\r
+int _PyUnicode_IsUppercase(Py_UNICODE ch)\r
+{\r
+ return iswupper(ch);\r
+}\r
+\r
+Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch)\r
+{\r
+ return towlower(ch);\r
+}\r
+\r
+Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch)\r
+{\r
+ return towupper(ch);\r
+}\r
+\r
+int _PyUnicode_IsAlpha(Py_UNICODE ch)\r
+{\r
+ return iswalpha(ch);\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+\r
+Unicode implementation based on original code by Fredrik Lundh,\r
+modified by Marc-Andre Lemburg <mal@lemburg.com> according to the\r
+Unicode Integration Proposal (see file Misc/unicode.txt).\r
+\r
+Major speed upgrades to the method implementations at the Reykjavik\r
+NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke.\r
+\r
+Copyright (c) Corporation for National Research Initiatives.\r
+\r
+--------------------------------------------------------------------\r
+The original string type implementation is:\r
+\r
+ Copyright (c) 1999 by Secret Labs AB\r
+ Copyright (c) 1999 by Fredrik Lundh\r
+\r
+By obtaining, using, and/or copying this software and/or its\r
+associated documentation, you agree that you have read, understood,\r
+and will comply with the following terms and conditions:\r
+\r
+Permission to use, copy, modify, and distribute this software and its\r
+associated documentation for any purpose and without fee is hereby\r
+granted, provided that the above copyright notice appears in all\r
+copies, and that both that copyright notice and this permission notice\r
+appear in supporting documentation, and that the name of Secret Labs\r
+AB or the author not be used in advertising or publicity pertaining to\r
+distribution of the software without specific, written prior\r
+permission.\r
+\r
+SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO\r
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR\r
+ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\r
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\r
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT\r
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+--------------------------------------------------------------------\r
+\r
+*/\r
+\r
+#define PY_SSIZE_T_CLEAN\r
+#include "Python.h"\r
+\r
+#include "unicodeobject.h"\r
+#include "ucnhash.h"\r
+\r
+#ifdef MS_WINDOWS\r
+#include <windows.h>\r
+#endif\r
+\r
+/* Limit for the Unicode object free list */\r
+\r
+#define PyUnicode_MAXFREELIST 1024\r
+\r
+/* Limit for the Unicode object free list stay alive optimization.\r
+\r
+ The implementation will keep allocated Unicode memory intact for\r
+ all objects on the free list having a size less than this\r
+ limit. This reduces malloc() overhead for small Unicode objects.\r
+\r
+ At worst this will result in PyUnicode_MAXFREELIST *\r
+ (sizeof(PyUnicodeObject) + KEEPALIVE_SIZE_LIMIT +\r
+ malloc()-overhead) bytes of unused garbage.\r
+\r
+ Setting the limit to 0 effectively turns the feature off.\r
+\r
+ Note: This is an experimental feature ! If you get core dumps when\r
+ using Unicode objects, turn this feature off.\r
+\r
+*/\r
+\r
+#define KEEPALIVE_SIZE_LIMIT 9\r
+\r
+/* Endianness switches; defaults to little endian */\r
+\r
+#ifdef WORDS_BIGENDIAN\r
+# define BYTEORDER_IS_BIG_ENDIAN\r
+#else\r
+# define BYTEORDER_IS_LITTLE_ENDIAN\r
+#endif\r
+\r
+/* --- Globals ------------------------------------------------------------\r
+\r
+NOTE: In the interpreter's initialization phase, some globals are currently\r
+ initialized dynamically as needed. In the process Unicode objects may\r
+ be created before the Unicode type is ready.\r
+\r
+*/\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* Free list for Unicode objects */\r
+static PyUnicodeObject *free_list = NULL;\r
+static int numfree = 0;\r
+\r
+/* The empty Unicode object is shared to improve performance. */\r
+static PyUnicodeObject *unicode_empty = NULL;\r
+\r
+#define _Py_RETURN_UNICODE_EMPTY() \\r
+ do { \\r
+ if (unicode_empty != NULL) \\r
+ Py_INCREF(unicode_empty); \\r
+ else { \\r
+ unicode_empty = _PyUnicode_New(0); \\r
+ if (unicode_empty != NULL) \\r
+ Py_INCREF(unicode_empty); \\r
+ } \\r
+ return (PyObject *)unicode_empty; \\r
+ } while (0)\r
+\r
+/* Single character Unicode strings in the Latin-1 range are being\r
+ shared as well. */\r
+static PyUnicodeObject *unicode_latin1[256] = {NULL};\r
+\r
+/* Default encoding to use and assume when NULL is passed as encoding\r
+ parameter; it is initialized by _PyUnicode_Init().\r
+\r
+ Always use the PyUnicode_SetDefaultEncoding() and\r
+ PyUnicode_GetDefaultEncoding() APIs to access this global.\r
+\r
+*/\r
+static char unicode_default_encoding[100 + 1] = "ascii";\r
+\r
+/* Fast detection of the most frequent whitespace characters */\r
+const unsigned char _Py_ascii_whitespace[] = {\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+/* case 0x0009: * CHARACTER TABULATION */\r
+/* case 0x000A: * LINE FEED */\r
+/* case 0x000B: * LINE TABULATION */\r
+/* case 0x000C: * FORM FEED */\r
+/* case 0x000D: * CARRIAGE RETURN */\r
+ 0, 1, 1, 1, 1, 1, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+/* case 0x001C: * FILE SEPARATOR */\r
+/* case 0x001D: * GROUP SEPARATOR */\r
+/* case 0x001E: * RECORD SEPARATOR */\r
+/* case 0x001F: * UNIT SEPARATOR */\r
+ 0, 0, 0, 0, 1, 1, 1, 1,\r
+/* case 0x0020: * SPACE */\r
+ 1, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+\r
+/* Same for linebreaks */\r
+static unsigned char ascii_linebreak[] = {\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+/* 0x000A, * LINE FEED */\r
+/* 0x000B, * LINE TABULATION */\r
+/* 0x000C, * FORM FEED */\r
+/* 0x000D, * CARRIAGE RETURN */\r
+ 0, 0, 1, 1, 1, 1, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+/* 0x001C, * FILE SEPARATOR */\r
+/* 0x001D, * GROUP SEPARATOR */\r
+/* 0x001E, * RECORD SEPARATOR */\r
+ 0, 0, 0, 0, 1, 1, 1, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+\r
+\r
+Py_UNICODE\r
+PyUnicode_GetMax(void)\r
+{\r
+#ifdef Py_UNICODE_WIDE\r
+ return 0x10FFFF;\r
+#else\r
+ /* This is actually an illegal character, so it should\r
+ not be passed to unichr. */\r
+ return 0xFFFF;\r
+#endif\r
+}\r
+\r
+/* --- Bloom Filters ----------------------------------------------------- */\r
+\r
+/* stuff to implement simple "bloom filters" for Unicode characters.\r
+ to keep things simple, we use a single bitmask, using the least 5\r
+ bits from each unicode characters as the bit index. */\r
+\r
+/* the linebreak mask is set up by Unicode_Init below */\r
+\r
+#if LONG_BIT >= 128\r
+#define BLOOM_WIDTH 128\r
+#elif LONG_BIT >= 64\r
+#define BLOOM_WIDTH 64\r
+#elif LONG_BIT >= 32\r
+#define BLOOM_WIDTH 32\r
+#else\r
+#error "LONG_BIT is smaller than 32"\r
+#endif\r
+\r
+#define BLOOM_MASK unsigned long\r
+\r
+static BLOOM_MASK bloom_linebreak = ~(BLOOM_MASK)0;\r
+\r
+#define BLOOM_ADD(mask, ch) ((mask |= (1UL << ((ch) & (BLOOM_WIDTH - 1)))))\r
+#define BLOOM(mask, ch) ((mask & (1UL << ((ch) & (BLOOM_WIDTH - 1)))))\r
+\r
+#define BLOOM_LINEBREAK(ch) \\r
+ ((ch) < 128U ? ascii_linebreak[(ch)] : \\r
+ (BLOOM(bloom_linebreak, (ch)) && Py_UNICODE_ISLINEBREAK(ch)))\r
+\r
+Py_LOCAL_INLINE(BLOOM_MASK) make_bloom_mask(Py_UNICODE* ptr, Py_ssize_t len)\r
+{\r
+ /* calculate simple bloom-style bitmask for a given unicode string */\r
+\r
+ BLOOM_MASK mask;\r
+ Py_ssize_t i;\r
+\r
+ mask = 0;\r
+ for (i = 0; i < len; i++)\r
+ BLOOM_ADD(mask, ptr[i]);\r
+\r
+ return mask;\r
+}\r
+\r
+Py_LOCAL_INLINE(int) unicode_member(Py_UNICODE chr, Py_UNICODE* set, Py_ssize_t setlen)\r
+{\r
+ Py_ssize_t i;\r
+\r
+ for (i = 0; i < setlen; i++)\r
+ if (set[i] == chr)\r
+ return 1;\r
+\r
+ return 0;\r
+}\r
+\r
+#define BLOOM_MEMBER(mask, chr, set, setlen) \\r
+ BLOOM(mask, chr) && unicode_member(chr, set, setlen)\r
+\r
+/* --- Unicode Object ----------------------------------------------------- */\r
+\r
+static\r
+int unicode_resize(register PyUnicodeObject *unicode,\r
+ Py_ssize_t length)\r
+{\r
+ void *oldstr;\r
+\r
+ /* Shortcut if there's nothing much to do. */\r
+ if (unicode->length == length)\r
+ goto reset;\r
+\r
+ /* Resizing shared object (unicode_empty or single character\r
+ objects) in-place is not allowed. Use PyUnicode_Resize()\r
+ instead ! */\r
+\r
+ if (unicode == unicode_empty ||\r
+ (unicode->length == 1 &&\r
+ unicode->str[0] < 256U &&\r
+ unicode_latin1[unicode->str[0]] == unicode)) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "can't resize shared unicode objects");\r
+ return -1;\r
+ }\r
+\r
+ /* We allocate one more byte to make sure the string is Ux0000 terminated.\r
+ The overallocation is also used by fastsearch, which assumes that it's\r
+ safe to look at str[length] (without making any assumptions about what\r
+ it contains). */\r
+\r
+ oldstr = unicode->str;\r
+ unicode->str = PyObject_REALLOC(unicode->str,\r
+ sizeof(Py_UNICODE) * (length + 1));\r
+ if (!unicode->str) {\r
+ unicode->str = (Py_UNICODE *)oldstr;\r
+ PyErr_NoMemory();\r
+ return -1;\r
+ }\r
+ unicode->str[length] = 0;\r
+ unicode->length = length;\r
+\r
+ reset:\r
+ /* Reset the object caches */\r
+ if (unicode->defenc) {\r
+ Py_CLEAR(unicode->defenc);\r
+ }\r
+ unicode->hash = -1;\r
+\r
+ return 0;\r
+}\r
+\r
+/* We allocate one more byte to make sure the string is\r
+ Ux0000 terminated; some code relies on that.\r
+\r
+ XXX This allocator could further be enhanced by assuring that the\r
+ free list never reduces its size below 1.\r
+\r
+*/\r
+\r
+static\r
+PyUnicodeObject *_PyUnicode_New(Py_ssize_t length)\r
+{\r
+ register PyUnicodeObject *unicode;\r
+\r
+ /* Optimization for empty strings */\r
+ if (length == 0 && unicode_empty != NULL) {\r
+ Py_INCREF(unicode_empty);\r
+ return unicode_empty;\r
+ }\r
+\r
+ /* Ensure we won't overflow the size. */\r
+ if (length > ((PY_SSIZE_T_MAX / sizeof(Py_UNICODE)) - 1)) {\r
+ return (PyUnicodeObject *)PyErr_NoMemory();\r
+ }\r
+\r
+ /* Unicode freelist & memory allocation */\r
+ if (free_list) {\r
+ unicode = free_list;\r
+ free_list = *(PyUnicodeObject **)unicode;\r
+ numfree--;\r
+ if (unicode->str) {\r
+ /* Keep-Alive optimization: we only upsize the buffer,\r
+ never downsize it. */\r
+ if ((unicode->length < length) &&\r
+ unicode_resize(unicode, length) < 0) {\r
+ PyObject_DEL(unicode->str);\r
+ unicode->str = NULL;\r
+ }\r
+ }\r
+ else {\r
+ size_t new_size = sizeof(Py_UNICODE) * ((size_t)length + 1);\r
+ unicode->str = (Py_UNICODE*) PyObject_MALLOC(new_size);\r
+ }\r
+ PyObject_INIT(unicode, &PyUnicode_Type);\r
+ }\r
+ else {\r
+ size_t new_size;\r
+ unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type);\r
+ if (unicode == NULL)\r
+ return NULL;\r
+ new_size = sizeof(Py_UNICODE) * ((size_t)length + 1);\r
+ unicode->str = (Py_UNICODE*) PyObject_MALLOC(new_size);\r
+ }\r
+\r
+ if (!unicode->str) {\r
+ PyErr_NoMemory();\r
+ goto onError;\r
+ }\r
+ /* Initialize the first element to guard against cases where\r
+ * the caller fails before initializing str -- unicode_resize()\r
+ * reads str[0], and the Keep-Alive optimization can keep memory\r
+ * allocated for str alive across a call to unicode_dealloc(unicode).\r
+ * We don't want unicode_resize to read uninitialized memory in\r
+ * that case.\r
+ */\r
+ unicode->str[0] = 0;\r
+ unicode->str[length] = 0;\r
+ unicode->length = length;\r
+ unicode->hash = -1;\r
+ unicode->defenc = NULL;\r
+ return unicode;\r
+\r
+ onError:\r
+ /* XXX UNREF/NEWREF interface should be more symmetrical */\r
+ _Py_DEC_REFTOTAL;\r
+ _Py_ForgetReference((PyObject *)unicode);\r
+ PyObject_Del(unicode);\r
+ return NULL;\r
+}\r
+\r
+static\r
+void unicode_dealloc(register PyUnicodeObject *unicode)\r
+{\r
+ if (PyUnicode_CheckExact(unicode) &&\r
+ numfree < PyUnicode_MAXFREELIST) {\r
+ /* Keep-Alive optimization */\r
+ if (unicode->length >= KEEPALIVE_SIZE_LIMIT) {\r
+ PyObject_DEL(unicode->str);\r
+ unicode->str = NULL;\r
+ unicode->length = 0;\r
+ }\r
+ if (unicode->defenc) {\r
+ Py_CLEAR(unicode->defenc);\r
+ }\r
+ /* Add to free list */\r
+ *(PyUnicodeObject **)unicode = free_list;\r
+ free_list = unicode;\r
+ numfree++;\r
+ }\r
+ else {\r
+ PyObject_DEL(unicode->str);\r
+ Py_XDECREF(unicode->defenc);\r
+ Py_TYPE(unicode)->tp_free((PyObject *)unicode);\r
+ }\r
+}\r
+\r
+static\r
+int _PyUnicode_Resize(PyUnicodeObject **unicode, Py_ssize_t length)\r
+{\r
+ register PyUnicodeObject *v;\r
+\r
+ /* Argument checks */\r
+ if (unicode == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+ v = *unicode;\r
+ if (v == NULL || !PyUnicode_Check(v) || Py_REFCNT(v) != 1 || length < 0) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+\r
+ /* Resizing unicode_empty and single character objects is not\r
+ possible since these are being shared. We simply return a fresh\r
+ copy with the same Unicode content. */\r
+ if (v->length != length &&\r
+ (v == unicode_empty || v->length == 1)) {\r
+ PyUnicodeObject *w = _PyUnicode_New(length);\r
+ if (w == NULL)\r
+ return -1;\r
+ Py_UNICODE_COPY(w->str, v->str,\r
+ length < v->length ? length : v->length);\r
+ Py_DECREF(*unicode);\r
+ *unicode = w;\r
+ return 0;\r
+ }\r
+\r
+ /* Note that we don't have to modify *unicode for unshared Unicode\r
+ objects, since we can modify them in-place. */\r
+ return unicode_resize(v, length);\r
+}\r
+\r
+int PyUnicode_Resize(PyObject **unicode, Py_ssize_t length)\r
+{\r
+ return _PyUnicode_Resize((PyUnicodeObject **)unicode, length);\r
+}\r
+\r
+PyObject *PyUnicode_FromUnicode(const Py_UNICODE *u,\r
+ Py_ssize_t size)\r
+{\r
+ PyUnicodeObject *unicode;\r
+\r
+ /* If the Unicode data is known at construction time, we can apply\r
+ some optimizations which share commonly used objects. */\r
+ if (u != NULL) {\r
+\r
+ /* Optimization for empty strings */\r
+ if (size == 0)\r
+ _Py_RETURN_UNICODE_EMPTY();\r
+\r
+ /* Single character Unicode objects in the Latin-1 range are\r
+ shared when using this constructor */\r
+ if (size == 1 && *u < 256) {\r
+ unicode = unicode_latin1[*u];\r
+ if (!unicode) {\r
+ unicode = _PyUnicode_New(1);\r
+ if (!unicode)\r
+ return NULL;\r
+ unicode->str[0] = *u;\r
+ unicode_latin1[*u] = unicode;\r
+ }\r
+ Py_INCREF(unicode);\r
+ return (PyObject *)unicode;\r
+ }\r
+ }\r
+\r
+ unicode = _PyUnicode_New(size);\r
+ if (!unicode)\r
+ return NULL;\r
+\r
+ /* Copy the Unicode data into the new object */\r
+ if (u != NULL)\r
+ Py_UNICODE_COPY(unicode->str, u, size);\r
+\r
+ return (PyObject *)unicode;\r
+}\r
+\r
+PyObject *PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size)\r
+{\r
+ PyUnicodeObject *unicode;\r
+\r
+ if (size < 0) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "Negative size passed to PyUnicode_FromStringAndSize");\r
+ return NULL;\r
+ }\r
+\r
+ /* If the Unicode data is known at construction time, we can apply\r
+ some optimizations which share commonly used objects.\r
+ Also, this means the input must be UTF-8, so fall back to the\r
+ UTF-8 decoder at the end. */\r
+ if (u != NULL) {\r
+\r
+ /* Optimization for empty strings */\r
+ if (size == 0)\r
+ _Py_RETURN_UNICODE_EMPTY();\r
+\r
+ /* Single characters are shared when using this constructor.\r
+ Restrict to ASCII, since the input must be UTF-8. */\r
+ if (size == 1 && Py_CHARMASK(*u) < 128) {\r
+ unicode = unicode_latin1[Py_CHARMASK(*u)];\r
+ if (!unicode) {\r
+ unicode = _PyUnicode_New(1);\r
+ if (!unicode)\r
+ return NULL;\r
+ unicode->str[0] = Py_CHARMASK(*u);\r
+ unicode_latin1[Py_CHARMASK(*u)] = unicode;\r
+ }\r
+ Py_INCREF(unicode);\r
+ return (PyObject *)unicode;\r
+ }\r
+\r
+ return PyUnicode_DecodeUTF8(u, size, NULL);\r
+ }\r
+\r
+ unicode = _PyUnicode_New(size);\r
+ if (!unicode)\r
+ return NULL;\r
+\r
+ return (PyObject *)unicode;\r
+}\r
+\r
+PyObject *PyUnicode_FromString(const char *u)\r
+{\r
+ size_t size = strlen(u);\r
+ if (size > PY_SSIZE_T_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError, "input too long");\r
+ return NULL;\r
+ }\r
+\r
+ return PyUnicode_FromStringAndSize(u, size);\r
+}\r
+\r
+/* _Py_UNICODE_NEXT is a private macro used to retrieve the character pointed\r
+ * by 'ptr', possibly combining surrogate pairs on narrow builds.\r
+ * 'ptr' and 'end' must be Py_UNICODE*, with 'ptr' pointing at the character\r
+ * that should be returned and 'end' pointing to the end of the buffer.\r
+ * ('end' is used on narrow builds to detect a lone surrogate at the\r
+ * end of the buffer that should be returned unchanged.)\r
+ * The ptr and end arguments should be side-effect free and ptr must an lvalue.\r
+ * The type of the returned char is always Py_UCS4.\r
+ *\r
+ * Note: the macro advances ptr to next char, so it might have side-effects\r
+ * (especially if used with other macros).\r
+ */\r
+\r
+/* helper macros used by _Py_UNICODE_NEXT */\r
+#define _Py_UNICODE_IS_HIGH_SURROGATE(ch) (0xD800 <= ch && ch <= 0xDBFF)\r
+#define _Py_UNICODE_IS_LOW_SURROGATE(ch) (0xDC00 <= ch && ch <= 0xDFFF)\r
+/* Join two surrogate characters and return a single Py_UCS4 value. */\r
+#define _Py_UNICODE_JOIN_SURROGATES(high, low) \\r
+ (((((Py_UCS4)(high) & 0x03FF) << 10) | \\r
+ ((Py_UCS4)(low) & 0x03FF)) + 0x10000)\r
+\r
+#ifdef Py_UNICODE_WIDE\r
+#define _Py_UNICODE_NEXT(ptr, end) *(ptr)++\r
+#else\r
+#define _Py_UNICODE_NEXT(ptr, end) \\r
+ (((_Py_UNICODE_IS_HIGH_SURROGATE(*(ptr)) && (ptr) < (end)) && \\r
+ _Py_UNICODE_IS_LOW_SURROGATE((ptr)[1])) ? \\r
+ ((ptr) += 2,_Py_UNICODE_JOIN_SURROGATES((ptr)[-2], (ptr)[-1])) : \\r
+ (Py_UCS4)*(ptr)++)\r
+#endif\r
+\r
+#ifdef HAVE_WCHAR_H\r
+\r
+#if (Py_UNICODE_SIZE == 2) && defined(SIZEOF_WCHAR_T) && (SIZEOF_WCHAR_T == 4)\r
+# define CONVERT_WCHAR_TO_SURROGATES\r
+#endif\r
+\r
+#ifdef CONVERT_WCHAR_TO_SURROGATES\r
+\r
+/* Here sizeof(wchar_t) is 4 but Py_UNICODE_SIZE == 2, so we need\r
+ to convert from UTF32 to UTF16. */\r
+\r
+PyObject *PyUnicode_FromWideChar(register const wchar_t *w,\r
+ Py_ssize_t size)\r
+{\r
+ PyUnicodeObject *unicode;\r
+ register Py_ssize_t i;\r
+ Py_ssize_t alloc;\r
+ const wchar_t *orig_w;\r
+\r
+ if (w == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+\r
+ alloc = size;\r
+ orig_w = w;\r
+ for (i = size; i > 0; i--) {\r
+ if (*w > 0xFFFF)\r
+ alloc++;\r
+ w++;\r
+ }\r
+ w = orig_w;\r
+ unicode = _PyUnicode_New(alloc);\r
+ if (!unicode)\r
+ return NULL;\r
+\r
+ /* Copy the wchar_t data into the new object */\r
+ {\r
+ register Py_UNICODE *u;\r
+ u = PyUnicode_AS_UNICODE(unicode);\r
+ for (i = size; i > 0; i--) {\r
+ if (*w > 0xFFFF) {\r
+ wchar_t ordinal = *w++;\r
+ ordinal -= 0x10000;\r
+ *u++ = 0xD800 | (ordinal >> 10);\r
+ *u++ = 0xDC00 | (ordinal & 0x3FF);\r
+ }\r
+ else\r
+ *u++ = *w++;\r
+ }\r
+ }\r
+ return (PyObject *)unicode;\r
+}\r
+\r
+#else\r
+\r
+PyObject *PyUnicode_FromWideChar(register const wchar_t *w,\r
+ Py_ssize_t size)\r
+{\r
+ PyUnicodeObject *unicode;\r
+\r
+ if (w == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+\r
+ unicode = _PyUnicode_New(size);\r
+ if (!unicode)\r
+ return NULL;\r
+\r
+ /* Copy the wchar_t data into the new object */\r
+#ifdef HAVE_USABLE_WCHAR_T\r
+ memcpy(unicode->str, w, size * sizeof(wchar_t));\r
+#else\r
+ {\r
+ register Py_UNICODE *u;\r
+ register Py_ssize_t i;\r
+ u = PyUnicode_AS_UNICODE(unicode);\r
+ for (i = size; i > 0; i--)\r
+ *u++ = *w++;\r
+ }\r
+#endif\r
+\r
+ return (PyObject *)unicode;\r
+}\r
+\r
+#endif /* CONVERT_WCHAR_TO_SURROGATES */\r
+\r
+#undef CONVERT_WCHAR_TO_SURROGATES\r
+\r
+static void\r
+makefmt(char *fmt, int longflag, int size_tflag, int zeropad, int width, int precision, char c)\r
+{\r
+ *fmt++ = '%';\r
+ if (width) {\r
+ if (zeropad)\r
+ *fmt++ = '0';\r
+ fmt += sprintf(fmt, "%d", width);\r
+ }\r
+ if (precision)\r
+ fmt += sprintf(fmt, ".%d", precision);\r
+ if (longflag)\r
+ *fmt++ = 'l';\r
+ else if (size_tflag) {\r
+ char *f = PY_FORMAT_SIZE_T;\r
+ while (*f)\r
+ *fmt++ = *f++;\r
+ }\r
+ *fmt++ = c;\r
+ *fmt = '\0';\r
+}\r
+\r
+#define appendstring(string) \\r
+ do { \\r
+ for (copy = string;*copy; copy++) { \\r
+ *s++ = (unsigned char)*copy; \\r
+ } \\r
+ } while (0)\r
+\r
+PyObject *\r
+PyUnicode_FromFormatV(const char *format, va_list vargs)\r
+{\r
+ va_list count;\r
+ Py_ssize_t callcount = 0;\r
+ PyObject **callresults = NULL;\r
+ PyObject **callresult = NULL;\r
+ Py_ssize_t n = 0;\r
+ int width = 0;\r
+ int precision = 0;\r
+ int zeropad;\r
+ const char* f;\r
+ Py_UNICODE *s;\r
+ PyObject *string;\r
+ /* used by sprintf */\r
+ char buffer[21];\r
+ /* use abuffer instead of buffer, if we need more space\r
+ * (which can happen if there's a format specifier with width). */\r
+ char *abuffer = NULL;\r
+ char *realbuffer;\r
+ Py_ssize_t abuffersize = 0;\r
+ char fmt[60]; /* should be enough for %0width.precisionld */\r
+ const char *copy;\r
+\r
+#ifdef VA_LIST_IS_ARRAY\r
+ Py_MEMCPY(count, vargs, sizeof(va_list));\r
+#else\r
+#ifdef __va_copy\r
+ __va_copy(count, vargs);\r
+#else\r
+ count = vargs;\r
+#endif\r
+#endif\r
+ /* step 1: count the number of %S/%R/%s format specifications\r
+ * (we call PyObject_Str()/PyObject_Repr()/PyUnicode_DecodeUTF8() for these\r
+ * objects once during step 3 and put the result in an array) */\r
+ for (f = format; *f; f++) {\r
+ if (*f == '%') {\r
+ f++;\r
+ while (*f && *f != '%' && !isalpha((unsigned)*f))\r
+ f++;\r
+ if (!*f)\r
+ break;\r
+ if (*f == 's' || *f=='S' || *f=='R')\r
+ ++callcount;\r
+ }\r
+ }\r
+ /* step 2: allocate memory for the results of\r
+ * PyObject_Str()/PyObject_Repr()/PyUnicode_DecodeUTF8() calls */\r
+ if (callcount) {\r
+ callresults = PyObject_Malloc(sizeof(PyObject *)*callcount);\r
+ if (!callresults) {\r
+ PyErr_NoMemory();\r
+ return NULL;\r
+ }\r
+ callresult = callresults;\r
+ }\r
+ /* step 3: figure out how large a buffer we need */\r
+ for (f = format; *f; f++) {\r
+ if (*f == '%') {\r
+ const char* p = f++;\r
+ width = 0;\r
+ while (isdigit((unsigned)*f))\r
+ width = (width*10) + *f++ - '0';\r
+ precision = 0;\r
+ if (*f == '.') {\r
+ f++;\r
+ while (isdigit((unsigned)*f))\r
+ precision = (precision*10) + *f++ - '0';\r
+ }\r
+\r
+ /* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since\r
+ * they don't affect the amount of space we reserve.\r
+ */\r
+ if ((*f == 'l' || *f == 'z') &&\r
+ (f[1] == 'd' || f[1] == 'u'))\r
+ ++f;\r
+\r
+ switch (*f) {\r
+ case 'c':\r
+ {\r
+ int ordinal = va_arg(count, int);\r
+#ifdef Py_UNICODE_WIDE\r
+ if (ordinal < 0 || ordinal > 0x10ffff) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "%c arg not in range(0x110000) "\r
+ "(wide Python build)");\r
+ goto fail;\r
+ }\r
+#else\r
+ if (ordinal < 0 || ordinal > 0xffff) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "%c arg not in range(0x10000) "\r
+ "(narrow Python build)");\r
+ goto fail;\r
+ }\r
+#endif\r
+ /* fall through... */\r
+ }\r
+ case '%':\r
+ n++;\r
+ break;\r
+ case 'd': case 'u': case 'i': case 'x':\r
+ (void) va_arg(count, int);\r
+ if (width < precision)\r
+ width = precision;\r
+ /* 20 bytes is enough to hold a 64-bit\r
+ integer. Decimal takes the most space.\r
+ This isn't enough for octal.\r
+ If a width is specified we need more\r
+ (which we allocate later). */\r
+ if (width < 20)\r
+ width = 20;\r
+ n += width;\r
+ if (abuffersize < width)\r
+ abuffersize = width;\r
+ break;\r
+ case 's':\r
+ {\r
+ /* UTF-8 */\r
+ const char *s = va_arg(count, const char*);\r
+ PyObject *str = PyUnicode_DecodeUTF8(s, strlen(s), "replace");\r
+ if (!str)\r
+ goto fail;\r
+ n += PyUnicode_GET_SIZE(str);\r
+ /* Remember the str and switch to the next slot */\r
+ *callresult++ = str;\r
+ break;\r
+ }\r
+ case 'U':\r
+ {\r
+ PyObject *obj = va_arg(count, PyObject *);\r
+ assert(obj && PyUnicode_Check(obj));\r
+ n += PyUnicode_GET_SIZE(obj);\r
+ break;\r
+ }\r
+ case 'V':\r
+ {\r
+ PyObject *obj = va_arg(count, PyObject *);\r
+ const char *str = va_arg(count, const char *);\r
+ assert(obj || str);\r
+ assert(!obj || PyUnicode_Check(obj));\r
+ if (obj)\r
+ n += PyUnicode_GET_SIZE(obj);\r
+ else\r
+ n += strlen(str);\r
+ break;\r
+ }\r
+ case 'S':\r
+ {\r
+ PyObject *obj = va_arg(count, PyObject *);\r
+ PyObject *str;\r
+ assert(obj);\r
+ str = PyObject_Str(obj);\r
+ if (!str)\r
+ goto fail;\r
+ n += PyString_GET_SIZE(str);\r
+ /* Remember the str and switch to the next slot */\r
+ *callresult++ = str;\r
+ break;\r
+ }\r
+ case 'R':\r
+ {\r
+ PyObject *obj = va_arg(count, PyObject *);\r
+ PyObject *repr;\r
+ assert(obj);\r
+ repr = PyObject_Repr(obj);\r
+ if (!repr)\r
+ goto fail;\r
+ n += PyUnicode_GET_SIZE(repr);\r
+ /* Remember the repr and switch to the next slot */\r
+ *callresult++ = repr;\r
+ break;\r
+ }\r
+ case 'p':\r
+ (void) va_arg(count, int);\r
+ /* maximum 64-bit pointer representation:\r
+ * 0xffffffffffffffff\r
+ * so 19 characters is enough.\r
+ * XXX I count 18 -- what's the extra for?\r
+ */\r
+ n += 19;\r
+ break;\r
+ default:\r
+ /* if we stumble upon an unknown\r
+ formatting code, copy the rest of\r
+ the format string to the output\r
+ string. (we cannot just skip the\r
+ code, since there's no way to know\r
+ what's in the argument list) */\r
+ n += strlen(p);\r
+ goto expand;\r
+ }\r
+ } else\r
+ n++;\r
+ }\r
+ expand:\r
+ if (abuffersize > 20) {\r
+ /* add 1 for sprintf's trailing null byte */\r
+ abuffer = PyObject_Malloc(abuffersize + 1);\r
+ if (!abuffer) {\r
+ PyErr_NoMemory();\r
+ goto fail;\r
+ }\r
+ realbuffer = abuffer;\r
+ }\r
+ else\r
+ realbuffer = buffer;\r
+ /* step 4: fill the buffer */\r
+ /* Since we've analyzed how much space we need for the worst case,\r
+ we don't have to resize the string.\r
+ There can be no errors beyond this point. */\r
+ string = PyUnicode_FromUnicode(NULL, n);\r
+ if (!string)\r
+ goto fail;\r
+\r
+ s = PyUnicode_AS_UNICODE(string);\r
+ callresult = callresults;\r
+\r
+ for (f = format; *f; f++) {\r
+ if (*f == '%') {\r
+ const char* p = f++;\r
+ int longflag = 0;\r
+ int size_tflag = 0;\r
+ zeropad = (*f == '0');\r
+ /* parse the width.precision part */\r
+ width = 0;\r
+ while (isdigit((unsigned)*f))\r
+ width = (width*10) + *f++ - '0';\r
+ precision = 0;\r
+ if (*f == '.') {\r
+ f++;\r
+ while (isdigit((unsigned)*f))\r
+ precision = (precision*10) + *f++ - '0';\r
+ }\r
+ /* handle the long flag, but only for %ld and %lu.\r
+ others can be added when necessary. */\r
+ if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) {\r
+ longflag = 1;\r
+ ++f;\r
+ }\r
+ /* handle the size_t flag. */\r
+ if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) {\r
+ size_tflag = 1;\r
+ ++f;\r
+ }\r
+\r
+ switch (*f) {\r
+ case 'c':\r
+ *s++ = va_arg(vargs, int);\r
+ break;\r
+ case 'd':\r
+ makefmt(fmt, longflag, size_tflag, zeropad, width, precision, 'd');\r
+ if (longflag)\r
+ sprintf(realbuffer, fmt, va_arg(vargs, long));\r
+ else if (size_tflag)\r
+ sprintf(realbuffer, fmt, va_arg(vargs, Py_ssize_t));\r
+ else\r
+ sprintf(realbuffer, fmt, va_arg(vargs, int));\r
+ appendstring(realbuffer);\r
+ break;\r
+ case 'u':\r
+ makefmt(fmt, longflag, size_tflag, zeropad, width, precision, 'u');\r
+ if (longflag)\r
+ sprintf(realbuffer, fmt, va_arg(vargs, unsigned long));\r
+ else if (size_tflag)\r
+ sprintf(realbuffer, fmt, va_arg(vargs, size_t));\r
+ else\r
+ sprintf(realbuffer, fmt, va_arg(vargs, unsigned int));\r
+ appendstring(realbuffer);\r
+ break;\r
+ case 'i':\r
+ makefmt(fmt, 0, 0, zeropad, width, precision, 'i');\r
+ sprintf(realbuffer, fmt, va_arg(vargs, int));\r
+ appendstring(realbuffer);\r
+ break;\r
+ case 'x':\r
+ makefmt(fmt, 0, 0, zeropad, width, precision, 'x');\r
+ sprintf(realbuffer, fmt, va_arg(vargs, int));\r
+ appendstring(realbuffer);\r
+ break;\r
+ case 's':\r
+ {\r
+ /* unused, since we already have the result */\r
+ (void) va_arg(vargs, char *);\r
+ Py_UNICODE_COPY(s, PyUnicode_AS_UNICODE(*callresult),\r
+ PyUnicode_GET_SIZE(*callresult));\r
+ s += PyUnicode_GET_SIZE(*callresult);\r
+ /* We're done with the unicode()/repr() => forget it */\r
+ Py_DECREF(*callresult);\r
+ /* switch to next unicode()/repr() result */\r
+ ++callresult;\r
+ break;\r
+ }\r
+ case 'U':\r
+ {\r
+ PyObject *obj = va_arg(vargs, PyObject *);\r
+ Py_ssize_t size = PyUnicode_GET_SIZE(obj);\r
+ Py_UNICODE_COPY(s, PyUnicode_AS_UNICODE(obj), size);\r
+ s += size;\r
+ break;\r
+ }\r
+ case 'V':\r
+ {\r
+ PyObject *obj = va_arg(vargs, PyObject *);\r
+ const char *str = va_arg(vargs, const char *);\r
+ if (obj) {\r
+ Py_ssize_t size = PyUnicode_GET_SIZE(obj);\r
+ Py_UNICODE_COPY(s, PyUnicode_AS_UNICODE(obj), size);\r
+ s += size;\r
+ } else {\r
+ appendstring(str);\r
+ }\r
+ break;\r
+ }\r
+ case 'S':\r
+ case 'R':\r
+ {\r
+ const char *str = PyString_AS_STRING(*callresult);\r
+ /* unused, since we already have the result */\r
+ (void) va_arg(vargs, PyObject *);\r
+ appendstring(str);\r
+ /* We're done with the unicode()/repr() => forget it */\r
+ Py_DECREF(*callresult);\r
+ /* switch to next unicode()/repr() result */\r
+ ++callresult;\r
+ break;\r
+ }\r
+ case 'p':\r
+ sprintf(buffer, "%p", va_arg(vargs, void*));\r
+ /* %p is ill-defined: ensure leading 0x. */\r
+ if (buffer[1] == 'X')\r
+ buffer[1] = 'x';\r
+ else if (buffer[1] != 'x') {\r
+ memmove(buffer+2, buffer, strlen(buffer)+1);\r
+ buffer[0] = '0';\r
+ buffer[1] = 'x';\r
+ }\r
+ appendstring(buffer);\r
+ break;\r
+ case '%':\r
+ *s++ = '%';\r
+ break;\r
+ default:\r
+ appendstring(p);\r
+ goto end;\r
+ }\r
+ } else\r
+ *s++ = *f;\r
+ }\r
+\r
+ end:\r
+ if (callresults)\r
+ PyObject_Free(callresults);\r
+ if (abuffer)\r
+ PyObject_Free(abuffer);\r
+ PyUnicode_Resize(&string, s - PyUnicode_AS_UNICODE(string));\r
+ return string;\r
+ fail:\r
+ if (callresults) {\r
+ PyObject **callresult2 = callresults;\r
+ while (callresult2 < callresult) {\r
+ Py_DECREF(*callresult2);\r
+ ++callresult2;\r
+ }\r
+ PyObject_Free(callresults);\r
+ }\r
+ if (abuffer)\r
+ PyObject_Free(abuffer);\r
+ return NULL;\r
+}\r
+\r
+#undef appendstring\r
+\r
+PyObject *\r
+PyUnicode_FromFormat(const char *format, ...)\r
+{\r
+ PyObject* ret;\r
+ va_list vargs;\r
+\r
+#ifdef HAVE_STDARG_PROTOTYPES\r
+ va_start(vargs, format);\r
+#else\r
+ va_start(vargs);\r
+#endif\r
+ ret = PyUnicode_FromFormatV(format, vargs);\r
+ va_end(vargs);\r
+ return ret;\r
+}\r
+\r
+Py_ssize_t PyUnicode_AsWideChar(PyUnicodeObject *unicode,\r
+ wchar_t *w,\r
+ Py_ssize_t size)\r
+{\r
+ if (unicode == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return -1;\r
+ }\r
+\r
+ /* If possible, try to copy the 0-termination as well */\r
+ if (size > PyUnicode_GET_SIZE(unicode))\r
+ size = PyUnicode_GET_SIZE(unicode) + 1;\r
+\r
+#ifdef HAVE_USABLE_WCHAR_T\r
+ memcpy(w, unicode->str, size * sizeof(wchar_t));\r
+#else\r
+ {\r
+ register Py_UNICODE *u;\r
+ register Py_ssize_t i;\r
+ u = PyUnicode_AS_UNICODE(unicode);\r
+ for (i = size; i > 0; i--)\r
+ *w++ = *u++;\r
+ }\r
+#endif\r
+\r
+ if (size > PyUnicode_GET_SIZE(unicode))\r
+ return PyUnicode_GET_SIZE(unicode);\r
+ else\r
+ return size;\r
+}\r
+\r
+#endif\r
+\r
+PyObject *PyUnicode_FromOrdinal(int ordinal)\r
+{\r
+ Py_UNICODE s[1];\r
+\r
+#ifdef Py_UNICODE_WIDE\r
+ if (ordinal < 0 || ordinal > 0x10ffff) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "unichr() arg not in range(0x110000) "\r
+ "(wide Python build)");\r
+ return NULL;\r
+ }\r
+#else\r
+ if (ordinal < 0 || ordinal > 0xffff) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "unichr() arg not in range(0x10000) "\r
+ "(narrow Python build)");\r
+ return NULL;\r
+ }\r
+#endif\r
+\r
+ s[0] = (Py_UNICODE)ordinal;\r
+ return PyUnicode_FromUnicode(s, 1);\r
+}\r
+\r
+PyObject *PyUnicode_FromObject(register PyObject *obj)\r
+{\r
+ /* XXX Perhaps we should make this API an alias of\r
+ PyObject_Unicode() instead ?! */\r
+ if (PyUnicode_CheckExact(obj)) {\r
+ Py_INCREF(obj);\r
+ return obj;\r
+ }\r
+ if (PyUnicode_Check(obj)) {\r
+ /* For a Unicode subtype that's not a Unicode object,\r
+ return a true Unicode object with the same data. */\r
+ return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(obj),\r
+ PyUnicode_GET_SIZE(obj));\r
+ }\r
+ return PyUnicode_FromEncodedObject(obj, NULL, "strict");\r
+}\r
+\r
+PyObject *PyUnicode_FromEncodedObject(register PyObject *obj,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ const char *s = NULL;\r
+ Py_ssize_t len;\r
+ PyObject *v;\r
+\r
+ if (obj == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+\r
+#if 0\r
+ /* For b/w compatibility we also accept Unicode objects provided\r
+ that no encodings is given and then redirect to\r
+ PyObject_Unicode() which then applies the additional logic for\r
+ Unicode subclasses.\r
+\r
+ NOTE: This API should really only be used for object which\r
+ represent *encoded* Unicode !\r
+\r
+ */\r
+ if (PyUnicode_Check(obj)) {\r
+ if (encoding) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "decoding Unicode is not supported");\r
+ return NULL;\r
+ }\r
+ return PyObject_Unicode(obj);\r
+ }\r
+#else\r
+ if (PyUnicode_Check(obj)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "decoding Unicode is not supported");\r
+ return NULL;\r
+ }\r
+#endif\r
+\r
+ /* Coerce object */\r
+ if (PyString_Check(obj)) {\r
+ s = PyString_AS_STRING(obj);\r
+ len = PyString_GET_SIZE(obj);\r
+ }\r
+ else if (PyByteArray_Check(obj)) {\r
+ /* Python 2.x specific */\r
+ PyErr_Format(PyExc_TypeError,\r
+ "decoding bytearray is not supported");\r
+ return NULL;\r
+ }\r
+ else if (PyObject_AsCharBuffer(obj, &s, &len)) {\r
+ /* Overwrite the error message with something more useful in\r
+ case of a TypeError. */\r
+ if (PyErr_ExceptionMatches(PyExc_TypeError))\r
+ PyErr_Format(PyExc_TypeError,\r
+ "coercing to Unicode: need string or buffer, "\r
+ "%.80s found",\r
+ Py_TYPE(obj)->tp_name);\r
+ goto onError;\r
+ }\r
+\r
+ /* Convert to Unicode */\r
+ if (len == 0)\r
+ _Py_RETURN_UNICODE_EMPTY();\r
+\r
+ v = PyUnicode_Decode(s, len, encoding, errors);\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyUnicode_Decode(const char *s,\r
+ Py_ssize_t size,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *buffer = NULL, *unicode;\r
+\r
+ if (encoding == NULL)\r
+ encoding = PyUnicode_GetDefaultEncoding();\r
+\r
+ /* Shortcuts for common default encodings */\r
+ if (strcmp(encoding, "utf-8") == 0)\r
+ return PyUnicode_DecodeUTF8(s, size, errors);\r
+ else if (strcmp(encoding, "latin-1") == 0)\r
+ return PyUnicode_DecodeLatin1(s, size, errors);\r
+#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)\r
+ else if (strcmp(encoding, "mbcs") == 0)\r
+ return PyUnicode_DecodeMBCS(s, size, errors);\r
+#endif\r
+ else if (strcmp(encoding, "ascii") == 0)\r
+ return PyUnicode_DecodeASCII(s, size, errors);\r
+\r
+ /* Decode via the codec registry */\r
+ buffer = PyBuffer_FromMemory((void *)s, size);\r
+ if (buffer == NULL)\r
+ goto onError;\r
+ unicode = PyCodec_Decode(buffer, encoding, errors);\r
+ if (unicode == NULL)\r
+ goto onError;\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "decoder did not return an unicode object (type=%.400s)",\r
+ Py_TYPE(unicode)->tp_name);\r
+ Py_DECREF(unicode);\r
+ goto onError;\r
+ }\r
+ Py_DECREF(buffer);\r
+ return unicode;\r
+\r
+ onError:\r
+ Py_XDECREF(buffer);\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyUnicode_AsDecodedObject(PyObject *unicode,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v;\r
+\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ goto onError;\r
+ }\r
+\r
+ if (encoding == NULL)\r
+ encoding = PyUnicode_GetDefaultEncoding();\r
+\r
+ /* Decode via the codec registry */\r
+ v = PyCodec_Decode(unicode, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyUnicode_Encode(const Py_UNICODE *s,\r
+ Py_ssize_t size,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v, *unicode;\r
+\r
+ unicode = PyUnicode_FromUnicode(s, size);\r
+ if (unicode == NULL)\r
+ return NULL;\r
+ v = PyUnicode_AsEncodedString(unicode, encoding, errors);\r
+ Py_DECREF(unicode);\r
+ return v;\r
+}\r
+\r
+PyObject *PyUnicode_AsEncodedObject(PyObject *unicode,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v;\r
+\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ goto onError;\r
+ }\r
+\r
+ if (encoding == NULL)\r
+ encoding = PyUnicode_GetDefaultEncoding();\r
+\r
+ /* Encode via the codec registry */\r
+ v = PyCodec_Encode(unicode, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyUnicode_AsEncodedString(PyObject *unicode,\r
+ const char *encoding,\r
+ const char *errors)\r
+{\r
+ PyObject *v;\r
+\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ goto onError;\r
+ }\r
+\r
+ if (encoding == NULL)\r
+ encoding = PyUnicode_GetDefaultEncoding();\r
+\r
+ /* Shortcuts for common default encodings */\r
+ if (errors == NULL) {\r
+ if (strcmp(encoding, "utf-8") == 0)\r
+ return PyUnicode_AsUTF8String(unicode);\r
+ else if (strcmp(encoding, "latin-1") == 0)\r
+ return PyUnicode_AsLatin1String(unicode);\r
+#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)\r
+ else if (strcmp(encoding, "mbcs") == 0)\r
+ return PyUnicode_AsMBCSString(unicode);\r
+#endif\r
+ else if (strcmp(encoding, "ascii") == 0)\r
+ return PyUnicode_AsASCIIString(unicode);\r
+ }\r
+\r
+ /* Encode via the codec registry */\r
+ v = PyCodec_Encode(unicode, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (!PyString_Check(v)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "encoder did not return a string object (type=%.400s)",\r
+ Py_TYPE(v)->tp_name);\r
+ Py_DECREF(v);\r
+ goto onError;\r
+ }\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,\r
+ const char *errors)\r
+{\r
+ PyObject *v = ((PyUnicodeObject *)unicode)->defenc;\r
+\r
+ if (v)\r
+ return v;\r
+ v = PyUnicode_AsEncodedString(unicode, NULL, errors);\r
+ if (v && errors == NULL)\r
+ ((PyUnicodeObject *)unicode)->defenc = v;\r
+ return v;\r
+}\r
+\r
+Py_UNICODE *PyUnicode_AsUnicode(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ goto onError;\r
+ }\r
+ return PyUnicode_AS_UNICODE(unicode);\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+Py_ssize_t PyUnicode_GetSize(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ goto onError;\r
+ }\r
+ return PyUnicode_GET_SIZE(unicode);\r
+\r
+ onError:\r
+ return -1;\r
+}\r
+\r
+const char *PyUnicode_GetDefaultEncoding(void)\r
+{\r
+ return unicode_default_encoding;\r
+}\r
+\r
+int PyUnicode_SetDefaultEncoding(const char *encoding)\r
+{\r
+ PyObject *v;\r
+\r
+ /* Make sure the encoding is valid. As side effect, this also\r
+ loads the encoding into the codec registry cache. */\r
+ v = _PyCodec_Lookup(encoding);\r
+ if (v == NULL)\r
+ goto onError;\r
+ Py_DECREF(v);\r
+ strncpy(unicode_default_encoding,\r
+ encoding,\r
+ sizeof(unicode_default_encoding) - 1);\r
+ return 0;\r
+\r
+ onError:\r
+ return -1;\r
+}\r
+\r
+/* error handling callback helper:\r
+ build arguments, call the callback and check the arguments,\r
+ if no exception occurred, copy the replacement to the output\r
+ and adjust various state variables.\r
+ return 0 on success, -1 on error\r
+*/\r
+\r
+static\r
+int unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler,\r
+ const char *encoding, const char *reason,\r
+ const char *input, Py_ssize_t insize, Py_ssize_t *startinpos,\r
+ Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr,\r
+ PyUnicodeObject **output, Py_ssize_t *outpos, Py_UNICODE **outptr)\r
+{\r
+ static char *argparse = "O!n;decoding error handler must return (unicode, int) tuple";\r
+\r
+ PyObject *restuple = NULL;\r
+ PyObject *repunicode = NULL;\r
+ Py_ssize_t outsize = PyUnicode_GET_SIZE(*output);\r
+ Py_ssize_t requiredsize;\r
+ Py_ssize_t newpos;\r
+ Py_UNICODE *repptr;\r
+ Py_ssize_t repsize;\r
+ int res = -1;\r
+\r
+ if (*errorHandler == NULL) {\r
+ *errorHandler = PyCodec_LookupError(errors);\r
+ if (*errorHandler == NULL)\r
+ goto onError;\r
+ }\r
+\r
+ if (*exceptionObject == NULL) {\r
+ *exceptionObject = PyUnicodeDecodeError_Create(\r
+ encoding, input, insize, *startinpos, *endinpos, reason);\r
+ if (*exceptionObject == NULL)\r
+ goto onError;\r
+ }\r
+ else {\r
+ if (PyUnicodeDecodeError_SetStart(*exceptionObject, *startinpos))\r
+ goto onError;\r
+ if (PyUnicodeDecodeError_SetEnd(*exceptionObject, *endinpos))\r
+ goto onError;\r
+ if (PyUnicodeDecodeError_SetReason(*exceptionObject, reason))\r
+ goto onError;\r
+ }\r
+\r
+ restuple = PyObject_CallFunctionObjArgs(*errorHandler, *exceptionObject, NULL);\r
+ if (restuple == NULL)\r
+ goto onError;\r
+ if (!PyTuple_Check(restuple)) {\r
+ PyErr_SetString(PyExc_TypeError, &argparse[4]);\r
+ goto onError;\r
+ }\r
+ if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type, &repunicode, &newpos))\r
+ goto onError;\r
+ if (newpos<0)\r
+ newpos = insize+newpos;\r
+ if (newpos<0 || newpos>insize) {\r
+ PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", newpos);\r
+ goto onError;\r
+ }\r
+\r
+ /* need more space? (at least enough for what we\r
+ have+the replacement+the rest of the string (starting\r
+ at the new input position), so we won't have to check space\r
+ when there are no errors in the rest of the string) */\r
+ repptr = PyUnicode_AS_UNICODE(repunicode);\r
+ repsize = PyUnicode_GET_SIZE(repunicode);\r
+ requiredsize = *outpos;\r
+ if (requiredsize > PY_SSIZE_T_MAX - repsize)\r
+ goto overflow;\r
+ requiredsize += repsize;\r
+ if (requiredsize > PY_SSIZE_T_MAX - (insize - newpos))\r
+ goto overflow;\r
+ requiredsize += insize - newpos;\r
+ if (requiredsize > outsize) {\r
+ if (outsize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*outsize)\r
+ requiredsize = 2*outsize;\r
+ if (_PyUnicode_Resize(output, requiredsize) < 0)\r
+ goto onError;\r
+ *outptr = PyUnicode_AS_UNICODE(*output) + *outpos;\r
+ }\r
+ *endinpos = newpos;\r
+ *inptr = input + newpos;\r
+ Py_UNICODE_COPY(*outptr, repptr, repsize);\r
+ *outptr += repsize;\r
+ *outpos += repsize;\r
+ /* we made it! */\r
+ res = 0;\r
+\r
+ onError:\r
+ Py_XDECREF(restuple);\r
+ return res;\r
+\r
+ overflow:\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "decoded result is too long for a Python string");\r
+ goto onError;\r
+}\r
+\r
+/* --- UTF-7 Codec -------------------------------------------------------- */\r
+\r
+/* See RFC2152 for details. We encode conservatively and decode liberally. */\r
+\r
+/* Three simple macros defining base-64. */\r
+\r
+/* Is c a base-64 character? */\r
+\r
+#define IS_BASE64(c) \\r
+ (isalnum(c) || (c) == '+' || (c) == '/')\r
+\r
+/* given that c is a base-64 character, what is its base-64 value? */\r
+\r
+#define FROM_BASE64(c) \\r
+ (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' : \\r
+ ((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 26 : \\r
+ ((c) >= '0' && (c) <= '9') ? (c) - '0' + 52 : \\r
+ (c) == '+' ? 62 : 63)\r
+\r
+/* What is the base-64 character of the bottom 6 bits of n? */\r
+\r
+#define TO_BASE64(n) \\r
+ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f])\r
+\r
+/* DECODE_DIRECT: this byte encountered in a UTF-7 string should be\r
+ * decoded as itself. We are permissive on decoding; the only ASCII\r
+ * byte not decoding to itself is the + which begins a base64\r
+ * string. */\r
+\r
+#define DECODE_DIRECT(c) \\r
+ ((c) <= 127 && (c) != '+')\r
+\r
+/* The UTF-7 encoder treats ASCII characters differently according to\r
+ * whether they are Set D, Set O, Whitespace, or special (i.e. none of\r
+ * the above). See RFC2152. This array identifies these different\r
+ * sets:\r
+ * 0 : "Set D"\r
+ * alphanumeric and '(),-./:?\r
+ * 1 : "Set O"\r
+ * !"#$%&*;<=>@[]^_`{|}\r
+ * 2 : "whitespace"\r
+ * ht nl cr sp\r
+ * 3 : special (must be base64 encoded)\r
+ * everything else (i.e. +\~ and non-printing codes 0-8 11-12 14-31 127)\r
+ */\r
+\r
+static\r
+char utf7_category[128] = {\r
+/* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */\r
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3,\r
+/* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */\r
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\r
+/* sp ! " # $ % & ' ( ) * + , - . / */\r
+ 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 3, 0, 0, 0, 0,\r
+/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,\r
+/* @ A B C D E F G H I J K L M N O */\r
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/* P Q R S T U V W X Y Z [ \ ] ^ _ */\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 1,\r
+/* ` a b c d e f g h i j k l m n o */\r
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/* p q r s t u v w x y z { | } ~ del */\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3,\r
+};\r
+\r
+/* ENCODE_DIRECT: this character should be encoded as itself. The\r
+ * answer depends on whether we are encoding set O as itself, and also\r
+ * on whether we are encoding whitespace as itself. RFC2152 makes it\r
+ * clear that the answers to these questions vary between\r
+ * applications, so this code needs to be flexible. */\r
+\r
+#define ENCODE_DIRECT(c, directO, directWS) \\r
+ ((c) < 128 && (c) > 0 && \\r
+ ((utf7_category[(c)] == 0) || \\r
+ (directWS && (utf7_category[(c)] == 2)) || \\r
+ (directO && (utf7_category[(c)] == 1))))\r
+\r
+PyObject *PyUnicode_DecodeUTF7(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ return PyUnicode_DecodeUTF7Stateful(s, size, errors, NULL);\r
+}\r
+\r
+/* The decoder. The only state we preserve is our read position,\r
+ * i.e. how many characters we have consumed. So if we end in the\r
+ * middle of a shift sequence we have to back off the read position\r
+ * and the output to the beginning of the sequence, otherwise we lose\r
+ * all the shift state (seen bits, number of bits seen, high\r
+ * surrogate). */\r
+\r
+PyObject *PyUnicode_DecodeUTF7Stateful(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ Py_ssize_t *consumed)\r
+{\r
+ const char *starts = s;\r
+ Py_ssize_t startinpos;\r
+ Py_ssize_t endinpos;\r
+ Py_ssize_t outpos;\r
+ const char *e;\r
+ PyUnicodeObject *unicode;\r
+ Py_UNICODE *p;\r
+ const char *errmsg = "";\r
+ int inShift = 0;\r
+ Py_UNICODE *shiftOutStart;\r
+ unsigned int base64bits = 0;\r
+ unsigned long base64buffer = 0;\r
+ Py_UNICODE surrogate = 0;\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+\r
+ unicode = _PyUnicode_New(size);\r
+ if (!unicode)\r
+ return NULL;\r
+ if (size == 0) {\r
+ if (consumed)\r
+ *consumed = 0;\r
+ return (PyObject *)unicode;\r
+ }\r
+\r
+ p = unicode->str;\r
+ shiftOutStart = p;\r
+ e = s + size;\r
+\r
+ while (s < e) {\r
+ Py_UNICODE ch = (unsigned char) *s;\r
+\r
+ if (inShift) { /* in a base-64 section */\r
+ if (IS_BASE64(ch)) { /* consume a base-64 character */\r
+ base64buffer = (base64buffer << 6) | FROM_BASE64(ch);\r
+ base64bits += 6;\r
+ s++;\r
+ if (base64bits >= 16) {\r
+ /* we have enough bits for a UTF-16 value */\r
+ Py_UNICODE outCh = (Py_UNICODE)\r
+ (base64buffer >> (base64bits-16));\r
+ base64bits -= 16;\r
+ base64buffer &= (1 << base64bits) - 1; /* clear high bits */\r
+ assert(outCh <= 0xffff);\r
+ if (surrogate) {\r
+ /* expecting a second surrogate */\r
+ if (outCh >= 0xDC00 && outCh <= 0xDFFF) {\r
+#ifdef Py_UNICODE_WIDE\r
+ *p++ = (((surrogate & 0x3FF)<<10)\r
+ | (outCh & 0x3FF)) + 0x10000;\r
+#else\r
+ *p++ = surrogate;\r
+ *p++ = outCh;\r
+#endif\r
+ surrogate = 0;\r
+ continue;\r
+ }\r
+ else {\r
+ *p++ = surrogate;\r
+ surrogate = 0;\r
+ }\r
+ }\r
+ if (outCh >= 0xD800 && outCh <= 0xDBFF) {\r
+ /* first surrogate */\r
+ surrogate = outCh;\r
+ }\r
+ else {\r
+ *p++ = outCh;\r
+ }\r
+ }\r
+ }\r
+ else { /* now leaving a base-64 section */\r
+ inShift = 0;\r
+ s++;\r
+ if (surrogate) {\r
+ *p++ = surrogate;\r
+ surrogate = 0;\r
+ }\r
+ if (base64bits > 0) { /* left-over bits */\r
+ if (base64bits >= 6) {\r
+ /* We've seen at least one base-64 character */\r
+ errmsg = "partial character in shift sequence";\r
+ goto utf7Error;\r
+ }\r
+ else {\r
+ /* Some bits remain; they should be zero */\r
+ if (base64buffer != 0) {\r
+ errmsg = "non-zero padding bits in shift sequence";\r
+ goto utf7Error;\r
+ }\r
+ }\r
+ }\r
+ if (ch != '-') {\r
+ /* '-' is absorbed; other terminating\r
+ characters are preserved */\r
+ *p++ = ch;\r
+ }\r
+ }\r
+ }\r
+ else if ( ch == '+' ) {\r
+ startinpos = s-starts;\r
+ s++; /* consume '+' */\r
+ if (s < e && *s == '-') { /* '+-' encodes '+' */\r
+ s++;\r
+ *p++ = '+';\r
+ }\r
+ else { /* begin base64-encoded section */\r
+ inShift = 1;\r
+ shiftOutStart = p;\r
+ base64bits = 0;\r
+ base64buffer = 0;\r
+ }\r
+ }\r
+ else if (DECODE_DIRECT(ch)) { /* character decodes as itself */\r
+ *p++ = ch;\r
+ s++;\r
+ }\r
+ else {\r
+ startinpos = s-starts;\r
+ s++;\r
+ errmsg = "unexpected special character";\r
+ goto utf7Error;\r
+ }\r
+ continue;\r
+utf7Error:\r
+ outpos = p-PyUnicode_AS_UNICODE(unicode);\r
+ endinpos = s-starts;\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "utf7", errmsg,\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &unicode, &outpos, &p))\r
+ goto onError;\r
+ }\r
+\r
+ /* end of string */\r
+\r
+ if (inShift && !consumed) { /* in shift sequence, no more to follow */\r
+ /* if we're in an inconsistent state, that's an error */\r
+ if (surrogate ||\r
+ (base64bits >= 6) ||\r
+ (base64bits > 0 && base64buffer != 0)) {\r
+ outpos = p-PyUnicode_AS_UNICODE(unicode);\r
+ endinpos = size;\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "utf7", "unterminated shift sequence",\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &unicode, &outpos, &p))\r
+ goto onError;\r
+ }\r
+ }\r
+\r
+ /* return state */\r
+ if (consumed) {\r
+ if (inShift) {\r
+ p = shiftOutStart; /* back off output */\r
+ *consumed = startinpos;\r
+ }\r
+ else {\r
+ *consumed = s-starts;\r
+ }\r
+ }\r
+\r
+ if (_PyUnicode_Resize(&unicode, p - PyUnicode_AS_UNICODE(unicode)) < 0)\r
+ goto onError;\r
+\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return (PyObject *)unicode;\r
+\r
+ onError:\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ Py_DECREF(unicode);\r
+ return NULL;\r
+}\r
+\r
+\r
+PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s,\r
+ Py_ssize_t size,\r
+ int base64SetO,\r
+ int base64WhiteSpace,\r
+ const char *errors)\r
+{\r
+ PyObject *v;\r
+ /* It might be possible to tighten this worst case */\r
+ Py_ssize_t allocated = 8 * size;\r
+ int inShift = 0;\r
+ Py_ssize_t i = 0;\r
+ unsigned int base64bits = 0;\r
+ unsigned long base64buffer = 0;\r
+ char * out;\r
+ char * start;\r
+\r
+ if (allocated / 8 != size)\r
+ return PyErr_NoMemory();\r
+\r
+ if (size == 0)\r
+ return PyString_FromStringAndSize(NULL, 0);\r
+\r
+ v = PyString_FromStringAndSize(NULL, allocated);\r
+ if (v == NULL)\r
+ return NULL;\r
+\r
+ start = out = PyString_AS_STRING(v);\r
+ for (;i < size; ++i) {\r
+ Py_UNICODE ch = s[i];\r
+\r
+ if (inShift) {\r
+ if (ENCODE_DIRECT(ch, !base64SetO, !base64WhiteSpace)) {\r
+ /* shifting out */\r
+ if (base64bits) { /* output remaining bits */\r
+ *out++ = TO_BASE64(base64buffer << (6-base64bits));\r
+ base64buffer = 0;\r
+ base64bits = 0;\r
+ }\r
+ inShift = 0;\r
+ /* Characters not in the BASE64 set implicitly unshift the sequence\r
+ so no '-' is required, except if the character is itself a '-' */\r
+ if (IS_BASE64(ch) || ch == '-') {\r
+ *out++ = '-';\r
+ }\r
+ *out++ = (char) ch;\r
+ }\r
+ else {\r
+ goto encode_char;\r
+ }\r
+ }\r
+ else { /* not in a shift sequence */\r
+ if (ch == '+') {\r
+ *out++ = '+';\r
+ *out++ = '-';\r
+ }\r
+ else if (ENCODE_DIRECT(ch, !base64SetO, !base64WhiteSpace)) {\r
+ *out++ = (char) ch;\r
+ }\r
+ else {\r
+ *out++ = '+';\r
+ inShift = 1;\r
+ goto encode_char;\r
+ }\r
+ }\r
+ continue;\r
+encode_char:\r
+#ifdef Py_UNICODE_WIDE\r
+ if (ch >= 0x10000) {\r
+ /* code first surrogate */\r
+ base64bits += 16;\r
+ base64buffer = (base64buffer << 16) | 0xd800 | ((ch-0x10000) >> 10);\r
+ while (base64bits >= 6) {\r
+ *out++ = TO_BASE64(base64buffer >> (base64bits-6));\r
+ base64bits -= 6;\r
+ }\r
+ /* prepare second surrogate */\r
+ ch = 0xDC00 | ((ch-0x10000) & 0x3FF);\r
+ }\r
+#endif\r
+ base64bits += 16;\r
+ base64buffer = (base64buffer << 16) | ch;\r
+ while (base64bits >= 6) {\r
+ *out++ = TO_BASE64(base64buffer >> (base64bits-6));\r
+ base64bits -= 6;\r
+ }\r
+ }\r
+ if (base64bits)\r
+ *out++= TO_BASE64(base64buffer << (6-base64bits) );\r
+ if (inShift)\r
+ *out++ = '-';\r
+\r
+ if (_PyString_Resize(&v, out - start))\r
+ return NULL;\r
+ return v;\r
+}\r
+\r
+#undef IS_BASE64\r
+#undef FROM_BASE64\r
+#undef TO_BASE64\r
+#undef DECODE_DIRECT\r
+#undef ENCODE_DIRECT\r
+\r
+/* --- UTF-8 Codec -------------------------------------------------------- */\r
+\r
+static\r
+char utf8_code_length[256] = {\r
+ /* Map UTF-8 encoded prefix byte to sequence length. Zero means\r
+ illegal prefix. See RFC 3629 for details */\r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00-0F */\r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70-7F */\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80-8F */\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0-BF */\r
+ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* C0-C1 + C2-CF */\r
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* D0-DF */\r
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* E0-EF */\r
+ 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0-F4 + F5-FF */\r
+};\r
+\r
+PyObject *PyUnicode_DecodeUTF8(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ return PyUnicode_DecodeUTF8Stateful(s, size, errors, NULL);\r
+}\r
+\r
+PyObject *PyUnicode_DecodeUTF8Stateful(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ Py_ssize_t *consumed)\r
+{\r
+ const char *starts = s;\r
+ int n;\r
+ int k;\r
+ Py_ssize_t startinpos;\r
+ Py_ssize_t endinpos;\r
+ Py_ssize_t outpos;\r
+ const char *e;\r
+ PyUnicodeObject *unicode;\r
+ Py_UNICODE *p;\r
+ const char *errmsg = "";\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+\r
+ /* Note: size will always be longer than the resulting Unicode\r
+ character count */\r
+ unicode = _PyUnicode_New(size);\r
+ if (!unicode)\r
+ return NULL;\r
+ if (size == 0) {\r
+ if (consumed)\r
+ *consumed = 0;\r
+ return (PyObject *)unicode;\r
+ }\r
+\r
+ /* Unpack UTF-8 encoded data */\r
+ p = unicode->str;\r
+ e = s + size;\r
+\r
+ while (s < e) {\r
+ Py_UCS4 ch = (unsigned char)*s;\r
+\r
+ if (ch < 0x80) {\r
+ *p++ = (Py_UNICODE)ch;\r
+ s++;\r
+ continue;\r
+ }\r
+\r
+ n = utf8_code_length[ch];\r
+\r
+ if (s + n > e) {\r
+ if (consumed)\r
+ break;\r
+ else {\r
+ errmsg = "unexpected end of data";\r
+ startinpos = s-starts;\r
+ endinpos = startinpos+1;\r
+ for (k=1; (k < size-startinpos) && ((s[k]&0xC0) == 0x80); k++)\r
+ endinpos++;\r
+ goto utf8Error;\r
+ }\r
+ }\r
+\r
+ switch (n) {\r
+\r
+ case 0:\r
+ errmsg = "invalid start byte";\r
+ startinpos = s-starts;\r
+ endinpos = startinpos+1;\r
+ goto utf8Error;\r
+\r
+ case 1:\r
+ errmsg = "internal error";\r
+ startinpos = s-starts;\r
+ endinpos = startinpos+1;\r
+ goto utf8Error;\r
+\r
+ case 2:\r
+ if ((s[1] & 0xc0) != 0x80) {\r
+ errmsg = "invalid continuation byte";\r
+ startinpos = s-starts;\r
+ endinpos = startinpos + 1;\r
+ goto utf8Error;\r
+ }\r
+ ch = ((s[0] & 0x1f) << 6) + (s[1] & 0x3f);\r
+ assert ((ch > 0x007F) && (ch <= 0x07FF));\r
+ *p++ = (Py_UNICODE)ch;\r
+ break;\r
+\r
+ case 3:\r
+ /* XXX: surrogates shouldn't be valid UTF-8!\r
+ see http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf\r
+ (table 3-7) and http://www.rfc-editor.org/rfc/rfc3629.txt\r
+ Uncomment the 2 lines below to make them invalid,\r
+ code points: d800-dfff; UTF-8: \xed\xa0\x80-\xed\xbf\xbf. */\r
+ if ((s[1] & 0xc0) != 0x80 ||\r
+ (s[2] & 0xc0) != 0x80 ||\r
+ ((unsigned char)s[0] == 0xE0 &&\r
+ (unsigned char)s[1] < 0xA0)/* ||\r
+ ((unsigned char)s[0] == 0xED &&\r
+ (unsigned char)s[1] > 0x9F)*/) {\r
+ errmsg = "invalid continuation byte";\r
+ startinpos = s-starts;\r
+ endinpos = startinpos + 1;\r
+\r
+ /* if s[1] first two bits are 1 and 0, then the invalid\r
+ continuation byte is s[2], so increment endinpos by 1,\r
+ if not, s[1] is invalid and endinpos doesn't need to\r
+ be incremented. */\r
+ if ((s[1] & 0xC0) == 0x80)\r
+ endinpos++;\r
+ goto utf8Error;\r
+ }\r
+ ch = ((s[0] & 0x0f) << 12) + ((s[1] & 0x3f) << 6) + (s[2] & 0x3f);\r
+ assert ((ch > 0x07FF) && (ch <= 0xFFFF));\r
+ *p++ = (Py_UNICODE)ch;\r
+ break;\r
+\r
+ case 4:\r
+ if ((s[1] & 0xc0) != 0x80 ||\r
+ (s[2] & 0xc0) != 0x80 ||\r
+ (s[3] & 0xc0) != 0x80 ||\r
+ ((unsigned char)s[0] == 0xF0 &&\r
+ (unsigned char)s[1] < 0x90) ||\r
+ ((unsigned char)s[0] == 0xF4 &&\r
+ (unsigned char)s[1] > 0x8F)) {\r
+ errmsg = "invalid continuation byte";\r
+ startinpos = s-starts;\r
+ endinpos = startinpos + 1;\r
+ if ((s[1] & 0xC0) == 0x80) {\r
+ endinpos++;\r
+ if ((s[2] & 0xC0) == 0x80)\r
+ endinpos++;\r
+ }\r
+ goto utf8Error;\r
+ }\r
+ ch = ((s[0] & 0x7) << 18) + ((s[1] & 0x3f) << 12) +\r
+ ((s[2] & 0x3f) << 6) + (s[3] & 0x3f);\r
+ assert ((ch > 0xFFFF) && (ch <= 0x10ffff));\r
+\r
+#ifdef Py_UNICODE_WIDE\r
+ *p++ = (Py_UNICODE)ch;\r
+#else\r
+ /* compute and append the two surrogates: */\r
+\r
+ /* translate from 10000..10FFFF to 0..FFFF */\r
+ ch -= 0x10000;\r
+\r
+ /* high surrogate = top 10 bits added to D800 */\r
+ *p++ = (Py_UNICODE)(0xD800 + (ch >> 10));\r
+\r
+ /* low surrogate = bottom 10 bits added to DC00 */\r
+ *p++ = (Py_UNICODE)(0xDC00 + (ch & 0x03FF));\r
+#endif\r
+ break;\r
+ }\r
+ s += n;\r
+ continue;\r
+\r
+ utf8Error:\r
+ outpos = p-PyUnicode_AS_UNICODE(unicode);\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "utf8", errmsg,\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &unicode, &outpos, &p))\r
+ goto onError;\r
+ }\r
+ if (consumed)\r
+ *consumed = s-starts;\r
+\r
+ /* Adjust length */\r
+ if (_PyUnicode_Resize(&unicode, p - unicode->str) < 0)\r
+ goto onError;\r
+\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return (PyObject *)unicode;\r
+\r
+ onError:\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ Py_DECREF(unicode);\r
+ return NULL;\r
+}\r
+\r
+/* Allocation strategy: if the string is short, convert into a stack buffer\r
+ and allocate exactly as much space needed at the end. Else allocate the\r
+ maximum possible needed (4 result bytes per Unicode character), and return\r
+ the excess memory at the end.\r
+*/\r
+PyObject *\r
+PyUnicode_EncodeUTF8(const Py_UNICODE *s,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+#define MAX_SHORT_UNICHARS 300 /* largest size we'll do on the stack */\r
+\r
+ Py_ssize_t i; /* index into s of next input byte */\r
+ PyObject *v; /* result string object */\r
+ char *p; /* next free byte in output buffer */\r
+ Py_ssize_t nallocated; /* number of result bytes allocated */\r
+ Py_ssize_t nneeded; /* number of result bytes needed */\r
+ char stackbuf[MAX_SHORT_UNICHARS * 4];\r
+\r
+ assert(s != NULL);\r
+ assert(size >= 0);\r
+\r
+ if (size <= MAX_SHORT_UNICHARS) {\r
+ /* Write into the stack buffer; nallocated can't overflow.\r
+ * At the end, we'll allocate exactly as much heap space as it\r
+ * turns out we need.\r
+ */\r
+ nallocated = Py_SAFE_DOWNCAST(sizeof(stackbuf), size_t, int);\r
+ v = NULL; /* will allocate after we're done */\r
+ p = stackbuf;\r
+ }\r
+ else {\r
+ /* Overallocate on the heap, and give the excess back at the end. */\r
+ nallocated = size * 4;\r
+ if (nallocated / 4 != size) /* overflow! */\r
+ return PyErr_NoMemory();\r
+ v = PyString_FromStringAndSize(NULL, nallocated);\r
+ if (v == NULL)\r
+ return NULL;\r
+ p = PyString_AS_STRING(v);\r
+ }\r
+\r
+ for (i = 0; i < size;) {\r
+ Py_UCS4 ch = s[i++];\r
+\r
+ if (ch < 0x80)\r
+ /* Encode ASCII */\r
+ *p++ = (char) ch;\r
+\r
+ else if (ch < 0x0800) {\r
+ /* Encode Latin-1 */\r
+ *p++ = (char)(0xc0 | (ch >> 6));\r
+ *p++ = (char)(0x80 | (ch & 0x3f));\r
+ }\r
+ else {\r
+ /* Encode UCS2 Unicode ordinals */\r
+ if (ch < 0x10000) {\r
+ /* Special case: check for high surrogate */\r
+ if (0xD800 <= ch && ch <= 0xDBFF && i != size) {\r
+ Py_UCS4 ch2 = s[i];\r
+ /* Check for low surrogate and combine the two to\r
+ form a UCS4 value */\r
+ if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {\r
+ ch = ((ch - 0xD800) << 10 | (ch2 - 0xDC00)) + 0x10000;\r
+ i++;\r
+ goto encodeUCS4;\r
+ }\r
+ /* Fall through: handles isolated high surrogates */\r
+ }\r
+ *p++ = (char)(0xe0 | (ch >> 12));\r
+ *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));\r
+ *p++ = (char)(0x80 | (ch & 0x3f));\r
+ continue;\r
+ }\r
+ encodeUCS4:\r
+ /* Encode UCS4 Unicode ordinals */\r
+ *p++ = (char)(0xf0 | (ch >> 18));\r
+ *p++ = (char)(0x80 | ((ch >> 12) & 0x3f));\r
+ *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));\r
+ *p++ = (char)(0x80 | (ch & 0x3f));\r
+ }\r
+ }\r
+\r
+ if (v == NULL) {\r
+ /* This was stack allocated. */\r
+ nneeded = p - stackbuf;\r
+ assert(nneeded <= nallocated);\r
+ v = PyString_FromStringAndSize(stackbuf, nneeded);\r
+ }\r
+ else {\r
+ /* Cut back to size actually needed. */\r
+ nneeded = p - PyString_AS_STRING(v);\r
+ assert(nneeded <= nallocated);\r
+ if (_PyString_Resize(&v, nneeded))\r
+ return NULL;\r
+ }\r
+ return v;\r
+\r
+#undef MAX_SHORT_UNICHARS\r
+}\r
+\r
+PyObject *PyUnicode_AsUTF8String(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ return PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode),\r
+ NULL);\r
+}\r
+\r
+/* --- UTF-32 Codec ------------------------------------------------------- */\r
+\r
+PyObject *\r
+PyUnicode_DecodeUTF32(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ int *byteorder)\r
+{\r
+ return PyUnicode_DecodeUTF32Stateful(s, size, errors, byteorder, NULL);\r
+}\r
+\r
+PyObject *\r
+PyUnicode_DecodeUTF32Stateful(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ int *byteorder,\r
+ Py_ssize_t *consumed)\r
+{\r
+ const char *starts = s;\r
+ Py_ssize_t startinpos;\r
+ Py_ssize_t endinpos;\r
+ Py_ssize_t outpos;\r
+ PyUnicodeObject *unicode;\r
+ Py_UNICODE *p;\r
+#ifndef Py_UNICODE_WIDE\r
+ int pairs = 0;\r
+ const unsigned char *qq;\r
+#else\r
+ const int pairs = 0;\r
+#endif\r
+ const unsigned char *q, *e;\r
+ int bo = 0; /* assume native ordering by default */\r
+ const char *errmsg = "";\r
+ /* Offsets from q for retrieving bytes in the right order. */\r
+#ifdef BYTEORDER_IS_LITTLE_ENDIAN\r
+ int iorder[] = {0, 1, 2, 3};\r
+#else\r
+ int iorder[] = {3, 2, 1, 0};\r
+#endif\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+\r
+ q = (unsigned char *)s;\r
+ e = q + size;\r
+\r
+ if (byteorder)\r
+ bo = *byteorder;\r
+\r
+ /* Check for BOM marks (U+FEFF) in the input and adjust current\r
+ byte order setting accordingly. In native mode, the leading BOM\r
+ mark is skipped, in all other modes, it is copied to the output\r
+ stream as-is (giving a ZWNBSP character). */\r
+ if (bo == 0) {\r
+ if (size >= 4) {\r
+ const Py_UCS4 bom = (q[iorder[3]] << 24) | (q[iorder[2]] << 16) |\r
+ (q[iorder[1]] << 8) | q[iorder[0]];\r
+#ifdef BYTEORDER_IS_LITTLE_ENDIAN\r
+ if (bom == 0x0000FEFF) {\r
+ q += 4;\r
+ bo = -1;\r
+ }\r
+ else if (bom == 0xFFFE0000) {\r
+ q += 4;\r
+ bo = 1;\r
+ }\r
+#else\r
+ if (bom == 0x0000FEFF) {\r
+ q += 4;\r
+ bo = 1;\r
+ }\r
+ else if (bom == 0xFFFE0000) {\r
+ q += 4;\r
+ bo = -1;\r
+ }\r
+#endif\r
+ }\r
+ }\r
+\r
+ if (bo == -1) {\r
+ /* force LE */\r
+ iorder[0] = 0;\r
+ iorder[1] = 1;\r
+ iorder[2] = 2;\r
+ iorder[3] = 3;\r
+ }\r
+ else if (bo == 1) {\r
+ /* force BE */\r
+ iorder[0] = 3;\r
+ iorder[1] = 2;\r
+ iorder[2] = 1;\r
+ iorder[3] = 0;\r
+ }\r
+\r
+ /* On narrow builds we split characters outside the BMP into two\r
+ code points => count how much extra space we need. */\r
+#ifndef Py_UNICODE_WIDE\r
+ for (qq = q; e - qq >= 4; qq += 4)\r
+ if (qq[iorder[2]] != 0 || qq[iorder[3]] != 0)\r
+ pairs++;\r
+#endif\r
+\r
+ /* This might be one to much, because of a BOM */\r
+ unicode = _PyUnicode_New((size+3)/4+pairs);\r
+ if (!unicode)\r
+ return NULL;\r
+ if (size == 0)\r
+ return (PyObject *)unicode;\r
+\r
+ /* Unpack UTF-32 encoded data */\r
+ p = unicode->str;\r
+\r
+ while (q < e) {\r
+ Py_UCS4 ch;\r
+ /* remaining bytes at the end? (size should be divisible by 4) */\r
+ if (e-q<4) {\r
+ if (consumed)\r
+ break;\r
+ errmsg = "truncated data";\r
+ startinpos = ((const char *)q)-starts;\r
+ endinpos = ((const char *)e)-starts;\r
+ goto utf32Error;\r
+ /* The remaining input chars are ignored if the callback\r
+ chooses to skip the input */\r
+ }\r
+ ch = (q[iorder[3]] << 24) | (q[iorder[2]] << 16) |\r
+ (q[iorder[1]] << 8) | q[iorder[0]];\r
+\r
+ if (ch >= 0x110000)\r
+ {\r
+ errmsg = "code point not in range(0x110000)";\r
+ startinpos = ((const char *)q)-starts;\r
+ endinpos = startinpos+4;\r
+ goto utf32Error;\r
+ }\r
+#ifndef Py_UNICODE_WIDE\r
+ if (ch >= 0x10000)\r
+ {\r
+ *p++ = 0xD800 | ((ch-0x10000) >> 10);\r
+ *p++ = 0xDC00 | ((ch-0x10000) & 0x3FF);\r
+ }\r
+ else\r
+#endif\r
+ *p++ = ch;\r
+ q += 4;\r
+ continue;\r
+ utf32Error:\r
+ outpos = p-PyUnicode_AS_UNICODE(unicode);\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "utf32", errmsg,\r
+ starts, size, &startinpos, &endinpos, &exc, (const char **)&q,\r
+ &unicode, &outpos, &p))\r
+ goto onError;\r
+ }\r
+\r
+ if (byteorder)\r
+ *byteorder = bo;\r
+\r
+ if (consumed)\r
+ *consumed = (const char *)q-starts;\r
+\r
+ /* Adjust length */\r
+ if (_PyUnicode_Resize(&unicode, p - unicode->str) < 0)\r
+ goto onError;\r
+\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return (PyObject *)unicode;\r
+\r
+ onError:\r
+ Py_DECREF(unicode);\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return NULL;\r
+}\r
+\r
+PyObject *\r
+PyUnicode_EncodeUTF32(const Py_UNICODE *s,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ int byteorder)\r
+{\r
+ PyObject *v;\r
+ unsigned char *p;\r
+ Py_ssize_t nsize, bytesize;\r
+#ifndef Py_UNICODE_WIDE\r
+ Py_ssize_t i, pairs;\r
+#else\r
+ const int pairs = 0;\r
+#endif\r
+ /* Offsets from p for storing byte pairs in the right order. */\r
+#ifdef BYTEORDER_IS_LITTLE_ENDIAN\r
+ int iorder[] = {0, 1, 2, 3};\r
+#else\r
+ int iorder[] = {3, 2, 1, 0};\r
+#endif\r
+\r
+#define STORECHAR(CH) \\r
+ do { \\r
+ p[iorder[3]] = ((CH) >> 24) & 0xff; \\r
+ p[iorder[2]] = ((CH) >> 16) & 0xff; \\r
+ p[iorder[1]] = ((CH) >> 8) & 0xff; \\r
+ p[iorder[0]] = (CH) & 0xff; \\r
+ p += 4; \\r
+ } while(0)\r
+\r
+ /* In narrow builds we can output surrogate pairs as one code point,\r
+ so we need less space. */\r
+#ifndef Py_UNICODE_WIDE\r
+ for (i = pairs = 0; i < size-1; i++)\r
+ if (0xD800 <= s[i] && s[i] <= 0xDBFF &&\r
+ 0xDC00 <= s[i+1] && s[i+1] <= 0xDFFF)\r
+ pairs++;\r
+#endif\r
+ nsize = (size - pairs + (byteorder == 0));\r
+ bytesize = nsize * 4;\r
+ if (bytesize / 4 != nsize)\r
+ return PyErr_NoMemory();\r
+ v = PyString_FromStringAndSize(NULL, bytesize);\r
+ if (v == NULL)\r
+ return NULL;\r
+\r
+ p = (unsigned char *)PyString_AS_STRING(v);\r
+ if (byteorder == 0)\r
+ STORECHAR(0xFEFF);\r
+ if (size == 0)\r
+ return v;\r
+\r
+ if (byteorder == -1) {\r
+ /* force LE */\r
+ iorder[0] = 0;\r
+ iorder[1] = 1;\r
+ iorder[2] = 2;\r
+ iorder[3] = 3;\r
+ }\r
+ else if (byteorder == 1) {\r
+ /* force BE */\r
+ iorder[0] = 3;\r
+ iorder[1] = 2;\r
+ iorder[2] = 1;\r
+ iorder[3] = 0;\r
+ }\r
+\r
+ while (size-- > 0) {\r
+ Py_UCS4 ch = *s++;\r
+#ifndef Py_UNICODE_WIDE\r
+ if (0xD800 <= ch && ch <= 0xDBFF && size > 0) {\r
+ Py_UCS4 ch2 = *s;\r
+ if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {\r
+ ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000;\r
+ s++;\r
+ size--;\r
+ }\r
+ }\r
+#endif\r
+ STORECHAR(ch);\r
+ }\r
+ return v;\r
+#undef STORECHAR\r
+}\r
+\r
+PyObject *PyUnicode_AsUTF32String(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode),\r
+ NULL,\r
+ 0);\r
+}\r
+\r
+/* --- UTF-16 Codec ------------------------------------------------------- */\r
+\r
+PyObject *\r
+PyUnicode_DecodeUTF16(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ int *byteorder)\r
+{\r
+ return PyUnicode_DecodeUTF16Stateful(s, size, errors, byteorder, NULL);\r
+}\r
+\r
+PyObject *\r
+PyUnicode_DecodeUTF16Stateful(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ int *byteorder,\r
+ Py_ssize_t *consumed)\r
+{\r
+ const char *starts = s;\r
+ Py_ssize_t startinpos;\r
+ Py_ssize_t endinpos;\r
+ Py_ssize_t outpos;\r
+ PyUnicodeObject *unicode;\r
+ Py_UNICODE *p;\r
+ const unsigned char *q, *e;\r
+ int bo = 0; /* assume native ordering by default */\r
+ const char *errmsg = "";\r
+ /* Offsets from q for retrieving byte pairs in the right order. */\r
+#ifdef BYTEORDER_IS_LITTLE_ENDIAN\r
+ int ihi = 1, ilo = 0;\r
+#else\r
+ int ihi = 0, ilo = 1;\r
+#endif\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+\r
+ /* Note: size will always be longer than the resulting Unicode\r
+ character count */\r
+ unicode = _PyUnicode_New(size);\r
+ if (!unicode)\r
+ return NULL;\r
+ if (size == 0)\r
+ return (PyObject *)unicode;\r
+\r
+ /* Unpack UTF-16 encoded data */\r
+ p = unicode->str;\r
+ q = (unsigned char *)s;\r
+ e = q + size;\r
+\r
+ if (byteorder)\r
+ bo = *byteorder;\r
+\r
+ /* Check for BOM marks (U+FEFF) in the input and adjust current\r
+ byte order setting accordingly. In native mode, the leading BOM\r
+ mark is skipped, in all other modes, it is copied to the output\r
+ stream as-is (giving a ZWNBSP character). */\r
+ if (bo == 0) {\r
+ if (size >= 2) {\r
+ const Py_UNICODE bom = (q[ihi] << 8) | q[ilo];\r
+#ifdef BYTEORDER_IS_LITTLE_ENDIAN\r
+ if (bom == 0xFEFF) {\r
+ q += 2;\r
+ bo = -1;\r
+ }\r
+ else if (bom == 0xFFFE) {\r
+ q += 2;\r
+ bo = 1;\r
+ }\r
+#else\r
+ if (bom == 0xFEFF) {\r
+ q += 2;\r
+ bo = 1;\r
+ }\r
+ else if (bom == 0xFFFE) {\r
+ q += 2;\r
+ bo = -1;\r
+ }\r
+#endif\r
+ }\r
+ }\r
+\r
+ if (bo == -1) {\r
+ /* force LE */\r
+ ihi = 1;\r
+ ilo = 0;\r
+ }\r
+ else if (bo == 1) {\r
+ /* force BE */\r
+ ihi = 0;\r
+ ilo = 1;\r
+ }\r
+\r
+ while (q < e) {\r
+ Py_UNICODE ch;\r
+ /* remaining bytes at the end? (size should be even) */\r
+ if (e-q<2) {\r
+ if (consumed)\r
+ break;\r
+ errmsg = "truncated data";\r
+ startinpos = ((const char *)q)-starts;\r
+ endinpos = ((const char *)e)-starts;\r
+ goto utf16Error;\r
+ /* The remaining input chars are ignored if the callback\r
+ chooses to skip the input */\r
+ }\r
+ ch = (q[ihi] << 8) | q[ilo];\r
+\r
+ q += 2;\r
+\r
+ if (ch < 0xD800 || ch > 0xDFFF) {\r
+ *p++ = ch;\r
+ continue;\r
+ }\r
+\r
+ /* UTF-16 code pair: */\r
+ if (e - q < 2) {\r
+ q -= 2;\r
+ if (consumed)\r
+ break;\r
+ errmsg = "unexpected end of data";\r
+ startinpos = ((const char *)q)-starts;\r
+ endinpos = ((const char *)e)-starts;\r
+ goto utf16Error;\r
+ }\r
+ if (0xD800 <= ch && ch <= 0xDBFF) {\r
+ Py_UNICODE ch2 = (q[ihi] << 8) | q[ilo];\r
+ q += 2;\r
+ if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {\r
+#ifndef Py_UNICODE_WIDE\r
+ *p++ = ch;\r
+ *p++ = ch2;\r
+#else\r
+ *p++ = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000;\r
+#endif\r
+ continue;\r
+ }\r
+ else {\r
+ errmsg = "illegal UTF-16 surrogate";\r
+ startinpos = (((const char *)q)-4)-starts;\r
+ endinpos = startinpos+2;\r
+ goto utf16Error;\r
+ }\r
+\r
+ }\r
+ errmsg = "illegal encoding";\r
+ startinpos = (((const char *)q)-2)-starts;\r
+ endinpos = startinpos+2;\r
+ /* Fall through to report the error */\r
+\r
+ utf16Error:\r
+ outpos = p-PyUnicode_AS_UNICODE(unicode);\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "utf16", errmsg,\r
+ starts, size, &startinpos, &endinpos, &exc, (const char **)&q,\r
+ &unicode, &outpos, &p))\r
+ goto onError;\r
+ }\r
+\r
+ if (byteorder)\r
+ *byteorder = bo;\r
+\r
+ if (consumed)\r
+ *consumed = (const char *)q-starts;\r
+\r
+ /* Adjust length */\r
+ if (_PyUnicode_Resize(&unicode, p - unicode->str) < 0)\r
+ goto onError;\r
+\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return (PyObject *)unicode;\r
+\r
+ onError:\r
+ Py_DECREF(unicode);\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return NULL;\r
+}\r
+\r
+PyObject *\r
+PyUnicode_EncodeUTF16(const Py_UNICODE *s,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ int byteorder)\r
+{\r
+ PyObject *v;\r
+ unsigned char *p;\r
+ Py_ssize_t nsize, bytesize;\r
+#ifdef Py_UNICODE_WIDE\r
+ Py_ssize_t i, pairs;\r
+#else\r
+ const int pairs = 0;\r
+#endif\r
+ /* Offsets from p for storing byte pairs in the right order. */\r
+#ifdef BYTEORDER_IS_LITTLE_ENDIAN\r
+ int ihi = 1, ilo = 0;\r
+#else\r
+ int ihi = 0, ilo = 1;\r
+#endif\r
+\r
+#define STORECHAR(CH) \\r
+ do { \\r
+ p[ihi] = ((CH) >> 8) & 0xff; \\r
+ p[ilo] = (CH) & 0xff; \\r
+ p += 2; \\r
+ } while(0)\r
+\r
+#ifdef Py_UNICODE_WIDE\r
+ for (i = pairs = 0; i < size; i++)\r
+ if (s[i] >= 0x10000)\r
+ pairs++;\r
+#endif\r
+ /* 2 * (size + pairs + (byteorder == 0)) */\r
+ if (size > PY_SSIZE_T_MAX ||\r
+ size > PY_SSIZE_T_MAX - pairs - (byteorder == 0))\r
+ return PyErr_NoMemory();\r
+ nsize = size + pairs + (byteorder == 0);\r
+ bytesize = nsize * 2;\r
+ if (bytesize / 2 != nsize)\r
+ return PyErr_NoMemory();\r
+ v = PyString_FromStringAndSize(NULL, bytesize);\r
+ if (v == NULL)\r
+ return NULL;\r
+\r
+ p = (unsigned char *)PyString_AS_STRING(v);\r
+ if (byteorder == 0)\r
+ STORECHAR(0xFEFF);\r
+ if (size == 0)\r
+ return v;\r
+\r
+ if (byteorder == -1) {\r
+ /* force LE */\r
+ ihi = 1;\r
+ ilo = 0;\r
+ }\r
+ else if (byteorder == 1) {\r
+ /* force BE */\r
+ ihi = 0;\r
+ ilo = 1;\r
+ }\r
+\r
+ while (size-- > 0) {\r
+ Py_UNICODE ch = *s++;\r
+ Py_UNICODE ch2 = 0;\r
+#ifdef Py_UNICODE_WIDE\r
+ if (ch >= 0x10000) {\r
+ ch2 = 0xDC00 | ((ch-0x10000) & 0x3FF);\r
+ ch = 0xD800 | ((ch-0x10000) >> 10);\r
+ }\r
+#endif\r
+ STORECHAR(ch);\r
+ if (ch2)\r
+ STORECHAR(ch2);\r
+ }\r
+ return v;\r
+#undef STORECHAR\r
+}\r
+\r
+PyObject *PyUnicode_AsUTF16String(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode),\r
+ NULL,\r
+ 0);\r
+}\r
+\r
+/* --- Unicode Escape Codec ----------------------------------------------- */\r
+\r
+static _PyUnicode_Name_CAPI *ucnhash_CAPI = NULL;\r
+\r
+PyObject *PyUnicode_DecodeUnicodeEscape(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ const char *starts = s;\r
+ Py_ssize_t startinpos;\r
+ Py_ssize_t endinpos;\r
+ Py_ssize_t outpos;\r
+ PyUnicodeObject *v;\r
+ Py_UNICODE *p;\r
+ const char *end;\r
+ char* message;\r
+ Py_UCS4 chr = 0xffffffff; /* in case 'getcode' messes up */\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+\r
+ /* Escaped strings will always be longer than the resulting\r
+ Unicode string, so we start with size here and then reduce the\r
+ length after conversion to the true value.\r
+ (but if the error callback returns a long replacement string\r
+ we'll have to allocate more space) */\r
+ v = _PyUnicode_New(size);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (size == 0)\r
+ return (PyObject *)v;\r
+\r
+ p = PyUnicode_AS_UNICODE(v);\r
+ end = s + size;\r
+\r
+ while (s < end) {\r
+ unsigned char c;\r
+ Py_UNICODE x;\r
+ int digits;\r
+\r
+ /* Non-escape characters are interpreted as Unicode ordinals */\r
+ if (*s != '\\') {\r
+ *p++ = (unsigned char) *s++;\r
+ continue;\r
+ }\r
+\r
+ startinpos = s-starts;\r
+ /* \ - Escapes */\r
+ s++;\r
+ c = *s++;\r
+ if (s > end)\r
+ c = '\0'; /* Invalid after \ */\r
+ switch (c) {\r
+\r
+ /* \x escapes */\r
+ case '\n': break;\r
+ case '\\': *p++ = '\\'; break;\r
+ case '\'': *p++ = '\''; break;\r
+ case '\"': *p++ = '\"'; break;\r
+ case 'b': *p++ = '\b'; break;\r
+ case 'f': *p++ = '\014'; break; /* FF */\r
+ case 't': *p++ = '\t'; break;\r
+ case 'n': *p++ = '\n'; break;\r
+ case 'r': *p++ = '\r'; break;\r
+ case 'v': *p++ = '\013'; break; /* VT */\r
+ case 'a': *p++ = '\007'; break; /* BEL, not classic C */\r
+\r
+ /* \OOO (octal) escapes */\r
+ case '0': case '1': case '2': case '3':\r
+ case '4': case '5': case '6': case '7':\r
+ x = s[-1] - '0';\r
+ if (s < end && '0' <= *s && *s <= '7') {\r
+ x = (x<<3) + *s++ - '0';\r
+ if (s < end && '0' <= *s && *s <= '7')\r
+ x = (x<<3) + *s++ - '0';\r
+ }\r
+ *p++ = x;\r
+ break;\r
+\r
+ /* hex escapes */\r
+ /* \xXX */\r
+ case 'x':\r
+ digits = 2;\r
+ message = "truncated \\xXX escape";\r
+ goto hexescape;\r
+\r
+ /* \uXXXX */\r
+ case 'u':\r
+ digits = 4;\r
+ message = "truncated \\uXXXX escape";\r
+ goto hexescape;\r
+\r
+ /* \UXXXXXXXX */\r
+ case 'U':\r
+ digits = 8;\r
+ message = "truncated \\UXXXXXXXX escape";\r
+ hexescape:\r
+ chr = 0;\r
+ if (end - s < digits) {\r
+ /* count only hex digits */\r
+ for (; s < end; ++s) {\r
+ c = (unsigned char)*s;\r
+ if (!Py_ISXDIGIT(c))\r
+ goto error;\r
+ }\r
+ goto error;\r
+ }\r
+ for (; digits--; ++s) {\r
+ c = (unsigned char)*s;\r
+ if (!Py_ISXDIGIT(c))\r
+ goto error;\r
+ chr = (chr<<4) & ~0xF;\r
+ if (c >= '0' && c <= '9')\r
+ chr += c - '0';\r
+ else if (c >= 'a' && c <= 'f')\r
+ chr += 10 + c - 'a';\r
+ else\r
+ chr += 10 + c - 'A';\r
+ }\r
+ if (chr == 0xffffffff && PyErr_Occurred())\r
+ /* _decoding_error will have already written into the\r
+ target buffer. */\r
+ break;\r
+ store:\r
+ /* when we get here, chr is a 32-bit unicode character */\r
+ if (chr <= 0xffff)\r
+ /* UCS-2 character */\r
+ *p++ = (Py_UNICODE) chr;\r
+ else if (chr <= 0x10ffff) {\r
+ /* UCS-4 character. Either store directly, or as\r
+ surrogate pair. */\r
+#ifdef Py_UNICODE_WIDE\r
+ *p++ = chr;\r
+#else\r
+ chr -= 0x10000L;\r
+ *p++ = 0xD800 + (Py_UNICODE) (chr >> 10);\r
+ *p++ = 0xDC00 + (Py_UNICODE) (chr & 0x03FF);\r
+#endif\r
+ } else {\r
+ message = "illegal Unicode character";\r
+ goto error;\r
+ }\r
+ break;\r
+\r
+ /* \N{name} */\r
+ case 'N':\r
+ message = "malformed \\N character escape";\r
+ if (ucnhash_CAPI == NULL) {\r
+ /* load the unicode data module */\r
+ ucnhash_CAPI = (_PyUnicode_Name_CAPI *)PyCapsule_Import(PyUnicodeData_CAPSULE_NAME, 1);\r
+ if (ucnhash_CAPI == NULL)\r
+ goto ucnhashError;\r
+ }\r
+ if (*s == '{') {\r
+ const char *start = s+1;\r
+ /* look for the closing brace */\r
+ while (*s != '}' && s < end)\r
+ s++;\r
+ if (s > start && s < end && *s == '}') {\r
+ /* found a name. look it up in the unicode database */\r
+ message = "unknown Unicode character name";\r
+ s++;\r
+ if (s - start - 1 <= INT_MAX &&\r
+ ucnhash_CAPI->getcode(NULL, start, (int)(s-start-1), &chr))\r
+ goto store;\r
+ }\r
+ }\r
+ goto error;\r
+\r
+ default:\r
+ if (s > end) {\r
+ message = "\\ at end of string";\r
+ s--;\r
+ goto error;\r
+ }\r
+ else {\r
+ *p++ = '\\';\r
+ *p++ = (unsigned char)s[-1];\r
+ }\r
+ break;\r
+ }\r
+ continue;\r
+\r
+ error:\r
+ endinpos = s-starts;\r
+ outpos = p-PyUnicode_AS_UNICODE(v);\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "unicodeescape", message,\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &v, &outpos, &p))\r
+ goto onError;\r
+ continue;\r
+ }\r
+ if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)\r
+ goto onError;\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return (PyObject *)v;\r
+\r
+ ucnhashError:\r
+ PyErr_SetString(\r
+ PyExc_UnicodeError,\r
+ "\\N escapes not supported (can't load unicodedata module)"\r
+ );\r
+ Py_XDECREF(v);\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return NULL;\r
+\r
+ onError:\r
+ Py_XDECREF(v);\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return NULL;\r
+}\r
+\r
+/* Return a Unicode-Escape string version of the Unicode object.\r
+\r
+ If quotes is true, the string is enclosed in u"" or u'' quotes as\r
+ appropriate.\r
+\r
+*/\r
+\r
+Py_LOCAL_INLINE(const Py_UNICODE *) findchar(const Py_UNICODE *s,\r
+ Py_ssize_t size,\r
+ Py_UNICODE ch)\r
+{\r
+ /* like wcschr, but doesn't stop at NULL characters */\r
+\r
+ while (size-- > 0) {\r
+ if (*s == ch)\r
+ return s;\r
+ s++;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+static\r
+PyObject *unicodeescape_string(const Py_UNICODE *s,\r
+ Py_ssize_t size,\r
+ int quotes)\r
+{\r
+ PyObject *repr;\r
+ char *p;\r
+\r
+ static const char *hexdigit = "0123456789abcdef";\r
+#ifdef Py_UNICODE_WIDE\r
+ const Py_ssize_t expandsize = 10;\r
+#else\r
+ const Py_ssize_t expandsize = 6;\r
+#endif\r
+\r
+ /* XXX(nnorwitz): rather than over-allocating, it would be\r
+ better to choose a different scheme. Perhaps scan the\r
+ first N-chars of the string and allocate based on that size.\r
+ */\r
+ /* Initial allocation is based on the longest-possible unichr\r
+ escape.\r
+\r
+ In wide (UTF-32) builds '\U00xxxxxx' is 10 chars per source\r
+ unichr, so in this case it's the longest unichr escape. In\r
+ narrow (UTF-16) builds this is five chars per source unichr\r
+ since there are two unichrs in the surrogate pair, so in narrow\r
+ (UTF-16) builds it's not the longest unichr escape.\r
+\r
+ In wide or narrow builds '\uxxxx' is 6 chars per source unichr,\r
+ so in the narrow (UTF-16) build case it's the longest unichr\r
+ escape.\r
+ */\r
+\r
+ if (size > (PY_SSIZE_T_MAX - 2 - 1) / expandsize)\r
+ return PyErr_NoMemory();\r
+\r
+ repr = PyString_FromStringAndSize(NULL,\r
+ 2\r
+ + expandsize*size\r
+ + 1);\r
+ if (repr == NULL)\r
+ return NULL;\r
+\r
+ p = PyString_AS_STRING(repr);\r
+\r
+ if (quotes) {\r
+ *p++ = 'u';\r
+ *p++ = (findchar(s, size, '\'') &&\r
+ !findchar(s, size, '"')) ? '"' : '\'';\r
+ }\r
+ while (size-- > 0) {\r
+ Py_UNICODE ch = *s++;\r
+\r
+ /* Escape quotes and backslashes */\r
+ if ((quotes &&\r
+ ch == (Py_UNICODE) PyString_AS_STRING(repr)[1]) || ch == '\\') {\r
+ *p++ = '\\';\r
+ *p++ = (char) ch;\r
+ continue;\r
+ }\r
+\r
+#ifdef Py_UNICODE_WIDE\r
+ /* Map 21-bit characters to '\U00xxxxxx' */\r
+ else if (ch >= 0x10000) {\r
+ *p++ = '\\';\r
+ *p++ = 'U';\r
+ *p++ = hexdigit[(ch >> 28) & 0x0000000F];\r
+ *p++ = hexdigit[(ch >> 24) & 0x0000000F];\r
+ *p++ = hexdigit[(ch >> 20) & 0x0000000F];\r
+ *p++ = hexdigit[(ch >> 16) & 0x0000000F];\r
+ *p++ = hexdigit[(ch >> 12) & 0x0000000F];\r
+ *p++ = hexdigit[(ch >> 8) & 0x0000000F];\r
+ *p++ = hexdigit[(ch >> 4) & 0x0000000F];\r
+ *p++ = hexdigit[ch & 0x0000000F];\r
+ continue;\r
+ }\r
+#else\r
+ /* Map UTF-16 surrogate pairs to '\U00xxxxxx' */\r
+ else if (ch >= 0xD800 && ch < 0xDC00) {\r
+ Py_UNICODE ch2;\r
+ Py_UCS4 ucs;\r
+\r
+ ch2 = *s++;\r
+ size--;\r
+ if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {\r
+ ucs = (((ch & 0x03FF) << 10) | (ch2 & 0x03FF)) + 0x00010000;\r
+ *p++ = '\\';\r
+ *p++ = 'U';\r
+ *p++ = hexdigit[(ucs >> 28) & 0x0000000F];\r
+ *p++ = hexdigit[(ucs >> 24) & 0x0000000F];\r
+ *p++ = hexdigit[(ucs >> 20) & 0x0000000F];\r
+ *p++ = hexdigit[(ucs >> 16) & 0x0000000F];\r
+ *p++ = hexdigit[(ucs >> 12) & 0x0000000F];\r
+ *p++ = hexdigit[(ucs >> 8) & 0x0000000F];\r
+ *p++ = hexdigit[(ucs >> 4) & 0x0000000F];\r
+ *p++ = hexdigit[ucs & 0x0000000F];\r
+ continue;\r
+ }\r
+ /* Fall through: isolated surrogates are copied as-is */\r
+ s--;\r
+ size++;\r
+ }\r
+#endif\r
+\r
+ /* Map 16-bit characters to '\uxxxx' */\r
+ if (ch >= 256) {\r
+ *p++ = '\\';\r
+ *p++ = 'u';\r
+ *p++ = hexdigit[(ch >> 12) & 0x000F];\r
+ *p++ = hexdigit[(ch >> 8) & 0x000F];\r
+ *p++ = hexdigit[(ch >> 4) & 0x000F];\r
+ *p++ = hexdigit[ch & 0x000F];\r
+ }\r
+\r
+ /* Map special whitespace to '\t', \n', '\r' */\r
+ else if (ch == '\t') {\r
+ *p++ = '\\';\r
+ *p++ = 't';\r
+ }\r
+ else if (ch == '\n') {\r
+ *p++ = '\\';\r
+ *p++ = 'n';\r
+ }\r
+ else if (ch == '\r') {\r
+ *p++ = '\\';\r
+ *p++ = 'r';\r
+ }\r
+\r
+ /* Map non-printable US ASCII to '\xhh' */\r
+ else if (ch < ' ' || ch >= 0x7F) {\r
+ *p++ = '\\';\r
+ *p++ = 'x';\r
+ *p++ = hexdigit[(ch >> 4) & 0x000F];\r
+ *p++ = hexdigit[ch & 0x000F];\r
+ }\r
+\r
+ /* Copy everything else as-is */\r
+ else\r
+ *p++ = (char) ch;\r
+ }\r
+ if (quotes)\r
+ *p++ = PyString_AS_STRING(repr)[1];\r
+\r
+ *p = '\0';\r
+ if (_PyString_Resize(&repr, p - PyString_AS_STRING(repr)))\r
+ return NULL;\r
+ return repr;\r
+}\r
+\r
+PyObject *PyUnicode_EncodeUnicodeEscape(const Py_UNICODE *s,\r
+ Py_ssize_t size)\r
+{\r
+ return unicodeescape_string(s, size, 0);\r
+}\r
+\r
+PyObject *PyUnicode_AsUnicodeEscapeString(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ return PyUnicode_EncodeUnicodeEscape(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode));\r
+}\r
+\r
+/* --- Raw Unicode Escape Codec ------------------------------------------- */\r
+\r
+PyObject *PyUnicode_DecodeRawUnicodeEscape(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ const char *starts = s;\r
+ Py_ssize_t startinpos;\r
+ Py_ssize_t endinpos;\r
+ Py_ssize_t outpos;\r
+ PyUnicodeObject *v;\r
+ Py_UNICODE *p;\r
+ const char *end;\r
+ const char *bs;\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+\r
+ /* Escaped strings will always be longer than the resulting\r
+ Unicode string, so we start with size here and then reduce the\r
+ length after conversion to the true value. (But decoding error\r
+ handler might have to resize the string) */\r
+ v = _PyUnicode_New(size);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (size == 0)\r
+ return (PyObject *)v;\r
+ p = PyUnicode_AS_UNICODE(v);\r
+ end = s + size;\r
+ while (s < end) {\r
+ unsigned char c;\r
+ Py_UCS4 x;\r
+ int i;\r
+ int count;\r
+\r
+ /* Non-escape characters are interpreted as Unicode ordinals */\r
+ if (*s != '\\') {\r
+ *p++ = (unsigned char)*s++;\r
+ continue;\r
+ }\r
+ startinpos = s-starts;\r
+\r
+ /* \u-escapes are only interpreted iff the number of leading\r
+ backslashes if odd */\r
+ bs = s;\r
+ for (;s < end;) {\r
+ if (*s != '\\')\r
+ break;\r
+ *p++ = (unsigned char)*s++;\r
+ }\r
+ if (((s - bs) & 1) == 0 ||\r
+ s >= end ||\r
+ (*s != 'u' && *s != 'U')) {\r
+ continue;\r
+ }\r
+ p--;\r
+ count = *s=='u' ? 4 : 8;\r
+ s++;\r
+\r
+ /* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */\r
+ outpos = p-PyUnicode_AS_UNICODE(v);\r
+ for (x = 0, i = 0; i < count; ++i, ++s) {\r
+ c = (unsigned char)*s;\r
+ if (!isxdigit(c)) {\r
+ endinpos = s-starts;\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "rawunicodeescape", "truncated \\uXXXX",\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &v, &outpos, &p))\r
+ goto onError;\r
+ goto nextByte;\r
+ }\r
+ x = (x<<4) & ~0xF;\r
+ if (c >= '0' && c <= '9')\r
+ x += c - '0';\r
+ else if (c >= 'a' && c <= 'f')\r
+ x += 10 + c - 'a';\r
+ else\r
+ x += 10 + c - 'A';\r
+ }\r
+ if (x <= 0xffff)\r
+ /* UCS-2 character */\r
+ *p++ = (Py_UNICODE) x;\r
+ else if (x <= 0x10ffff) {\r
+ /* UCS-4 character. Either store directly, or as\r
+ surrogate pair. */\r
+#ifdef Py_UNICODE_WIDE\r
+ *p++ = (Py_UNICODE) x;\r
+#else\r
+ x -= 0x10000L;\r
+ *p++ = 0xD800 + (Py_UNICODE) (x >> 10);\r
+ *p++ = 0xDC00 + (Py_UNICODE) (x & 0x03FF);\r
+#endif\r
+ } else {\r
+ endinpos = s-starts;\r
+ outpos = p-PyUnicode_AS_UNICODE(v);\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "rawunicodeescape", "\\Uxxxxxxxx out of range",\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &v, &outpos, &p))\r
+ goto onError;\r
+ }\r
+ nextByte:\r
+ ;\r
+ }\r
+ if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)\r
+ goto onError;\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return (PyObject *)v;\r
+\r
+ onError:\r
+ Py_XDECREF(v);\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s,\r
+ Py_ssize_t size)\r
+{\r
+ PyObject *repr;\r
+ char *p;\r
+ char *q;\r
+\r
+ static const char *hexdigit = "0123456789abcdef";\r
+#ifdef Py_UNICODE_WIDE\r
+ const Py_ssize_t expandsize = 10;\r
+#else\r
+ const Py_ssize_t expandsize = 6;\r
+#endif\r
+\r
+ if (size > PY_SSIZE_T_MAX / expandsize)\r
+ return PyErr_NoMemory();\r
+\r
+ repr = PyString_FromStringAndSize(NULL, expandsize * size);\r
+ if (repr == NULL)\r
+ return NULL;\r
+ if (size == 0)\r
+ return repr;\r
+\r
+ p = q = PyString_AS_STRING(repr);\r
+ while (size-- > 0) {\r
+ Py_UNICODE ch = *s++;\r
+#ifdef Py_UNICODE_WIDE\r
+ /* Map 32-bit characters to '\Uxxxxxxxx' */\r
+ if (ch >= 0x10000) {\r
+ *p++ = '\\';\r
+ *p++ = 'U';\r
+ *p++ = hexdigit[(ch >> 28) & 0xf];\r
+ *p++ = hexdigit[(ch >> 24) & 0xf];\r
+ *p++ = hexdigit[(ch >> 20) & 0xf];\r
+ *p++ = hexdigit[(ch >> 16) & 0xf];\r
+ *p++ = hexdigit[(ch >> 12) & 0xf];\r
+ *p++ = hexdigit[(ch >> 8) & 0xf];\r
+ *p++ = hexdigit[(ch >> 4) & 0xf];\r
+ *p++ = hexdigit[ch & 15];\r
+ }\r
+ else\r
+#else\r
+ /* Map UTF-16 surrogate pairs to '\U00xxxxxx' */\r
+ if (ch >= 0xD800 && ch < 0xDC00) {\r
+ Py_UNICODE ch2;\r
+ Py_UCS4 ucs;\r
+\r
+ ch2 = *s++;\r
+ size--;\r
+ if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {\r
+ ucs = (((ch & 0x03FF) << 10) | (ch2 & 0x03FF)) + 0x00010000;\r
+ *p++ = '\\';\r
+ *p++ = 'U';\r
+ *p++ = hexdigit[(ucs >> 28) & 0xf];\r
+ *p++ = hexdigit[(ucs >> 24) & 0xf];\r
+ *p++ = hexdigit[(ucs >> 20) & 0xf];\r
+ *p++ = hexdigit[(ucs >> 16) & 0xf];\r
+ *p++ = hexdigit[(ucs >> 12) & 0xf];\r
+ *p++ = hexdigit[(ucs >> 8) & 0xf];\r
+ *p++ = hexdigit[(ucs >> 4) & 0xf];\r
+ *p++ = hexdigit[ucs & 0xf];\r
+ continue;\r
+ }\r
+ /* Fall through: isolated surrogates are copied as-is */\r
+ s--;\r
+ size++;\r
+ }\r
+#endif\r
+ /* Map 16-bit characters to '\uxxxx' */\r
+ if (ch >= 256) {\r
+ *p++ = '\\';\r
+ *p++ = 'u';\r
+ *p++ = hexdigit[(ch >> 12) & 0xf];\r
+ *p++ = hexdigit[(ch >> 8) & 0xf];\r
+ *p++ = hexdigit[(ch >> 4) & 0xf];\r
+ *p++ = hexdigit[ch & 15];\r
+ }\r
+ /* Copy everything else as-is */\r
+ else\r
+ *p++ = (char) ch;\r
+ }\r
+ *p = '\0';\r
+ if (_PyString_Resize(&repr, p - q))\r
+ return NULL;\r
+ return repr;\r
+}\r
+\r
+PyObject *PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ return PyUnicode_EncodeRawUnicodeEscape(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode));\r
+}\r
+\r
+/* --- Unicode Internal Codec ------------------------------------------- */\r
+\r
+PyObject *_PyUnicode_DecodeUnicodeInternal(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ const char *starts = s;\r
+ Py_ssize_t startinpos;\r
+ Py_ssize_t endinpos;\r
+ Py_ssize_t outpos;\r
+ PyUnicodeObject *v;\r
+ Py_UNICODE *p;\r
+ const char *end;\r
+ const char *reason;\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+\r
+#ifdef Py_UNICODE_WIDE\r
+ Py_UNICODE unimax = PyUnicode_GetMax();\r
+#endif\r
+\r
+ /* XXX overflow detection missing */\r
+ v = _PyUnicode_New((size+Py_UNICODE_SIZE-1)/ Py_UNICODE_SIZE);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (PyUnicode_GetSize((PyObject *)v) == 0)\r
+ return (PyObject *)v;\r
+ p = PyUnicode_AS_UNICODE(v);\r
+ end = s + size;\r
+\r
+ while (s < end) {\r
+ if (end-s < Py_UNICODE_SIZE) {\r
+ endinpos = end-starts;\r
+ reason = "truncated input";\r
+ goto error;\r
+ }\r
+ memcpy(p, s, sizeof(Py_UNICODE));\r
+#ifdef Py_UNICODE_WIDE\r
+ /* We have to sanity check the raw data, otherwise doom looms for\r
+ some malformed UCS-4 data. */\r
+ if (*p > unimax || *p < 0) {\r
+ endinpos = s - starts + Py_UNICODE_SIZE;\r
+ reason = "illegal code point (> 0x10FFFF)";\r
+ goto error;\r
+ }\r
+#endif\r
+ p++;\r
+ s += Py_UNICODE_SIZE;\r
+ continue;\r
+\r
+ error:\r
+ startinpos = s - starts;\r
+ outpos = p - PyUnicode_AS_UNICODE(v);\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "unicode_internal", reason,\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &v, &outpos, &p)) {\r
+ goto onError;\r
+ }\r
+ }\r
+\r
+ if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)\r
+ goto onError;\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return (PyObject *)v;\r
+\r
+ onError:\r
+ Py_XDECREF(v);\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return NULL;\r
+}\r
+\r
+/* --- Latin-1 Codec ------------------------------------------------------ */\r
+\r
+PyObject *PyUnicode_DecodeLatin1(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ PyUnicodeObject *v;\r
+ Py_UNICODE *p;\r
+\r
+ /* Latin-1 is equivalent to the first 256 ordinals in Unicode. */\r
+ if (size == 1) {\r
+ Py_UNICODE r = *(unsigned char*)s;\r
+ return PyUnicode_FromUnicode(&r, 1);\r
+ }\r
+\r
+ v = _PyUnicode_New(size);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (size == 0)\r
+ return (PyObject *)v;\r
+ p = PyUnicode_AS_UNICODE(v);\r
+ while (size-- > 0)\r
+ *p++ = (unsigned char)*s++;\r
+ return (PyObject *)v;\r
+\r
+ onError:\r
+ Py_XDECREF(v);\r
+ return NULL;\r
+}\r
+\r
+/* create or adjust a UnicodeEncodeError */\r
+static void make_encode_exception(PyObject **exceptionObject,\r
+ const char *encoding,\r
+ const Py_UNICODE *unicode, Py_ssize_t size,\r
+ Py_ssize_t startpos, Py_ssize_t endpos,\r
+ const char *reason)\r
+{\r
+ if (*exceptionObject == NULL) {\r
+ *exceptionObject = PyUnicodeEncodeError_Create(\r
+ encoding, unicode, size, startpos, endpos, reason);\r
+ }\r
+ else {\r
+ if (PyUnicodeEncodeError_SetStart(*exceptionObject, startpos))\r
+ goto onError;\r
+ if (PyUnicodeEncodeError_SetEnd(*exceptionObject, endpos))\r
+ goto onError;\r
+ if (PyUnicodeEncodeError_SetReason(*exceptionObject, reason))\r
+ goto onError;\r
+ return;\r
+ onError:\r
+ Py_CLEAR(*exceptionObject);\r
+ }\r
+}\r
+\r
+/* raises a UnicodeEncodeError */\r
+static void raise_encode_exception(PyObject **exceptionObject,\r
+ const char *encoding,\r
+ const Py_UNICODE *unicode, Py_ssize_t size,\r
+ Py_ssize_t startpos, Py_ssize_t endpos,\r
+ const char *reason)\r
+{\r
+ make_encode_exception(exceptionObject,\r
+ encoding, unicode, size, startpos, endpos, reason);\r
+ if (*exceptionObject != NULL)\r
+ PyCodec_StrictErrors(*exceptionObject);\r
+}\r
+\r
+/* error handling callback helper:\r
+ build arguments, call the callback and check the arguments,\r
+ put the result into newpos and return the replacement string, which\r
+ has to be freed by the caller */\r
+static PyObject *unicode_encode_call_errorhandler(const char *errors,\r
+ PyObject **errorHandler,\r
+ const char *encoding, const char *reason,\r
+ const Py_UNICODE *unicode, Py_ssize_t size, PyObject **exceptionObject,\r
+ Py_ssize_t startpos, Py_ssize_t endpos,\r
+ Py_ssize_t *newpos)\r
+{\r
+ static char *argparse = "O!n;encoding error handler must return (unicode, int) tuple";\r
+\r
+ PyObject *restuple;\r
+ PyObject *resunicode;\r
+\r
+ if (*errorHandler == NULL) {\r
+ *errorHandler = PyCodec_LookupError(errors);\r
+ if (*errorHandler == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ make_encode_exception(exceptionObject,\r
+ encoding, unicode, size, startpos, endpos, reason);\r
+ if (*exceptionObject == NULL)\r
+ return NULL;\r
+\r
+ restuple = PyObject_CallFunctionObjArgs(\r
+ *errorHandler, *exceptionObject, NULL);\r
+ if (restuple == NULL)\r
+ return NULL;\r
+ if (!PyTuple_Check(restuple)) {\r
+ PyErr_SetString(PyExc_TypeError, &argparse[4]);\r
+ Py_DECREF(restuple);\r
+ return NULL;\r
+ }\r
+ if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type,\r
+ &resunicode, newpos)) {\r
+ Py_DECREF(restuple);\r
+ return NULL;\r
+ }\r
+ if (*newpos<0)\r
+ *newpos = size+*newpos;\r
+ if (*newpos<0 || *newpos>size) {\r
+ PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", *newpos);\r
+ Py_DECREF(restuple);\r
+ return NULL;\r
+ }\r
+ Py_INCREF(resunicode);\r
+ Py_DECREF(restuple);\r
+ return resunicode;\r
+}\r
+\r
+static PyObject *unicode_encode_ucs1(const Py_UNICODE *p,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ int limit)\r
+{\r
+ /* output object */\r
+ PyObject *res;\r
+ /* pointers to the beginning and end+1 of input */\r
+ const Py_UNICODE *startp = p;\r
+ const Py_UNICODE *endp = p + size;\r
+ /* pointer to the beginning of the unencodable characters */\r
+ /* const Py_UNICODE *badp = NULL; */\r
+ /* pointer into the output */\r
+ char *str;\r
+ /* current output position */\r
+ Py_ssize_t respos = 0;\r
+ Py_ssize_t ressize;\r
+ const char *encoding = (limit == 256) ? "latin-1" : "ascii";\r
+ const char *reason = (limit == 256) ? "ordinal not in range(256)" : "ordinal not in range(128)";\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+ /* the following variable is used for caching string comparisons\r
+ * -1=not initialized, 0=unknown, 1=strict, 2=replace, 3=ignore, 4=xmlcharrefreplace */\r
+ int known_errorHandler = -1;\r
+\r
+ /* allocate enough for a simple encoding without\r
+ replacements, if we need more, we'll resize */\r
+ res = PyString_FromStringAndSize(NULL, size);\r
+ if (res == NULL)\r
+ goto onError;\r
+ if (size == 0)\r
+ return res;\r
+ str = PyString_AS_STRING(res);\r
+ ressize = size;\r
+\r
+ while (p<endp) {\r
+ Py_UNICODE c = *p;\r
+\r
+ /* can we encode this? */\r
+ if (c<limit) {\r
+ /* no overflow check, because we know that the space is enough */\r
+ *str++ = (char)c;\r
+ ++p;\r
+ }\r
+ else {\r
+ Py_ssize_t unicodepos = p-startp;\r
+ Py_ssize_t requiredsize;\r
+ PyObject *repunicode;\r
+ Py_ssize_t repsize;\r
+ Py_ssize_t newpos;\r
+ Py_ssize_t respos;\r
+ Py_UNICODE *uni2;\r
+ /* startpos for collecting unencodable chars */\r
+ const Py_UNICODE *collstart = p;\r
+ const Py_UNICODE *collend = p;\r
+ /* find all unecodable characters */\r
+ while ((collend < endp) && ((*collend) >= limit))\r
+ ++collend;\r
+ /* cache callback name lookup (if not done yet, i.e. it's the first error) */\r
+ if (known_errorHandler==-1) {\r
+ if ((errors==NULL) || (!strcmp(errors, "strict")))\r
+ known_errorHandler = 1;\r
+ else if (!strcmp(errors, "replace"))\r
+ known_errorHandler = 2;\r
+ else if (!strcmp(errors, "ignore"))\r
+ known_errorHandler = 3;\r
+ else if (!strcmp(errors, "xmlcharrefreplace"))\r
+ known_errorHandler = 4;\r
+ else\r
+ known_errorHandler = 0;\r
+ }\r
+ switch (known_errorHandler) {\r
+ case 1: /* strict */\r
+ raise_encode_exception(&exc, encoding, startp, size, collstart-startp, collend-startp, reason);\r
+ goto onError;\r
+ case 2: /* replace */\r
+ while (collstart++ < collend)\r
+ *str++ = '?'; /* fall through */\r
+ case 3: /* ignore */\r
+ p = collend;\r
+ break;\r
+ case 4: /* xmlcharrefreplace */\r
+ respos = str - PyString_AS_STRING(res);\r
+ /* determine replacement size (temporarily (mis)uses p) */\r
+ requiredsize = respos;\r
+ for (p = collstart; p < collend;) {\r
+ Py_UCS4 ch = _Py_UNICODE_NEXT(p, collend);\r
+ Py_ssize_t incr;\r
+ if (ch < 10)\r
+ incr = 2+1+1;\r
+ else if (ch < 100)\r
+ incr = 2+2+1;\r
+ else if (ch < 1000)\r
+ incr = 2+3+1;\r
+ else if (ch < 10000)\r
+ incr = 2+4+1;\r
+ else if (ch < 100000)\r
+ incr = 2+5+1;\r
+ else if (ch < 1000000)\r
+ incr = 2+6+1;\r
+ else\r
+ incr = 2+7+1;\r
+ if (requiredsize > PY_SSIZE_T_MAX - incr)\r
+ goto overflow;\r
+ requiredsize += incr;\r
+ }\r
+ if (requiredsize > PY_SSIZE_T_MAX - (endp - collend))\r
+ goto overflow;\r
+ requiredsize += endp - collend;\r
+ if (requiredsize > ressize) {\r
+ if (ressize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*ressize)\r
+ requiredsize = 2*ressize;\r
+ if (_PyString_Resize(&res, requiredsize))\r
+ goto onError;\r
+ str = PyString_AS_STRING(res) + respos;\r
+ ressize = requiredsize;\r
+ }\r
+ /* generate replacement (temporarily (mis)uses p) */\r
+ for (p = collstart; p < collend;) {\r
+ Py_UCS4 ch = _Py_UNICODE_NEXT(p, collend);\r
+ str += sprintf(str, "&#%d;", (int)ch);\r
+ }\r
+ p = collend;\r
+ break;\r
+ default:\r
+ repunicode = unicode_encode_call_errorhandler(errors, &errorHandler,\r
+ encoding, reason, startp, size, &exc,\r
+ collstart-startp, collend-startp, &newpos);\r
+ if (repunicode == NULL)\r
+ goto onError;\r
+ /* need more space? (at least enough for what we have+the\r
+ replacement+the rest of the string, so we won't have to\r
+ check space for encodable characters) */\r
+ respos = str - PyString_AS_STRING(res);\r
+ repsize = PyUnicode_GET_SIZE(repunicode);\r
+ if (respos > PY_SSIZE_T_MAX - repsize)\r
+ goto overflow;\r
+ requiredsize = respos + repsize;\r
+ if (requiredsize > PY_SSIZE_T_MAX - (endp - collend))\r
+ goto overflow;\r
+ requiredsize += endp - collend;\r
+ if (requiredsize > ressize) {\r
+ if (ressize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*ressize)\r
+ requiredsize = 2*ressize;\r
+ if (_PyString_Resize(&res, requiredsize)) {\r
+ Py_DECREF(repunicode);\r
+ goto onError;\r
+ }\r
+ str = PyString_AS_STRING(res) + respos;\r
+ ressize = requiredsize;\r
+ }\r
+ /* check if there is anything unencodable in the replacement\r
+ and copy it to the output */\r
+ for (uni2 = PyUnicode_AS_UNICODE(repunicode); repsize-->0; ++uni2, ++str) {\r
+ c = *uni2;\r
+ if (c >= limit) {\r
+ raise_encode_exception(&exc, encoding, startp, size,\r
+ unicodepos, unicodepos+1, reason);\r
+ Py_DECREF(repunicode);\r
+ goto onError;\r
+ }\r
+ *str = (char)c;\r
+ }\r
+ p = startp + newpos;\r
+ Py_DECREF(repunicode);\r
+ }\r
+ }\r
+ }\r
+ /* Resize if we allocated to much */\r
+ respos = str - PyString_AS_STRING(res);\r
+ if (respos < ressize)\r
+ /* If this falls res will be NULL */\r
+ _PyString_Resize(&res, respos);\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return res;\r
+\r
+ overflow:\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "encoded result is too long for a Python string");\r
+\r
+ onError:\r
+ Py_XDECREF(res);\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyUnicode_EncodeLatin1(const Py_UNICODE *p,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ return unicode_encode_ucs1(p, size, errors, 256);\r
+}\r
+\r
+PyObject *PyUnicode_AsLatin1String(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ return PyUnicode_EncodeLatin1(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode),\r
+ NULL);\r
+}\r
+\r
+/* --- 7-bit ASCII Codec -------------------------------------------------- */\r
+\r
+PyObject *PyUnicode_DecodeASCII(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ const char *starts = s;\r
+ PyUnicodeObject *v;\r
+ Py_UNICODE *p;\r
+ Py_ssize_t startinpos;\r
+ Py_ssize_t endinpos;\r
+ Py_ssize_t outpos;\r
+ const char *e;\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+\r
+ /* ASCII is equivalent to the first 128 ordinals in Unicode. */\r
+ if (size == 1 && *(unsigned char*)s < 128) {\r
+ Py_UNICODE r = *(unsigned char*)s;\r
+ return PyUnicode_FromUnicode(&r, 1);\r
+ }\r
+\r
+ v = _PyUnicode_New(size);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (size == 0)\r
+ return (PyObject *)v;\r
+ p = PyUnicode_AS_UNICODE(v);\r
+ e = s + size;\r
+ while (s < e) {\r
+ register unsigned char c = (unsigned char)*s;\r
+ if (c < 128) {\r
+ *p++ = c;\r
+ ++s;\r
+ }\r
+ else {\r
+ startinpos = s-starts;\r
+ endinpos = startinpos + 1;\r
+ outpos = p - (Py_UNICODE *)PyUnicode_AS_UNICODE(v);\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "ascii", "ordinal not in range(128)",\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &v, &outpos, &p))\r
+ goto onError;\r
+ }\r
+ }\r
+ if (p - PyUnicode_AS_UNICODE(v) < PyString_GET_SIZE(v))\r
+ if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)\r
+ goto onError;\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return (PyObject *)v;\r
+\r
+ onError:\r
+ Py_XDECREF(v);\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyUnicode_EncodeASCII(const Py_UNICODE *p,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ return unicode_encode_ucs1(p, size, errors, 128);\r
+}\r
+\r
+PyObject *PyUnicode_AsASCIIString(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ return PyUnicode_EncodeASCII(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode),\r
+ NULL);\r
+}\r
+\r
+#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)\r
+\r
+/* --- MBCS codecs for Windows -------------------------------------------- */\r
+\r
+#if SIZEOF_INT < SIZEOF_SIZE_T\r
+#define NEED_RETRY\r
+#endif\r
+\r
+/* XXX This code is limited to "true" double-byte encodings, as\r
+ a) it assumes an incomplete character consists of a single byte, and\r
+ b) IsDBCSLeadByte (probably) does not work for non-DBCS multi-byte\r
+ encodings, see IsDBCSLeadByteEx documentation. */\r
+\r
+static int is_dbcs_lead_byte(const char *s, int offset)\r
+{\r
+ const char *curr = s + offset;\r
+\r
+ if (IsDBCSLeadByte(*curr)) {\r
+ const char *prev = CharPrev(s, curr);\r
+ return (prev == curr) || !IsDBCSLeadByte(*prev) || (curr - prev == 2);\r
+ }\r
+ return 0;\r
+}\r
+\r
+/*\r
+ * Decode MBCS string into unicode object. If 'final' is set, converts\r
+ * trailing lead-byte too. Returns consumed size if succeed, -1 otherwise.\r
+ */\r
+static int decode_mbcs(PyUnicodeObject **v,\r
+ const char *s, /* MBCS string */\r
+ int size, /* sizeof MBCS string */\r
+ int final)\r
+{\r
+ Py_UNICODE *p;\r
+ Py_ssize_t n = 0;\r
+ int usize = 0;\r
+\r
+ assert(size >= 0);\r
+\r
+ /* Skip trailing lead-byte unless 'final' is set */\r
+ if (!final && size >= 1 && is_dbcs_lead_byte(s, size - 1))\r
+ --size;\r
+\r
+ /* First get the size of the result */\r
+ if (size > 0) {\r
+ usize = MultiByteToWideChar(CP_ACP, 0, s, size, NULL, 0);\r
+ if (usize == 0) {\r
+ PyErr_SetFromWindowsErrWithFilename(0, NULL);\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ if (*v == NULL) {\r
+ /* Create unicode object */\r
+ *v = _PyUnicode_New(usize);\r
+ if (*v == NULL)\r
+ return -1;\r
+ }\r
+ else {\r
+ /* Extend unicode object */\r
+ n = PyUnicode_GET_SIZE(*v);\r
+ if (_PyUnicode_Resize(v, n + usize) < 0)\r
+ return -1;\r
+ }\r
+\r
+ /* Do the conversion */\r
+ if (size > 0) {\r
+ p = PyUnicode_AS_UNICODE(*v) + n;\r
+ if (0 == MultiByteToWideChar(CP_ACP, 0, s, size, p, usize)) {\r
+ PyErr_SetFromWindowsErrWithFilename(0, NULL);\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ return size;\r
+}\r
+\r
+PyObject *PyUnicode_DecodeMBCSStateful(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors,\r
+ Py_ssize_t *consumed)\r
+{\r
+ PyUnicodeObject *v = NULL;\r
+ int done;\r
+\r
+ if (consumed)\r
+ *consumed = 0;\r
+\r
+#ifdef NEED_RETRY\r
+ retry:\r
+ if (size > INT_MAX)\r
+ done = decode_mbcs(&v, s, INT_MAX, 0);\r
+ else\r
+#endif\r
+ done = decode_mbcs(&v, s, (int)size, !consumed);\r
+\r
+ if (done < 0) {\r
+ Py_XDECREF(v);\r
+ return NULL;\r
+ }\r
+\r
+ if (consumed)\r
+ *consumed += done;\r
+\r
+#ifdef NEED_RETRY\r
+ if (size > INT_MAX) {\r
+ s += done;\r
+ size -= done;\r
+ goto retry;\r
+ }\r
+#endif\r
+\r
+ return (PyObject *)v;\r
+}\r
+\r
+PyObject *PyUnicode_DecodeMBCS(const char *s,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ return PyUnicode_DecodeMBCSStateful(s, size, errors, NULL);\r
+}\r
+\r
+/*\r
+ * Convert unicode into string object (MBCS).\r
+ * Returns 0 if succeed, -1 otherwise.\r
+ */\r
+static int encode_mbcs(PyObject **repr,\r
+ const Py_UNICODE *p, /* unicode */\r
+ int size) /* size of unicode */\r
+{\r
+ int mbcssize = 0;\r
+ Py_ssize_t n = 0;\r
+\r
+ assert(size >= 0);\r
+\r
+ /* First get the size of the result */\r
+ if (size > 0) {\r
+ mbcssize = WideCharToMultiByte(CP_ACP, 0, p, size, NULL, 0, NULL, NULL);\r
+ if (mbcssize == 0) {\r
+ PyErr_SetFromWindowsErrWithFilename(0, NULL);\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ if (*repr == NULL) {\r
+ /* Create string object */\r
+ *repr = PyString_FromStringAndSize(NULL, mbcssize);\r
+ if (*repr == NULL)\r
+ return -1;\r
+ }\r
+ else {\r
+ /* Extend string object */\r
+ n = PyString_Size(*repr);\r
+ if (_PyString_Resize(repr, n + mbcssize) < 0)\r
+ return -1;\r
+ }\r
+\r
+ /* Do the conversion */\r
+ if (size > 0) {\r
+ char *s = PyString_AS_STRING(*repr) + n;\r
+ if (0 == WideCharToMultiByte(CP_ACP, 0, p, size, s, mbcssize, NULL, NULL)) {\r
+ PyErr_SetFromWindowsErrWithFilename(0, NULL);\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+PyObject *PyUnicode_EncodeMBCS(const Py_UNICODE *p,\r
+ Py_ssize_t size,\r
+ const char *errors)\r
+{\r
+ PyObject *repr = NULL;\r
+ int ret;\r
+\r
+#ifdef NEED_RETRY\r
+ retry:\r
+ if (size > INT_MAX)\r
+ ret = encode_mbcs(&repr, p, INT_MAX);\r
+ else\r
+#endif\r
+ ret = encode_mbcs(&repr, p, (int)size);\r
+\r
+ if (ret < 0) {\r
+ Py_XDECREF(repr);\r
+ return NULL;\r
+ }\r
+\r
+#ifdef NEED_RETRY\r
+ if (size > INT_MAX) {\r
+ p += INT_MAX;\r
+ size -= INT_MAX;\r
+ goto retry;\r
+ }\r
+#endif\r
+\r
+ return repr;\r
+}\r
+\r
+PyObject *PyUnicode_AsMBCSString(PyObject *unicode)\r
+{\r
+ if (!PyUnicode_Check(unicode)) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ return PyUnicode_EncodeMBCS(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode),\r
+ NULL);\r
+}\r
+\r
+#undef NEED_RETRY\r
+\r
+#endif /* MS_WINDOWS */\r
+\r
+/* --- Character Mapping Codec -------------------------------------------- */\r
+\r
+PyObject *PyUnicode_DecodeCharmap(const char *s,\r
+ Py_ssize_t size,\r
+ PyObject *mapping,\r
+ const char *errors)\r
+{\r
+ const char *starts = s;\r
+ Py_ssize_t startinpos;\r
+ Py_ssize_t endinpos;\r
+ Py_ssize_t outpos;\r
+ const char *e;\r
+ PyUnicodeObject *v;\r
+ Py_UNICODE *p;\r
+ Py_ssize_t extrachars = 0;\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+ Py_UNICODE *mapstring = NULL;\r
+ Py_ssize_t maplen = 0;\r
+\r
+ /* Default to Latin-1 */\r
+ if (mapping == NULL)\r
+ return PyUnicode_DecodeLatin1(s, size, errors);\r
+\r
+ v = _PyUnicode_New(size);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (size == 0)\r
+ return (PyObject *)v;\r
+ p = PyUnicode_AS_UNICODE(v);\r
+ e = s + size;\r
+ if (PyUnicode_CheckExact(mapping)) {\r
+ mapstring = PyUnicode_AS_UNICODE(mapping);\r
+ maplen = PyUnicode_GET_SIZE(mapping);\r
+ while (s < e) {\r
+ unsigned char ch = *s;\r
+ Py_UNICODE x = 0xfffe; /* illegal value */\r
+\r
+ if (ch < maplen)\r
+ x = mapstring[ch];\r
+\r
+ if (x == 0xfffe) {\r
+ /* undefined mapping */\r
+ outpos = p-PyUnicode_AS_UNICODE(v);\r
+ startinpos = s-starts;\r
+ endinpos = startinpos+1;\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "charmap", "character maps to <undefined>",\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &v, &outpos, &p)) {\r
+ goto onError;\r
+ }\r
+ continue;\r
+ }\r
+ *p++ = x;\r
+ ++s;\r
+ }\r
+ }\r
+ else {\r
+ while (s < e) {\r
+ unsigned char ch = *s;\r
+ PyObject *w, *x;\r
+\r
+ /* Get mapping (char ordinal -> integer, Unicode char or None) */\r
+ w = PyInt_FromLong((long)ch);\r
+ if (w == NULL)\r
+ goto onError;\r
+ x = PyObject_GetItem(mapping, w);\r
+ Py_DECREF(w);\r
+ if (x == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_LookupError)) {\r
+ /* No mapping found means: mapping is undefined. */\r
+ PyErr_Clear();\r
+ goto Undefined;\r
+ } else\r
+ goto onError;\r
+ }\r
+\r
+ /* Apply mapping */\r
+ if (x == Py_None)\r
+ goto Undefined;\r
+ if (PyInt_Check(x)) {\r
+ long value = PyInt_AS_LONG(x);\r
+ if (value == 0xFFFE)\r
+ goto Undefined;\r
+ if (value < 0 || value > 0x10FFFF) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "character mapping must be in range(0x110000)");\r
+ Py_DECREF(x);\r
+ goto onError;\r
+ }\r
+\r
+#ifndef Py_UNICODE_WIDE\r
+ if (value > 0xFFFF) {\r
+ /* see the code for 1-n mapping below */\r
+ if (extrachars < 2) {\r
+ /* resize first */\r
+ Py_ssize_t oldpos = p - PyUnicode_AS_UNICODE(v);\r
+ Py_ssize_t needed = 10 - extrachars;\r
+ extrachars += needed;\r
+ /* XXX overflow detection missing */\r
+ if (_PyUnicode_Resize(&v,\r
+ PyUnicode_GET_SIZE(v) + needed) < 0) {\r
+ Py_DECREF(x);\r
+ goto onError;\r
+ }\r
+ p = PyUnicode_AS_UNICODE(v) + oldpos;\r
+ }\r
+ value -= 0x10000;\r
+ *p++ = 0xD800 | (value >> 10);\r
+ *p++ = 0xDC00 | (value & 0x3FF);\r
+ extrachars -= 2;\r
+ }\r
+ else\r
+#endif\r
+ *p++ = (Py_UNICODE)value;\r
+ }\r
+ else if (PyUnicode_Check(x)) {\r
+ Py_ssize_t targetsize = PyUnicode_GET_SIZE(x);\r
+\r
+ if (targetsize == 1) {\r
+ /* 1-1 mapping */\r
+ Py_UNICODE value = *PyUnicode_AS_UNICODE(x);\r
+ if (value == 0xFFFE)\r
+ goto Undefined;\r
+ *p++ = value;\r
+ }\r
+ else if (targetsize > 1) {\r
+ /* 1-n mapping */\r
+ if (targetsize > extrachars) {\r
+ /* resize first */\r
+ Py_ssize_t oldpos = p - PyUnicode_AS_UNICODE(v);\r
+ Py_ssize_t needed = (targetsize - extrachars) + \\r
+ (targetsize << 2);\r
+ extrachars += needed;\r
+ /* XXX overflow detection missing */\r
+ if (_PyUnicode_Resize(&v,\r
+ PyUnicode_GET_SIZE(v) + needed) < 0) {\r
+ Py_DECREF(x);\r
+ goto onError;\r
+ }\r
+ p = PyUnicode_AS_UNICODE(v) + oldpos;\r
+ }\r
+ Py_UNICODE_COPY(p,\r
+ PyUnicode_AS_UNICODE(x),\r
+ targetsize);\r
+ p += targetsize;\r
+ extrachars -= targetsize;\r
+ }\r
+ /* 1-0 mapping: skip the character */\r
+ }\r
+ else {\r
+ /* wrong return value */\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "character mapping must return integer, None or unicode");\r
+ Py_DECREF(x);\r
+ goto onError;\r
+ }\r
+ Py_DECREF(x);\r
+ ++s;\r
+ continue;\r
+Undefined:\r
+ /* undefined mapping */\r
+ Py_XDECREF(x);\r
+ outpos = p-PyUnicode_AS_UNICODE(v);\r
+ startinpos = s-starts;\r
+ endinpos = startinpos+1;\r
+ if (unicode_decode_call_errorhandler(\r
+ errors, &errorHandler,\r
+ "charmap", "character maps to <undefined>",\r
+ starts, size, &startinpos, &endinpos, &exc, &s,\r
+ &v, &outpos, &p)) {\r
+ goto onError;\r
+ }\r
+ }\r
+ }\r
+ if (p - PyUnicode_AS_UNICODE(v) < PyUnicode_GET_SIZE(v))\r
+ if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)\r
+ goto onError;\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ return (PyObject *)v;\r
+\r
+ onError:\r
+ Py_XDECREF(errorHandler);\r
+ Py_XDECREF(exc);\r
+ Py_XDECREF(v);\r
+ return NULL;\r
+}\r
+\r
+/* Charmap encoding: the lookup table */\r
+\r
+struct encoding_map{\r
+ PyObject_HEAD\r
+ unsigned char level1[32];\r
+ int count2, count3;\r
+ unsigned char level23[1];\r
+};\r
+\r
+static PyObject*\r
+encoding_map_size(PyObject *obj, PyObject* args)\r
+{\r
+ struct encoding_map *map = (struct encoding_map*)obj;\r
+ return PyInt_FromLong(sizeof(*map) - 1 + 16*map->count2 +\r
+ 128*map->count3);\r
+}\r
+\r
+static PyMethodDef encoding_map_methods[] = {\r
+ {"size", encoding_map_size, METH_NOARGS,\r
+ PyDoc_STR("Return the size (in bytes) of this object") },\r
+ { 0 }\r
+};\r
+\r
+static void\r
+encoding_map_dealloc(PyObject* o)\r
+{\r
+ PyObject_FREE(o);\r
+}\r
+\r
+static PyTypeObject EncodingMapType = {\r
+ PyVarObject_HEAD_INIT(NULL, 0)\r
+ "EncodingMap", /*tp_name*/\r
+ sizeof(struct encoding_map), /*tp_basicsize*/\r
+ 0, /*tp_itemsize*/\r
+ /* methods */\r
+ encoding_map_dealloc, /*tp_dealloc*/\r
+ 0, /*tp_print*/\r
+ 0, /*tp_getattr*/\r
+ 0, /*tp_setattr*/\r
+ 0, /*tp_compare*/\r
+ 0, /*tp_repr*/\r
+ 0, /*tp_as_number*/\r
+ 0, /*tp_as_sequence*/\r
+ 0, /*tp_as_mapping*/\r
+ 0, /*tp_hash*/\r
+ 0, /*tp_call*/\r
+ 0, /*tp_str*/\r
+ 0, /*tp_getattro*/\r
+ 0, /*tp_setattro*/\r
+ 0, /*tp_as_buffer*/\r
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/\r
+ 0, /*tp_doc*/\r
+ 0, /*tp_traverse*/\r
+ 0, /*tp_clear*/\r
+ 0, /*tp_richcompare*/\r
+ 0, /*tp_weaklistoffset*/\r
+ 0, /*tp_iter*/\r
+ 0, /*tp_iternext*/\r
+ encoding_map_methods, /*tp_methods*/\r
+ 0, /*tp_members*/\r
+ 0, /*tp_getset*/\r
+ 0, /*tp_base*/\r
+ 0, /*tp_dict*/\r
+ 0, /*tp_descr_get*/\r
+ 0, /*tp_descr_set*/\r
+ 0, /*tp_dictoffset*/\r
+ 0, /*tp_init*/\r
+ 0, /*tp_alloc*/\r
+ 0, /*tp_new*/\r
+ 0, /*tp_free*/\r
+ 0, /*tp_is_gc*/\r
+};\r
+\r
+PyObject*\r
+PyUnicode_BuildEncodingMap(PyObject* string)\r
+{\r
+ Py_UNICODE *decode;\r
+ PyObject *result;\r
+ struct encoding_map *mresult;\r
+ int i;\r
+ int need_dict = 0;\r
+ unsigned char level1[32];\r
+ unsigned char level2[512];\r
+ unsigned char *mlevel1, *mlevel2, *mlevel3;\r
+ int count2 = 0, count3 = 0;\r
+\r
+ if (!PyUnicode_Check(string) || PyUnicode_GetSize(string) != 256) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ decode = PyUnicode_AS_UNICODE(string);\r
+ memset(level1, 0xFF, sizeof level1);\r
+ memset(level2, 0xFF, sizeof level2);\r
+\r
+ /* If there isn't a one-to-one mapping of NULL to \0,\r
+ or if there are non-BMP characters, we need to use\r
+ a mapping dictionary. */\r
+ if (decode[0] != 0)\r
+ need_dict = 1;\r
+ for (i = 1; i < 256; i++) {\r
+ int l1, l2;\r
+ if (decode[i] == 0\r
+#ifdef Py_UNICODE_WIDE\r
+ || decode[i] > 0xFFFF\r
+#endif\r
+ ) {\r
+ need_dict = 1;\r
+ break;\r
+ }\r
+ if (decode[i] == 0xFFFE)\r
+ /* unmapped character */\r
+ continue;\r
+ l1 = decode[i] >> 11;\r
+ l2 = decode[i] >> 7;\r
+ if (level1[l1] == 0xFF)\r
+ level1[l1] = count2++;\r
+ if (level2[l2] == 0xFF)\r
+ level2[l2] = count3++;\r
+ }\r
+\r
+ if (count2 >= 0xFF || count3 >= 0xFF)\r
+ need_dict = 1;\r
+\r
+ if (need_dict) {\r
+ PyObject *result = PyDict_New();\r
+ PyObject *key, *value;\r
+ if (!result)\r
+ return NULL;\r
+ for (i = 0; i < 256; i++) {\r
+ value = NULL;\r
+ key = PyInt_FromLong(decode[i]);\r
+ value = PyInt_FromLong(i);\r
+ if (!key || !value)\r
+ goto failed1;\r
+ if (PyDict_SetItem(result, key, value) == -1)\r
+ goto failed1;\r
+ Py_DECREF(key);\r
+ Py_DECREF(value);\r
+ }\r
+ return result;\r
+ failed1:\r
+ Py_XDECREF(key);\r
+ Py_XDECREF(value);\r
+ Py_DECREF(result);\r
+ return NULL;\r
+ }\r
+\r
+ /* Create a three-level trie */\r
+ result = PyObject_MALLOC(sizeof(struct encoding_map) +\r
+ 16*count2 + 128*count3 - 1);\r
+ if (!result)\r
+ return PyErr_NoMemory();\r
+ PyObject_Init(result, &EncodingMapType);\r
+ mresult = (struct encoding_map*)result;\r
+ mresult->count2 = count2;\r
+ mresult->count3 = count3;\r
+ mlevel1 = mresult->level1;\r
+ mlevel2 = mresult->level23;\r
+ mlevel3 = mresult->level23 + 16*count2;\r
+ memcpy(mlevel1, level1, 32);\r
+ memset(mlevel2, 0xFF, 16*count2);\r
+ memset(mlevel3, 0, 128*count3);\r
+ count3 = 0;\r
+ for (i = 1; i < 256; i++) {\r
+ int o1, o2, o3, i2, i3;\r
+ if (decode[i] == 0xFFFE)\r
+ /* unmapped character */\r
+ continue;\r
+ o1 = decode[i]>>11;\r
+ o2 = (decode[i]>>7) & 0xF;\r
+ i2 = 16*mlevel1[o1] + o2;\r
+ if (mlevel2[i2] == 0xFF)\r
+ mlevel2[i2] = count3++;\r
+ o3 = decode[i] & 0x7F;\r
+ i3 = 128*mlevel2[i2] + o3;\r
+ mlevel3[i3] = i;\r
+ }\r
+ return result;\r
+}\r
+\r
+static int\r
+encoding_map_lookup(Py_UNICODE c, PyObject *mapping)\r
+{\r
+ struct encoding_map *map = (struct encoding_map*)mapping;\r
+ int l1 = c>>11;\r
+ int l2 = (c>>7) & 0xF;\r
+ int l3 = c & 0x7F;\r
+ int i;\r
+\r
+#ifdef Py_UNICODE_WIDE\r
+ if (c > 0xFFFF) {\r
+ return -1;\r
+ }\r
+#endif\r
+ if (c == 0)\r
+ return 0;\r
+ /* level 1*/\r
+ i = map->level1[l1];\r
+ if (i == 0xFF) {\r
+ return -1;\r
+ }\r
+ /* level 2*/\r
+ i = map->level23[16*i+l2];\r
+ if (i == 0xFF) {\r
+ return -1;\r
+ }\r
+ /* level 3 */\r
+ i = map->level23[16*map->count2 + 128*i + l3];\r
+ if (i == 0) {\r
+ return -1;\r
+ }\r
+ return i;\r
+}\r
+\r
+/* Lookup the character ch in the mapping. If the character\r
+ can't be found, Py_None is returned (or NULL, if another\r
+ error occurred). */\r
+static PyObject *charmapencode_lookup(Py_UNICODE c, PyObject *mapping)\r
+{\r
+ PyObject *w = PyInt_FromLong((long)c);\r
+ PyObject *x;\r
+\r
+ if (w == NULL)\r
+ return NULL;\r
+ x = PyObject_GetItem(mapping, w);\r
+ Py_DECREF(w);\r
+ if (x == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_LookupError)) {\r
+ /* No mapping found means: mapping is undefined. */\r
+ PyErr_Clear();\r
+ x = Py_None;\r
+ Py_INCREF(x);\r
+ return x;\r
+ } else\r
+ return NULL;\r
+ }\r
+ else if (x == Py_None)\r
+ return x;\r
+ else if (PyInt_Check(x)) {\r
+ long value = PyInt_AS_LONG(x);\r
+ if (value < 0 || value > 255) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "character mapping must be in range(256)");\r
+ Py_DECREF(x);\r
+ return NULL;\r
+ }\r
+ return x;\r
+ }\r
+ else if (PyString_Check(x))\r
+ return x;\r
+ else {\r
+ /* wrong return value */\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "character mapping must return integer, None or str");\r
+ Py_DECREF(x);\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static int\r
+charmapencode_resize(PyObject **outobj, Py_ssize_t *outpos, Py_ssize_t requiredsize)\r
+{\r
+ Py_ssize_t outsize = PyString_GET_SIZE(*outobj);\r
+ /* exponentially overallocate to minimize reallocations */\r
+ if (requiredsize < 2*outsize)\r
+ requiredsize = 2*outsize;\r
+ if (_PyString_Resize(outobj, requiredsize)) {\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+typedef enum charmapencode_result {\r
+ enc_SUCCESS, enc_FAILED, enc_EXCEPTION\r
+}charmapencode_result;\r
+/* lookup the character, put the result in the output string and adjust\r
+ various state variables. Reallocate the output string if not enough\r
+ space is available. Return a new reference to the object that\r
+ was put in the output buffer, or Py_None, if the mapping was undefined\r
+ (in which case no character was written) or NULL, if a\r
+ reallocation error occurred. The caller must decref the result */\r
+static\r
+charmapencode_result charmapencode_output(Py_UNICODE c, PyObject *mapping,\r
+ PyObject **outobj, Py_ssize_t *outpos)\r
+{\r
+ PyObject *rep;\r
+ char *outstart;\r
+ Py_ssize_t outsize = PyString_GET_SIZE(*outobj);\r
+\r
+ if (Py_TYPE(mapping) == &EncodingMapType) {\r
+ int res = encoding_map_lookup(c, mapping);\r
+ Py_ssize_t requiredsize = *outpos+1;\r
+ if (res == -1)\r
+ return enc_FAILED;\r
+ if (outsize<requiredsize)\r
+ if (!charmapencode_resize(outobj, outpos, requiredsize))\r
+ return enc_EXCEPTION;\r
+ outstart = PyString_AS_STRING(*outobj);\r
+ outstart[(*outpos)++] = (char)res;\r
+ return enc_SUCCESS;\r
+ }\r
+\r
+ rep = charmapencode_lookup(c, mapping);\r
+ if (rep==NULL)\r
+ return enc_EXCEPTION;\r
+ else if (rep==Py_None) {\r
+ Py_DECREF(rep);\r
+ return enc_FAILED;\r
+ } else {\r
+ if (PyInt_Check(rep)) {\r
+ Py_ssize_t requiredsize = *outpos+1;\r
+ if (outsize<requiredsize)\r
+ if (!charmapencode_resize(outobj, outpos, requiredsize)) {\r
+ Py_DECREF(rep);\r
+ return enc_EXCEPTION;\r
+ }\r
+ outstart = PyString_AS_STRING(*outobj);\r
+ outstart[(*outpos)++] = (char)PyInt_AS_LONG(rep);\r
+ }\r
+ else {\r
+ const char *repchars = PyString_AS_STRING(rep);\r
+ Py_ssize_t repsize = PyString_GET_SIZE(rep);\r
+ Py_ssize_t requiredsize = *outpos+repsize;\r
+ if (outsize<requiredsize)\r
+ if (!charmapencode_resize(outobj, outpos, requiredsize)) {\r
+ Py_DECREF(rep);\r
+ return enc_EXCEPTION;\r
+ }\r
+ outstart = PyString_AS_STRING(*outobj);\r
+ memcpy(outstart + *outpos, repchars, repsize);\r
+ *outpos += repsize;\r
+ }\r
+ }\r
+ Py_DECREF(rep);\r
+ return enc_SUCCESS;\r
+}\r
+\r
+/* handle an error in PyUnicode_EncodeCharmap\r
+ Return 0 on success, -1 on error */\r
+static\r
+int charmap_encoding_error(\r
+ const Py_UNICODE *p, Py_ssize_t size, Py_ssize_t *inpos, PyObject *mapping,\r
+ PyObject **exceptionObject,\r
+ int *known_errorHandler, PyObject **errorHandler, const char *errors,\r
+ PyObject **res, Py_ssize_t *respos)\r
+{\r
+ PyObject *repunicode = NULL; /* initialize to prevent gcc warning */\r
+ Py_ssize_t repsize;\r
+ Py_ssize_t newpos;\r
+ Py_UNICODE *uni2;\r
+ /* startpos for collecting unencodable chars */\r
+ Py_ssize_t collstartpos = *inpos;\r
+ Py_ssize_t collendpos = *inpos+1;\r
+ Py_ssize_t collpos;\r
+ char *encoding = "charmap";\r
+ char *reason = "character maps to <undefined>";\r
+ charmapencode_result x;\r
+\r
+ /* find all unencodable characters */\r
+ while (collendpos < size) {\r
+ PyObject *rep;\r
+ if (Py_TYPE(mapping) == &EncodingMapType) {\r
+ int res = encoding_map_lookup(p[collendpos], mapping);\r
+ if (res != -1)\r
+ break;\r
+ ++collendpos;\r
+ continue;\r
+ }\r
+\r
+ rep = charmapencode_lookup(p[collendpos], mapping);\r
+ if (rep==NULL)\r
+ return -1;\r
+ else if (rep!=Py_None) {\r
+ Py_DECREF(rep);\r
+ break;\r
+ }\r
+ Py_DECREF(rep);\r
+ ++collendpos;\r
+ }\r
+ /* cache callback name lookup\r
+ * (if not done yet, i.e. it's the first error) */\r
+ if (*known_errorHandler==-1) {\r
+ if ((errors==NULL) || (!strcmp(errors, "strict")))\r
+ *known_errorHandler = 1;\r
+ else if (!strcmp(errors, "replace"))\r
+ *known_errorHandler = 2;\r
+ else if (!strcmp(errors, "ignore"))\r
+ *known_errorHandler = 3;\r
+ else if (!strcmp(errors, "xmlcharrefreplace"))\r
+ *known_errorHandler = 4;\r
+ else\r
+ *known_errorHandler = 0;\r
+ }\r
+ switch (*known_errorHandler) {\r
+ case 1: /* strict */\r
+ raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);\r
+ return -1;\r
+ case 2: /* replace */\r
+ for (collpos = collstartpos; collpos<collendpos; ++collpos) {\r
+ x = charmapencode_output('?', mapping, res, respos);\r
+ if (x==enc_EXCEPTION) {\r
+ return -1;\r
+ }\r
+ else if (x==enc_FAILED) {\r
+ raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);\r
+ return -1;\r
+ }\r
+ }\r
+ /* fall through */\r
+ case 3: /* ignore */\r
+ *inpos = collendpos;\r
+ break;\r
+ case 4: /* xmlcharrefreplace */\r
+ /* generate replacement */\r
+ for (collpos = collstartpos; collpos < collendpos;) {\r
+ char buffer[2+29+1+1];\r
+ char *cp;\r
+ Py_UCS4 ch = p[collpos++];\r
+#ifndef Py_UNICODE_WIDE\r
+ if ((0xD800 <= ch && ch <= 0xDBFF) &&\r
+ (collpos < collendpos) &&\r
+ (0xDC00 <= p[collpos] && p[collpos] <= 0xDFFF)) {\r
+ ch = ((((ch & 0x03FF) << 10) |\r
+ ((Py_UCS4)p[collpos++] & 0x03FF)) + 0x10000);\r
+ }\r
+#endif\r
+ sprintf(buffer, "&#%d;", (int)ch);\r
+ for (cp = buffer; *cp; ++cp) {\r
+ x = charmapencode_output(*cp, mapping, res, respos);\r
+ if (x==enc_EXCEPTION)\r
+ return -1;\r
+ else if (x==enc_FAILED) {\r
+ raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+ *inpos = collendpos;\r
+ break;\r
+ default:\r
+ repunicode = unicode_encode_call_errorhandler(errors, errorHandler,\r
+ encoding, reason, p, size, exceptionObject,\r
+ collstartpos, collendpos, &newpos);\r
+ if (repunicode == NULL)\r
+ return -1;\r
+ /* generate replacement */\r
+ repsize = PyUnicode_GET_SIZE(repunicode);\r
+ for (uni2 = PyUnicode_AS_UNICODE(repunicode); repsize-->0; ++uni2) {\r
+ x = charmapencode_output(*uni2, mapping, res, respos);\r
+ if (x==enc_EXCEPTION) {\r
+ return -1;\r
+ }\r
+ else if (x==enc_FAILED) {\r
+ Py_DECREF(repunicode);\r
+ raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);\r
+ return -1;\r
+ }\r
+ }\r
+ *inpos = newpos;\r
+ Py_DECREF(repunicode);\r
+ }\r
+ return 0;\r
+}\r
+\r
+PyObject *PyUnicode_EncodeCharmap(const Py_UNICODE *p,\r
+ Py_ssize_t size,\r
+ PyObject *mapping,\r
+ const char *errors)\r
+{\r
+ /* output object */\r
+ PyObject *res = NULL;\r
+ /* current input position */\r
+ Py_ssize_t inpos = 0;\r
+ /* current output position */\r
+ Py_ssize_t respos = 0;\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+ /* the following variable is used for caching string comparisons\r
+ * -1=not initialized, 0=unknown, 1=strict, 2=replace,\r
+ * 3=ignore, 4=xmlcharrefreplace */\r
+ int known_errorHandler = -1;\r
+\r
+ /* Default to Latin-1 */\r
+ if (mapping == NULL)\r
+ return PyUnicode_EncodeLatin1(p, size, errors);\r
+\r
+ /* allocate enough for a simple encoding without\r
+ replacements, if we need more, we'll resize */\r
+ res = PyString_FromStringAndSize(NULL, size);\r
+ if (res == NULL)\r
+ goto onError;\r
+ if (size == 0)\r
+ return res;\r
+\r
+ while (inpos<size) {\r
+ /* try to encode it */\r
+ charmapencode_result x = charmapencode_output(p[inpos], mapping, &res, &respos);\r
+ if (x==enc_EXCEPTION) /* error */\r
+ goto onError;\r
+ if (x==enc_FAILED) { /* unencodable character */\r
+ if (charmap_encoding_error(p, size, &inpos, mapping,\r
+ &exc,\r
+ &known_errorHandler, &errorHandler, errors,\r
+ &res, &respos)) {\r
+ goto onError;\r
+ }\r
+ }\r
+ else\r
+ /* done with this character => adjust input position */\r
+ ++inpos;\r
+ }\r
+\r
+ /* Resize if we allocated to much */\r
+ if (respos<PyString_GET_SIZE(res)) {\r
+ if (_PyString_Resize(&res, respos))\r
+ goto onError;\r
+ }\r
+ Py_XDECREF(exc);\r
+ Py_XDECREF(errorHandler);\r
+ return res;\r
+\r
+ onError:\r
+ Py_XDECREF(res);\r
+ Py_XDECREF(exc);\r
+ Py_XDECREF(errorHandler);\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyUnicode_AsCharmapString(PyObject *unicode,\r
+ PyObject *mapping)\r
+{\r
+ if (!PyUnicode_Check(unicode) || mapping == NULL) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+ return PyUnicode_EncodeCharmap(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode),\r
+ mapping,\r
+ NULL);\r
+}\r
+\r
+/* create or adjust a UnicodeTranslateError */\r
+static void make_translate_exception(PyObject **exceptionObject,\r
+ const Py_UNICODE *unicode, Py_ssize_t size,\r
+ Py_ssize_t startpos, Py_ssize_t endpos,\r
+ const char *reason)\r
+{\r
+ if (*exceptionObject == NULL) {\r
+ *exceptionObject = PyUnicodeTranslateError_Create(\r
+ unicode, size, startpos, endpos, reason);\r
+ }\r
+ else {\r
+ if (PyUnicodeTranslateError_SetStart(*exceptionObject, startpos))\r
+ goto onError;\r
+ if (PyUnicodeTranslateError_SetEnd(*exceptionObject, endpos))\r
+ goto onError;\r
+ if (PyUnicodeTranslateError_SetReason(*exceptionObject, reason))\r
+ goto onError;\r
+ return;\r
+ onError:\r
+ Py_CLEAR(*exceptionObject);\r
+ }\r
+}\r
+\r
+/* raises a UnicodeTranslateError */\r
+static void raise_translate_exception(PyObject **exceptionObject,\r
+ const Py_UNICODE *unicode, Py_ssize_t size,\r
+ Py_ssize_t startpos, Py_ssize_t endpos,\r
+ const char *reason)\r
+{\r
+ make_translate_exception(exceptionObject,\r
+ unicode, size, startpos, endpos, reason);\r
+ if (*exceptionObject != NULL)\r
+ PyCodec_StrictErrors(*exceptionObject);\r
+}\r
+\r
+/* error handling callback helper:\r
+ build arguments, call the callback and check the arguments,\r
+ put the result into newpos and return the replacement string, which\r
+ has to be freed by the caller */\r
+static PyObject *unicode_translate_call_errorhandler(const char *errors,\r
+ PyObject **errorHandler,\r
+ const char *reason,\r
+ const Py_UNICODE *unicode, Py_ssize_t size, PyObject **exceptionObject,\r
+ Py_ssize_t startpos, Py_ssize_t endpos,\r
+ Py_ssize_t *newpos)\r
+{\r
+ static char *argparse = "O!n;translating error handler must return (unicode, int) tuple";\r
+\r
+ Py_ssize_t i_newpos;\r
+ PyObject *restuple;\r
+ PyObject *resunicode;\r
+\r
+ if (*errorHandler == NULL) {\r
+ *errorHandler = PyCodec_LookupError(errors);\r
+ if (*errorHandler == NULL)\r
+ return NULL;\r
+ }\r
+\r
+ make_translate_exception(exceptionObject,\r
+ unicode, size, startpos, endpos, reason);\r
+ if (*exceptionObject == NULL)\r
+ return NULL;\r
+\r
+ restuple = PyObject_CallFunctionObjArgs(\r
+ *errorHandler, *exceptionObject, NULL);\r
+ if (restuple == NULL)\r
+ return NULL;\r
+ if (!PyTuple_Check(restuple)) {\r
+ PyErr_SetString(PyExc_TypeError, &argparse[4]);\r
+ Py_DECREF(restuple);\r
+ return NULL;\r
+ }\r
+ if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type,\r
+ &resunicode, &i_newpos)) {\r
+ Py_DECREF(restuple);\r
+ return NULL;\r
+ }\r
+ if (i_newpos<0)\r
+ *newpos = size+i_newpos;\r
+ else\r
+ *newpos = i_newpos;\r
+ if (*newpos<0 || *newpos>size) {\r
+ PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", *newpos);\r
+ Py_DECREF(restuple);\r
+ return NULL;\r
+ }\r
+ Py_INCREF(resunicode);\r
+ Py_DECREF(restuple);\r
+ return resunicode;\r
+}\r
+\r
+/* Lookup the character ch in the mapping and put the result in result,\r
+ which must be decrefed by the caller.\r
+ Return 0 on success, -1 on error */\r
+static\r
+int charmaptranslate_lookup(Py_UNICODE c, PyObject *mapping, PyObject **result)\r
+{\r
+ PyObject *w = PyInt_FromLong((long)c);\r
+ PyObject *x;\r
+\r
+ if (w == NULL)\r
+ return -1;\r
+ x = PyObject_GetItem(mapping, w);\r
+ Py_DECREF(w);\r
+ if (x == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_LookupError)) {\r
+ /* No mapping found means: use 1:1 mapping. */\r
+ PyErr_Clear();\r
+ *result = NULL;\r
+ return 0;\r
+ } else\r
+ return -1;\r
+ }\r
+ else if (x == Py_None) {\r
+ *result = x;\r
+ return 0;\r
+ }\r
+ else if (PyInt_Check(x)) {\r
+ long value = PyInt_AS_LONG(x);\r
+ long max = PyUnicode_GetMax();\r
+ if (value < 0 || value > max) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "character mapping must be in range(0x%lx)", max+1);\r
+ Py_DECREF(x);\r
+ return -1;\r
+ }\r
+ *result = x;\r
+ return 0;\r
+ }\r
+ else if (PyUnicode_Check(x)) {\r
+ *result = x;\r
+ return 0;\r
+ }\r
+ else {\r
+ /* wrong return value */\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "character mapping must return integer, None or unicode");\r
+ Py_DECREF(x);\r
+ return -1;\r
+ }\r
+}\r
+/* ensure that *outobj is at least requiredsize characters long,\r
+ if not reallocate and adjust various state variables.\r
+ Return 0 on success, -1 on error */\r
+static\r
+int charmaptranslate_makespace(PyObject **outobj, Py_UNICODE **outp,\r
+ Py_ssize_t requiredsize)\r
+{\r
+ Py_ssize_t oldsize = PyUnicode_GET_SIZE(*outobj);\r
+ if (requiredsize > oldsize) {\r
+ /* remember old output position */\r
+ Py_ssize_t outpos = *outp-PyUnicode_AS_UNICODE(*outobj);\r
+ /* exponentially overallocate to minimize reallocations */\r
+ if (requiredsize < 2 * oldsize)\r
+ requiredsize = 2 * oldsize;\r
+ if (PyUnicode_Resize(outobj, requiredsize) < 0)\r
+ return -1;\r
+ *outp = PyUnicode_AS_UNICODE(*outobj) + outpos;\r
+ }\r
+ return 0;\r
+}\r
+/* lookup the character, put the result in the output string and adjust\r
+ various state variables. Return a new reference to the object that\r
+ was put in the output buffer in *result, or Py_None, if the mapping was\r
+ undefined (in which case no character was written).\r
+ The called must decref result.\r
+ Return 0 on success, -1 on error. */\r
+static\r
+int charmaptranslate_output(const Py_UNICODE *startinp, const Py_UNICODE *curinp,\r
+ Py_ssize_t insize, PyObject *mapping, PyObject **outobj, Py_UNICODE **outp,\r
+ PyObject **res)\r
+{\r
+ if (charmaptranslate_lookup(*curinp, mapping, res))\r
+ return -1;\r
+ if (*res==NULL) {\r
+ /* not found => default to 1:1 mapping */\r
+ *(*outp)++ = *curinp;\r
+ }\r
+ else if (*res==Py_None)\r
+ ;\r
+ else if (PyInt_Check(*res)) {\r
+ /* no overflow check, because we know that the space is enough */\r
+ *(*outp)++ = (Py_UNICODE)PyInt_AS_LONG(*res);\r
+ }\r
+ else if (PyUnicode_Check(*res)) {\r
+ Py_ssize_t repsize = PyUnicode_GET_SIZE(*res);\r
+ if (repsize==1) {\r
+ /* no overflow check, because we know that the space is enough */\r
+ *(*outp)++ = *PyUnicode_AS_UNICODE(*res);\r
+ }\r
+ else if (repsize!=0) {\r
+ /* more than one character */\r
+ Py_ssize_t requiredsize = (*outp-PyUnicode_AS_UNICODE(*outobj)) +\r
+ (insize - (curinp-startinp)) +\r
+ repsize - 1;\r
+ if (charmaptranslate_makespace(outobj, outp, requiredsize))\r
+ return -1;\r
+ memcpy(*outp, PyUnicode_AS_UNICODE(*res), sizeof(Py_UNICODE)*repsize);\r
+ *outp += repsize;\r
+ }\r
+ }\r
+ else\r
+ return -1;\r
+ return 0;\r
+}\r
+\r
+PyObject *PyUnicode_TranslateCharmap(const Py_UNICODE *p,\r
+ Py_ssize_t size,\r
+ PyObject *mapping,\r
+ const char *errors)\r
+{\r
+ /* output object */\r
+ PyObject *res = NULL;\r
+ /* pointers to the beginning and end+1 of input */\r
+ const Py_UNICODE *startp = p;\r
+ const Py_UNICODE *endp = p + size;\r
+ /* pointer into the output */\r
+ Py_UNICODE *str;\r
+ /* current output position */\r
+ Py_ssize_t respos = 0;\r
+ char *reason = "character maps to <undefined>";\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+ /* the following variable is used for caching string comparisons\r
+ * -1=not initialized, 0=unknown, 1=strict, 2=replace,\r
+ * 3=ignore, 4=xmlcharrefreplace */\r
+ int known_errorHandler = -1;\r
+\r
+ if (mapping == NULL) {\r
+ PyErr_BadArgument();\r
+ return NULL;\r
+ }\r
+\r
+ /* allocate enough for a simple 1:1 translation without\r
+ replacements, if we need more, we'll resize */\r
+ res = PyUnicode_FromUnicode(NULL, size);\r
+ if (res == NULL)\r
+ goto onError;\r
+ if (size == 0)\r
+ return res;\r
+ str = PyUnicode_AS_UNICODE(res);\r
+\r
+ while (p<endp) {\r
+ /* try to encode it */\r
+ PyObject *x = NULL;\r
+ if (charmaptranslate_output(startp, p, size, mapping, &res, &str, &x)) {\r
+ Py_XDECREF(x);\r
+ goto onError;\r
+ }\r
+ Py_XDECREF(x);\r
+ if (x!=Py_None) /* it worked => adjust input pointer */\r
+ ++p;\r
+ else { /* untranslatable character */\r
+ PyObject *repunicode = NULL; /* initialize to prevent gcc warning */\r
+ Py_ssize_t repsize;\r
+ Py_ssize_t newpos;\r
+ Py_UNICODE *uni2;\r
+ /* startpos for collecting untranslatable chars */\r
+ const Py_UNICODE *collstart = p;\r
+ const Py_UNICODE *collend = p+1;\r
+ const Py_UNICODE *coll;\r
+\r
+ /* find all untranslatable characters */\r
+ while (collend < endp) {\r
+ if (charmaptranslate_lookup(*collend, mapping, &x))\r
+ goto onError;\r
+ Py_XDECREF(x);\r
+ if (x!=Py_None)\r
+ break;\r
+ ++collend;\r
+ }\r
+ /* cache callback name lookup\r
+ * (if not done yet, i.e. it's the first error) */\r
+ if (known_errorHandler==-1) {\r
+ if ((errors==NULL) || (!strcmp(errors, "strict")))\r
+ known_errorHandler = 1;\r
+ else if (!strcmp(errors, "replace"))\r
+ known_errorHandler = 2;\r
+ else if (!strcmp(errors, "ignore"))\r
+ known_errorHandler = 3;\r
+ else if (!strcmp(errors, "xmlcharrefreplace"))\r
+ known_errorHandler = 4;\r
+ else\r
+ known_errorHandler = 0;\r
+ }\r
+ switch (known_errorHandler) {\r
+ case 1: /* strict */\r
+ raise_translate_exception(&exc, startp, size, collstart-startp, collend-startp, reason);\r
+ goto onError;\r
+ case 2: /* replace */\r
+ /* No need to check for space, this is a 1:1 replacement */\r
+ for (coll = collstart; coll<collend; ++coll)\r
+ *str++ = '?';\r
+ /* fall through */\r
+ case 3: /* ignore */\r
+ p = collend;\r
+ break;\r
+ case 4: /* xmlcharrefreplace */\r
+ /* generate replacement (temporarily (mis)uses p) */\r
+ for (p = collstart; p < collend;) {\r
+ char buffer[2+29+1+1];\r
+ char *cp;\r
+ Py_UCS4 ch = _Py_UNICODE_NEXT(p, collend);\r
+ sprintf(buffer, "&#%d;", (int)ch);\r
+ if (charmaptranslate_makespace(&res, &str,\r
+ (str-PyUnicode_AS_UNICODE(res))+strlen(buffer)+(endp-collend)))\r
+ goto onError;\r
+ for (cp = buffer; *cp; ++cp)\r
+ *str++ = *cp;\r
+ }\r
+ p = collend;\r
+ break;\r
+ default:\r
+ repunicode = unicode_translate_call_errorhandler(errors, &errorHandler,\r
+ reason, startp, size, &exc,\r
+ collstart-startp, collend-startp, &newpos);\r
+ if (repunicode == NULL)\r
+ goto onError;\r
+ /* generate replacement */\r
+ repsize = PyUnicode_GET_SIZE(repunicode);\r
+ if (charmaptranslate_makespace(&res, &str,\r
+ (str-PyUnicode_AS_UNICODE(res))+repsize+(endp-collend))) {\r
+ Py_DECREF(repunicode);\r
+ goto onError;\r
+ }\r
+ for (uni2 = PyUnicode_AS_UNICODE(repunicode); repsize-->0; ++uni2)\r
+ *str++ = *uni2;\r
+ p = startp + newpos;\r
+ Py_DECREF(repunicode);\r
+ }\r
+ }\r
+ }\r
+ /* Resize if we allocated to much */\r
+ respos = str-PyUnicode_AS_UNICODE(res);\r
+ if (respos<PyUnicode_GET_SIZE(res)) {\r
+ if (PyUnicode_Resize(&res, respos) < 0)\r
+ goto onError;\r
+ }\r
+ Py_XDECREF(exc);\r
+ Py_XDECREF(errorHandler);\r
+ return res;\r
+\r
+ onError:\r
+ Py_XDECREF(res);\r
+ Py_XDECREF(exc);\r
+ Py_XDECREF(errorHandler);\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyUnicode_Translate(PyObject *str,\r
+ PyObject *mapping,\r
+ const char *errors)\r
+{\r
+ PyObject *result;\r
+\r
+ str = PyUnicode_FromObject(str);\r
+ if (str == NULL)\r
+ goto onError;\r
+ result = PyUnicode_TranslateCharmap(PyUnicode_AS_UNICODE(str),\r
+ PyUnicode_GET_SIZE(str),\r
+ mapping,\r
+ errors);\r
+ Py_DECREF(str);\r
+ return result;\r
+\r
+ onError:\r
+ Py_XDECREF(str);\r
+ return NULL;\r
+}\r
+\r
+/* --- Decimal Encoder ---------------------------------------------------- */\r
+\r
+int PyUnicode_EncodeDecimal(Py_UNICODE *s,\r
+ Py_ssize_t length,\r
+ char *output,\r
+ const char *errors)\r
+{\r
+ Py_UNICODE *p, *end;\r
+ PyObject *errorHandler = NULL;\r
+ PyObject *exc = NULL;\r
+ const char *encoding = "decimal";\r
+ const char *reason = "invalid decimal Unicode string";\r
+ /* the following variable is used for caching string comparisons\r
+ * -1=not initialized, 0=unknown, 1=strict, 2=replace, 3=ignore, 4=xmlcharrefreplace */\r
+ int known_errorHandler = -1;\r
+\r
+ if (output == NULL) {\r
+ PyErr_BadArgument();\r
+ return -1;\r
+ }\r
+\r
+ p = s;\r
+ end = s + length;\r
+ while (p < end) {\r
+ register Py_UNICODE ch = *p;\r
+ int decimal;\r
+ PyObject *repunicode;\r
+ Py_ssize_t repsize;\r
+ Py_ssize_t newpos;\r
+ Py_UNICODE *uni2;\r
+ Py_UNICODE *collstart;\r
+ Py_UNICODE *collend;\r
+\r
+ if (Py_UNICODE_ISSPACE(ch)) {\r
+ *output++ = ' ';\r
+ ++p;\r
+ continue;\r
+ }\r
+ decimal = Py_UNICODE_TODECIMAL(ch);\r
+ if (decimal >= 0) {\r
+ *output++ = '0' + decimal;\r
+ ++p;\r
+ continue;\r
+ }\r
+ if (0 < ch && ch < 256) {\r
+ *output++ = (char)ch;\r
+ ++p;\r
+ continue;\r
+ }\r
+ /* All other characters are considered unencodable */\r
+ collstart = p;\r
+ for (collend = p+1; collend < end; collend++) {\r
+ if ((0 < *collend && *collend < 256) ||\r
+ Py_UNICODE_ISSPACE(*collend) ||\r
+ 0 <= Py_UNICODE_TODECIMAL(*collend))\r
+ break;\r
+ }\r
+ /* cache callback name lookup\r
+ * (if not done yet, i.e. it's the first error) */\r
+ if (known_errorHandler==-1) {\r
+ if ((errors==NULL) || (!strcmp(errors, "strict")))\r
+ known_errorHandler = 1;\r
+ else if (!strcmp(errors, "replace"))\r
+ known_errorHandler = 2;\r
+ else if (!strcmp(errors, "ignore"))\r
+ known_errorHandler = 3;\r
+ else if (!strcmp(errors, "xmlcharrefreplace"))\r
+ known_errorHandler = 4;\r
+ else\r
+ known_errorHandler = 0;\r
+ }\r
+ switch (known_errorHandler) {\r
+ case 1: /* strict */\r
+ raise_encode_exception(&exc, encoding, s, length, collstart-s, collend-s, reason);\r
+ goto onError;\r
+ case 2: /* replace */\r
+ for (p = collstart; p < collend; ++p)\r
+ *output++ = '?';\r
+ /* fall through */\r
+ case 3: /* ignore */\r
+ p = collend;\r
+ break;\r
+ case 4: /* xmlcharrefreplace */\r
+ /* generate replacement (temporarily (mis)uses p) */\r
+ for (p = collstart; p < collend;) {\r
+ Py_UCS4 ch = _Py_UNICODE_NEXT(p, collend);\r
+ output += sprintf(output, "&#%d;", ch);\r
+ }\r
+ p = collend;\r
+ break;\r
+ default:\r
+ repunicode = unicode_encode_call_errorhandler(errors, &errorHandler,\r
+ encoding, reason, s, length, &exc,\r
+ collstart-s, collend-s, &newpos);\r
+ if (repunicode == NULL)\r
+ goto onError;\r
+ /* generate replacement */\r
+ repsize = PyUnicode_GET_SIZE(repunicode);\r
+ for (uni2 = PyUnicode_AS_UNICODE(repunicode); repsize-->0; ++uni2) {\r
+ Py_UNICODE ch = *uni2;\r
+ if (Py_UNICODE_ISSPACE(ch))\r
+ *output++ = ' ';\r
+ else {\r
+ decimal = Py_UNICODE_TODECIMAL(ch);\r
+ if (decimal >= 0)\r
+ *output++ = '0' + decimal;\r
+ else if (0 < ch && ch < 256)\r
+ *output++ = (char)ch;\r
+ else {\r
+ Py_DECREF(repunicode);\r
+ raise_encode_exception(&exc, encoding,\r
+ s, length, collstart-s, collend-s, reason);\r
+ goto onError;\r
+ }\r
+ }\r
+ }\r
+ p = s + newpos;\r
+ Py_DECREF(repunicode);\r
+ }\r
+ }\r
+ /* 0-terminate the output string */\r
+ *output++ = '\0';\r
+ Py_XDECREF(exc);\r
+ Py_XDECREF(errorHandler);\r
+ return 0;\r
+\r
+ onError:\r
+ Py_XDECREF(exc);\r
+ Py_XDECREF(errorHandler);\r
+ return -1;\r
+}\r
+\r
+/* --- Helpers ------------------------------------------------------------ */\r
+\r
+#include "stringlib/unicodedefs.h"\r
+#include "stringlib/fastsearch.h"\r
+\r
+#include "stringlib/count.h"\r
+#include "stringlib/find.h"\r
+#include "stringlib/partition.h"\r
+#include "stringlib/split.h"\r
+\r
+/* helper macro to fixup start/end slice values */\r
+#define ADJUST_INDICES(start, end, len) \\r
+ if (end > len) \\r
+ end = len; \\r
+ else if (end < 0) { \\r
+ end += len; \\r
+ if (end < 0) \\r
+ end = 0; \\r
+ } \\r
+ if (start < 0) { \\r
+ start += len; \\r
+ if (start < 0) \\r
+ start = 0; \\r
+ }\r
+\r
+Py_ssize_t PyUnicode_Count(PyObject *str,\r
+ PyObject *substr,\r
+ Py_ssize_t start,\r
+ Py_ssize_t end)\r
+{\r
+ Py_ssize_t result;\r
+ PyUnicodeObject* str_obj;\r
+ PyUnicodeObject* sub_obj;\r
+\r
+ str_obj = (PyUnicodeObject*) PyUnicode_FromObject(str);\r
+ if (!str_obj)\r
+ return -1;\r
+ sub_obj = (PyUnicodeObject*) PyUnicode_FromObject(substr);\r
+ if (!sub_obj) {\r
+ Py_DECREF(str_obj);\r
+ return -1;\r
+ }\r
+\r
+ ADJUST_INDICES(start, end, str_obj->length);\r
+ result = stringlib_count(\r
+ str_obj->str + start, end - start, sub_obj->str, sub_obj->length,\r
+ PY_SSIZE_T_MAX\r
+ );\r
+\r
+ Py_DECREF(sub_obj);\r
+ Py_DECREF(str_obj);\r
+\r
+ return result;\r
+}\r
+\r
+Py_ssize_t PyUnicode_Find(PyObject *str,\r
+ PyObject *sub,\r
+ Py_ssize_t start,\r
+ Py_ssize_t end,\r
+ int direction)\r
+{\r
+ Py_ssize_t result;\r
+\r
+ str = PyUnicode_FromObject(str);\r
+ if (!str)\r
+ return -2;\r
+ sub = PyUnicode_FromObject(sub);\r
+ if (!sub) {\r
+ Py_DECREF(str);\r
+ return -2;\r
+ }\r
+\r
+ if (direction > 0)\r
+ result = stringlib_find_slice(\r
+ PyUnicode_AS_UNICODE(str), PyUnicode_GET_SIZE(str),\r
+ PyUnicode_AS_UNICODE(sub), PyUnicode_GET_SIZE(sub),\r
+ start, end\r
+ );\r
+ else\r
+ result = stringlib_rfind_slice(\r
+ PyUnicode_AS_UNICODE(str), PyUnicode_GET_SIZE(str),\r
+ PyUnicode_AS_UNICODE(sub), PyUnicode_GET_SIZE(sub),\r
+ start, end\r
+ );\r
+\r
+ Py_DECREF(str);\r
+ Py_DECREF(sub);\r
+\r
+ return result;\r
+}\r
+\r
+static\r
+int tailmatch(PyUnicodeObject *self,\r
+ PyUnicodeObject *substring,\r
+ Py_ssize_t start,\r
+ Py_ssize_t end,\r
+ int direction)\r
+{\r
+ if (substring->length == 0)\r
+ return 1;\r
+\r
+ ADJUST_INDICES(start, end, self->length);\r
+ end -= substring->length;\r
+ if (end < start)\r
+ return 0;\r
+\r
+ if (direction > 0) {\r
+ if (Py_UNICODE_MATCH(self, end, substring))\r
+ return 1;\r
+ } else {\r
+ if (Py_UNICODE_MATCH(self, start, substring))\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+Py_ssize_t PyUnicode_Tailmatch(PyObject *str,\r
+ PyObject *substr,\r
+ Py_ssize_t start,\r
+ Py_ssize_t end,\r
+ int direction)\r
+{\r
+ Py_ssize_t result;\r
+\r
+ str = PyUnicode_FromObject(str);\r
+ if (str == NULL)\r
+ return -1;\r
+ substr = PyUnicode_FromObject(substr);\r
+ if (substr == NULL) {\r
+ Py_DECREF(str);\r
+ return -1;\r
+ }\r
+\r
+ result = tailmatch((PyUnicodeObject *)str,\r
+ (PyUnicodeObject *)substr,\r
+ start, end, direction);\r
+ Py_DECREF(str);\r
+ Py_DECREF(substr);\r
+ return result;\r
+}\r
+\r
+/* Apply fixfct filter to the Unicode object self and return a\r
+ reference to the modified object */\r
+\r
+static\r
+PyObject *fixup(PyUnicodeObject *self,\r
+ int (*fixfct)(PyUnicodeObject *s))\r
+{\r
+\r
+ PyUnicodeObject *u;\r
+\r
+ u = (PyUnicodeObject*) PyUnicode_FromUnicode(NULL, self->length);\r
+ if (u == NULL)\r
+ return NULL;\r
+\r
+ Py_UNICODE_COPY(u->str, self->str, self->length);\r
+\r
+ if (!fixfct(u) && PyUnicode_CheckExact(self)) {\r
+ /* fixfct should return TRUE if it modified the buffer. If\r
+ FALSE, return a reference to the original buffer instead\r
+ (to save space, not time) */\r
+ Py_INCREF(self);\r
+ Py_DECREF(u);\r
+ return (PyObject*) self;\r
+ }\r
+ return (PyObject*) u;\r
+}\r
+\r
+static\r
+int fixupper(PyUnicodeObject *self)\r
+{\r
+ Py_ssize_t len = self->length;\r
+ Py_UNICODE *s = self->str;\r
+ int status = 0;\r
+\r
+ while (len-- > 0) {\r
+ register Py_UNICODE ch;\r
+\r
+ ch = Py_UNICODE_TOUPPER(*s);\r
+ if (ch != *s) {\r
+ status = 1;\r
+ *s = ch;\r
+ }\r
+ s++;\r
+ }\r
+\r
+ return status;\r
+}\r
+\r
+static\r
+int fixlower(PyUnicodeObject *self)\r
+{\r
+ Py_ssize_t len = self->length;\r
+ Py_UNICODE *s = self->str;\r
+ int status = 0;\r
+\r
+ while (len-- > 0) {\r
+ register Py_UNICODE ch;\r
+\r
+ ch = Py_UNICODE_TOLOWER(*s);\r
+ if (ch != *s) {\r
+ status = 1;\r
+ *s = ch;\r
+ }\r
+ s++;\r
+ }\r
+\r
+ return status;\r
+}\r
+\r
+static\r
+int fixswapcase(PyUnicodeObject *self)\r
+{\r
+ Py_ssize_t len = self->length;\r
+ Py_UNICODE *s = self->str;\r
+ int status = 0;\r
+\r
+ while (len-- > 0) {\r
+ if (Py_UNICODE_ISUPPER(*s)) {\r
+ *s = Py_UNICODE_TOLOWER(*s);\r
+ status = 1;\r
+ } else if (Py_UNICODE_ISLOWER(*s)) {\r
+ *s = Py_UNICODE_TOUPPER(*s);\r
+ status = 1;\r
+ }\r
+ s++;\r
+ }\r
+\r
+ return status;\r
+}\r
+\r
+static\r
+int fixcapitalize(PyUnicodeObject *self)\r
+{\r
+ Py_ssize_t len = self->length;\r
+ Py_UNICODE *s = self->str;\r
+ int status = 0;\r
+\r
+ if (len == 0)\r
+ return 0;\r
+ if (!Py_UNICODE_ISUPPER(*s)) {\r
+ *s = Py_UNICODE_TOUPPER(*s);\r
+ status = 1;\r
+ }\r
+ s++;\r
+ while (--len > 0) {\r
+ if (!Py_UNICODE_ISLOWER(*s)) {\r
+ *s = Py_UNICODE_TOLOWER(*s);\r
+ status = 1;\r
+ }\r
+ s++;\r
+ }\r
+ return status;\r
+}\r
+\r
+static\r
+int fixtitle(PyUnicodeObject *self)\r
+{\r
+ register Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register Py_UNICODE *e;\r
+ int previous_is_cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1) {\r
+ Py_UNICODE ch = Py_UNICODE_TOTITLE(*p);\r
+ if (*p != ch) {\r
+ *p = ch;\r
+ return 1;\r
+ }\r
+ else\r
+ return 0;\r
+ }\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ previous_is_cased = 0;\r
+ for (; p < e; p++) {\r
+ register const Py_UNICODE ch = *p;\r
+\r
+ if (previous_is_cased)\r
+ *p = Py_UNICODE_TOLOWER(ch);\r
+ else\r
+ *p = Py_UNICODE_TOTITLE(ch);\r
+\r
+ if (Py_UNICODE_ISLOWER(ch) ||\r
+ Py_UNICODE_ISUPPER(ch) ||\r
+ Py_UNICODE_ISTITLE(ch))\r
+ previous_is_cased = 1;\r
+ else\r
+ previous_is_cased = 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+PyObject *\r
+PyUnicode_Join(PyObject *separator, PyObject *seq)\r
+{\r
+ PyObject *internal_separator = NULL;\r
+ const Py_UNICODE blank = ' ';\r
+ const Py_UNICODE *sep = ␣\r
+ Py_ssize_t seplen = 1;\r
+ PyUnicodeObject *res = NULL; /* the result */\r
+ Py_ssize_t res_alloc = 100; /* # allocated bytes for string in res */\r
+ Py_ssize_t res_used; /* # used bytes */\r
+ Py_UNICODE *res_p; /* pointer to free byte in res's string area */\r
+ PyObject *fseq; /* PySequence_Fast(seq) */\r
+ Py_ssize_t seqlen; /* len(fseq) -- number of items in sequence */\r
+ PyObject *item;\r
+ Py_ssize_t i;\r
+\r
+ fseq = PySequence_Fast(seq, "can only join an iterable");\r
+ if (fseq == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ /* Grrrr. A codec may be invoked to convert str objects to\r
+ * Unicode, and so it's possible to call back into Python code\r
+ * during PyUnicode_FromObject(), and so it's possible for a sick\r
+ * codec to change the size of fseq (if seq is a list). Therefore\r
+ * we have to keep refetching the size -- can't assume seqlen\r
+ * is invariant.\r
+ */\r
+ seqlen = PySequence_Fast_GET_SIZE(fseq);\r
+ /* If empty sequence, return u"". */\r
+ if (seqlen == 0) {\r
+ res = _PyUnicode_New(0); /* empty sequence; return u"" */\r
+ goto Done;\r
+ }\r
+ /* If singleton sequence with an exact Unicode, return that. */\r
+ if (seqlen == 1) {\r
+ item = PySequence_Fast_GET_ITEM(fseq, 0);\r
+ if (PyUnicode_CheckExact(item)) {\r
+ Py_INCREF(item);\r
+ res = (PyUnicodeObject *)item;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ /* At least two items to join, or one that isn't exact Unicode. */\r
+ if (seqlen > 1) {\r
+ /* Set up sep and seplen -- they're needed. */\r
+ if (separator == NULL) {\r
+ sep = ␣\r
+ seplen = 1;\r
+ }\r
+ else {\r
+ internal_separator = PyUnicode_FromObject(separator);\r
+ if (internal_separator == NULL)\r
+ goto onError;\r
+ sep = PyUnicode_AS_UNICODE(internal_separator);\r
+ seplen = PyUnicode_GET_SIZE(internal_separator);\r
+ /* In case PyUnicode_FromObject() mutated seq. */\r
+ seqlen = PySequence_Fast_GET_SIZE(fseq);\r
+ }\r
+ }\r
+\r
+ /* Get space. */\r
+ res = _PyUnicode_New(res_alloc);\r
+ if (res == NULL)\r
+ goto onError;\r
+ res_p = PyUnicode_AS_UNICODE(res);\r
+ res_used = 0;\r
+\r
+ for (i = 0; i < seqlen; ++i) {\r
+ Py_ssize_t itemlen;\r
+ Py_ssize_t new_res_used;\r
+\r
+ item = PySequence_Fast_GET_ITEM(fseq, i);\r
+ /* Convert item to Unicode. */\r
+ if (! PyUnicode_Check(item) && ! PyString_Check(item)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "sequence item %zd: expected string or Unicode,"\r
+ " %.80s found",\r
+ i, Py_TYPE(item)->tp_name);\r
+ goto onError;\r
+ }\r
+ item = PyUnicode_FromObject(item);\r
+ if (item == NULL)\r
+ goto onError;\r
+ /* We own a reference to item from here on. */\r
+\r
+ /* In case PyUnicode_FromObject() mutated seq. */\r
+ seqlen = PySequence_Fast_GET_SIZE(fseq);\r
+\r
+ /* Make sure we have enough space for the separator and the item. */\r
+ itemlen = PyUnicode_GET_SIZE(item);\r
+ new_res_used = res_used + itemlen;\r
+ if (new_res_used < 0)\r
+ goto Overflow;\r
+ if (i < seqlen - 1) {\r
+ new_res_used += seplen;\r
+ if (new_res_used < 0)\r
+ goto Overflow;\r
+ }\r
+ if (new_res_used > res_alloc) {\r
+ /* double allocated size until it's big enough */\r
+ do {\r
+ res_alloc += res_alloc;\r
+ if (res_alloc <= 0)\r
+ goto Overflow;\r
+ } while (new_res_used > res_alloc);\r
+ if (_PyUnicode_Resize(&res, res_alloc) < 0) {\r
+ Py_DECREF(item);\r
+ goto onError;\r
+ }\r
+ res_p = PyUnicode_AS_UNICODE(res) + res_used;\r
+ }\r
+\r
+ /* Copy item, and maybe the separator. */\r
+ Py_UNICODE_COPY(res_p, PyUnicode_AS_UNICODE(item), itemlen);\r
+ res_p += itemlen;\r
+ if (i < seqlen - 1) {\r
+ Py_UNICODE_COPY(res_p, sep, seplen);\r
+ res_p += seplen;\r
+ }\r
+ Py_DECREF(item);\r
+ res_used = new_res_used;\r
+ }\r
+\r
+ /* Shrink res to match the used area; this probably can't fail,\r
+ * but it's cheap to check.\r
+ */\r
+ if (_PyUnicode_Resize(&res, res_used) < 0)\r
+ goto onError;\r
+\r
+ Done:\r
+ Py_XDECREF(internal_separator);\r
+ Py_DECREF(fseq);\r
+ return (PyObject *)res;\r
+\r
+ Overflow:\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "join() result is too long for a Python string");\r
+ Py_DECREF(item);\r
+ /* fall through */\r
+\r
+ onError:\r
+ Py_XDECREF(internal_separator);\r
+ Py_DECREF(fseq);\r
+ Py_XDECREF(res);\r
+ return NULL;\r
+}\r
+\r
+static\r
+PyUnicodeObject *pad(PyUnicodeObject *self,\r
+ Py_ssize_t left,\r
+ Py_ssize_t right,\r
+ Py_UNICODE fill)\r
+{\r
+ PyUnicodeObject *u;\r
+\r
+ if (left < 0)\r
+ left = 0;\r
+ if (right < 0)\r
+ right = 0;\r
+\r
+ if (left == 0 && right == 0 && PyUnicode_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return self;\r
+ }\r
+\r
+ if (left > PY_SSIZE_T_MAX - self->length ||\r
+ right > PY_SSIZE_T_MAX - (left + self->length)) {\r
+ PyErr_SetString(PyExc_OverflowError, "padded string is too long");\r
+ return NULL;\r
+ }\r
+ u = _PyUnicode_New(left + self->length + right);\r
+ if (u) {\r
+ if (left)\r
+ Py_UNICODE_FILL(u->str, fill, left);\r
+ Py_UNICODE_COPY(u->str + left, self->str, self->length);\r
+ if (right)\r
+ Py_UNICODE_FILL(u->str + left + self->length, fill, right);\r
+ }\r
+\r
+ return u;\r
+}\r
+\r
+PyObject *PyUnicode_Splitlines(PyObject *string, int keepends)\r
+{\r
+ PyObject *list;\r
+\r
+ string = PyUnicode_FromObject(string);\r
+ if (string == NULL)\r
+ return NULL;\r
+\r
+ list = stringlib_splitlines(\r
+ (PyObject*) string, PyUnicode_AS_UNICODE(string),\r
+ PyUnicode_GET_SIZE(string), keepends);\r
+\r
+ Py_DECREF(string);\r
+ return list;\r
+}\r
+\r
+static\r
+PyObject *split(PyUnicodeObject *self,\r
+ PyUnicodeObject *substring,\r
+ Py_ssize_t maxcount)\r
+{\r
+ if (maxcount < 0)\r
+ maxcount = PY_SSIZE_T_MAX;\r
+\r
+ if (substring == NULL)\r
+ return stringlib_split_whitespace(\r
+ (PyObject*) self, self->str, self->length, maxcount\r
+ );\r
+\r
+ return stringlib_split(\r
+ (PyObject*) self, self->str, self->length,\r
+ substring->str, substring->length,\r
+ maxcount\r
+ );\r
+}\r
+\r
+static\r
+PyObject *rsplit(PyUnicodeObject *self,\r
+ PyUnicodeObject *substring,\r
+ Py_ssize_t maxcount)\r
+{\r
+ if (maxcount < 0)\r
+ maxcount = PY_SSIZE_T_MAX;\r
+\r
+ if (substring == NULL)\r
+ return stringlib_rsplit_whitespace(\r
+ (PyObject*) self, self->str, self->length, maxcount\r
+ );\r
+\r
+ return stringlib_rsplit(\r
+ (PyObject*) self, self->str, self->length,\r
+ substring->str, substring->length,\r
+ maxcount\r
+ );\r
+}\r
+\r
+static\r
+PyObject *replace(PyUnicodeObject *self,\r
+ PyUnicodeObject *str1,\r
+ PyUnicodeObject *str2,\r
+ Py_ssize_t maxcount)\r
+{\r
+ PyUnicodeObject *u;\r
+\r
+ if (maxcount < 0)\r
+ maxcount = PY_SSIZE_T_MAX;\r
+ else if (maxcount == 0 || self->length == 0)\r
+ goto nothing;\r
+\r
+ if (str1->length == str2->length) {\r
+ Py_ssize_t i;\r
+ /* same length */\r
+ if (str1->length == 0)\r
+ goto nothing;\r
+ if (str1->length == 1) {\r
+ /* replace characters */\r
+ Py_UNICODE u1, u2;\r
+ if (!findchar(self->str, self->length, str1->str[0]))\r
+ goto nothing;\r
+ u = (PyUnicodeObject*) PyUnicode_FromUnicode(NULL, self->length);\r
+ if (!u)\r
+ return NULL;\r
+ Py_UNICODE_COPY(u->str, self->str, self->length);\r
+ u1 = str1->str[0];\r
+ u2 = str2->str[0];\r
+ for (i = 0; i < u->length; i++)\r
+ if (u->str[i] == u1) {\r
+ if (--maxcount < 0)\r
+ break;\r
+ u->str[i] = u2;\r
+ }\r
+ } else {\r
+ i = stringlib_find(\r
+ self->str, self->length, str1->str, str1->length, 0\r
+ );\r
+ if (i < 0)\r
+ goto nothing;\r
+ u = (PyUnicodeObject*) PyUnicode_FromUnicode(NULL, self->length);\r
+ if (!u)\r
+ return NULL;\r
+ Py_UNICODE_COPY(u->str, self->str, self->length);\r
+\r
+ /* change everything in-place, starting with this one */\r
+ Py_UNICODE_COPY(u->str+i, str2->str, str2->length);\r
+ i += str1->length;\r
+\r
+ while ( --maxcount > 0) {\r
+ i = stringlib_find(self->str+i, self->length-i,\r
+ str1->str, str1->length,\r
+ i);\r
+ if (i == -1)\r
+ break;\r
+ Py_UNICODE_COPY(u->str+i, str2->str, str2->length);\r
+ i += str1->length;\r
+ }\r
+ }\r
+ } else {\r
+\r
+ Py_ssize_t n, i, j;\r
+ Py_ssize_t product, new_size, delta;\r
+ Py_UNICODE *p;\r
+\r
+ /* replace strings */\r
+ n = stringlib_count(self->str, self->length, str1->str, str1->length,\r
+ maxcount);\r
+ if (n == 0)\r
+ goto nothing;\r
+ /* new_size = self->length + n * (str2->length - str1->length)); */\r
+ delta = (str2->length - str1->length);\r
+ if (delta == 0) {\r
+ new_size = self->length;\r
+ } else {\r
+ product = n * (str2->length - str1->length);\r
+ if ((product / (str2->length - str1->length)) != n) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "replace string is too long");\r
+ return NULL;\r
+ }\r
+ new_size = self->length + product;\r
+ if (new_size < 0) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "replace string is too long");\r
+ return NULL;\r
+ }\r
+ }\r
+ u = _PyUnicode_New(new_size);\r
+ if (!u)\r
+ return NULL;\r
+ i = 0;\r
+ p = u->str;\r
+ if (str1->length > 0) {\r
+ while (n-- > 0) {\r
+ /* look for next match */\r
+ j = stringlib_find(self->str+i, self->length-i,\r
+ str1->str, str1->length,\r
+ i);\r
+ if (j == -1)\r
+ break;\r
+ else if (j > i) {\r
+ /* copy unchanged part [i:j] */\r
+ Py_UNICODE_COPY(p, self->str+i, j-i);\r
+ p += j - i;\r
+ }\r
+ /* copy substitution string */\r
+ if (str2->length > 0) {\r
+ Py_UNICODE_COPY(p, str2->str, str2->length);\r
+ p += str2->length;\r
+ }\r
+ i = j + str1->length;\r
+ }\r
+ if (i < self->length)\r
+ /* copy tail [i:] */\r
+ Py_UNICODE_COPY(p, self->str+i, self->length-i);\r
+ } else {\r
+ /* interleave */\r
+ while (n > 0) {\r
+ Py_UNICODE_COPY(p, str2->str, str2->length);\r
+ p += str2->length;\r
+ if (--n <= 0)\r
+ break;\r
+ *p++ = self->str[i++];\r
+ }\r
+ Py_UNICODE_COPY(p, self->str+i, self->length-i);\r
+ }\r
+ }\r
+ return (PyObject *) u;\r
+\r
+ nothing:\r
+ /* nothing to replace; return original string (when possible) */\r
+ if (PyUnicode_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject *) self;\r
+ }\r
+ return PyUnicode_FromUnicode(self->str, self->length);\r
+}\r
+\r
+/* --- Unicode Object Methods --------------------------------------------- */\r
+\r
+PyDoc_STRVAR(title__doc__,\r
+ "S.title() -> unicode\n\\r
+\n\\r
+Return a titlecased version of S, i.e. words start with title case\n\\r
+characters, all remaining cased characters have lower case.");\r
+\r
+static PyObject*\r
+unicode_title(PyUnicodeObject *self)\r
+{\r
+ return fixup(self, fixtitle);\r
+}\r
+\r
+PyDoc_STRVAR(capitalize__doc__,\r
+ "S.capitalize() -> unicode\n\\r
+\n\\r
+Return a capitalized version of S, i.e. make the first character\n\\r
+have upper case and the rest lower case.");\r
+\r
+static PyObject*\r
+unicode_capitalize(PyUnicodeObject *self)\r
+{\r
+ return fixup(self, fixcapitalize);\r
+}\r
+\r
+#if 0\r
+PyDoc_STRVAR(capwords__doc__,\r
+ "S.capwords() -> unicode\n\\r
+\n\\r
+Apply .capitalize() to all words in S and return the result with\n\\r
+normalized whitespace (all whitespace strings are replaced by ' ').");\r
+\r
+static PyObject*\r
+unicode_capwords(PyUnicodeObject *self)\r
+{\r
+ PyObject *list;\r
+ PyObject *item;\r
+ Py_ssize_t i;\r
+\r
+ /* Split into words */\r
+ list = split(self, NULL, -1);\r
+ if (!list)\r
+ return NULL;\r
+\r
+ /* Capitalize each word */\r
+ for (i = 0; i < PyList_GET_SIZE(list); i++) {\r
+ item = fixup((PyUnicodeObject *)PyList_GET_ITEM(list, i),\r
+ fixcapitalize);\r
+ if (item == NULL)\r
+ goto onError;\r
+ Py_DECREF(PyList_GET_ITEM(list, i));\r
+ PyList_SET_ITEM(list, i, item);\r
+ }\r
+\r
+ /* Join the words to form a new string */\r
+ item = PyUnicode_Join(NULL, list);\r
+\r
+ onError:\r
+ Py_DECREF(list);\r
+ return (PyObject *)item;\r
+}\r
+#endif\r
+\r
+/* Argument converter. Coerces to a single unicode character */\r
+\r
+static int\r
+convert_uc(PyObject *obj, void *addr)\r
+{\r
+ Py_UNICODE *fillcharloc = (Py_UNICODE *)addr;\r
+ PyObject *uniobj;\r
+ Py_UNICODE *unistr;\r
+\r
+ uniobj = PyUnicode_FromObject(obj);\r
+ if (uniobj == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "The fill character cannot be converted to Unicode");\r
+ return 0;\r
+ }\r
+ if (PyUnicode_GET_SIZE(uniobj) != 1) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "The fill character must be exactly one character long");\r
+ Py_DECREF(uniobj);\r
+ return 0;\r
+ }\r
+ unistr = PyUnicode_AS_UNICODE(uniobj);\r
+ *fillcharloc = unistr[0];\r
+ Py_DECREF(uniobj);\r
+ return 1;\r
+}\r
+\r
+PyDoc_STRVAR(center__doc__,\r
+ "S.center(width[, fillchar]) -> unicode\n\\r
+\n\\r
+Return S centered in a Unicode string of length width. Padding is\n\\r
+done using the specified fill character (default is a space)");\r
+\r
+static PyObject *\r
+unicode_center(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t marg, left;\r
+ Py_ssize_t width;\r
+ Py_UNICODE fillchar = ' ';\r
+\r
+ if (!PyArg_ParseTuple(args, "n|O&:center", &width, convert_uc, &fillchar))\r
+ return NULL;\r
+\r
+ if (self->length >= width && PyUnicode_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+ }\r
+\r
+ marg = width - self->length;\r
+ left = marg / 2 + (marg & width & 1);\r
+\r
+ return (PyObject*) pad(self, left, marg - left, fillchar);\r
+}\r
+\r
+#if 0\r
+\r
+/* This code should go into some future Unicode collation support\r
+ module. The basic comparison should compare ordinals on a naive\r
+ basis (this is what Java does and thus Jython too). */\r
+\r
+/* speedy UTF-16 code point order comparison */\r
+/* gleaned from: */\r
+/* http://www-4.ibm.com/software/developer/library/utf16.html?dwzone=unicode */\r
+\r
+static short utf16Fixup[32] =\r
+{\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0x2000, -0x800, -0x800, -0x800, -0x800\r
+};\r
+\r
+static int\r
+unicode_compare(PyUnicodeObject *str1, PyUnicodeObject *str2)\r
+{\r
+ Py_ssize_t len1, len2;\r
+\r
+ Py_UNICODE *s1 = str1->str;\r
+ Py_UNICODE *s2 = str2->str;\r
+\r
+ len1 = str1->length;\r
+ len2 = str2->length;\r
+\r
+ while (len1 > 0 && len2 > 0) {\r
+ Py_UNICODE c1, c2;\r
+\r
+ c1 = *s1++;\r
+ c2 = *s2++;\r
+\r
+ if (c1 > (1<<11) * 26)\r
+ c1 += utf16Fixup[c1>>11];\r
+ if (c2 > (1<<11) * 26)\r
+ c2 += utf16Fixup[c2>>11];\r
+ /* now c1 and c2 are in UTF-32-compatible order */\r
+\r
+ if (c1 != c2)\r
+ return (c1 < c2) ? -1 : 1;\r
+\r
+ len1--; len2--;\r
+ }\r
+\r
+ return (len1 < len2) ? -1 : (len1 != len2);\r
+}\r
+\r
+#else\r
+\r
+static int\r
+unicode_compare(PyUnicodeObject *str1, PyUnicodeObject *str2)\r
+{\r
+ register Py_ssize_t len1, len2;\r
+\r
+ Py_UNICODE *s1 = str1->str;\r
+ Py_UNICODE *s2 = str2->str;\r
+\r
+ len1 = str1->length;\r
+ len2 = str2->length;\r
+\r
+ while (len1 > 0 && len2 > 0) {\r
+ Py_UNICODE c1, c2;\r
+\r
+ c1 = *s1++;\r
+ c2 = *s2++;\r
+\r
+ if (c1 != c2)\r
+ return (c1 < c2) ? -1 : 1;\r
+\r
+ len1--; len2--;\r
+ }\r
+\r
+ return (len1 < len2) ? -1 : (len1 != len2);\r
+}\r
+\r
+#endif\r
+\r
+int PyUnicode_Compare(PyObject *left,\r
+ PyObject *right)\r
+{\r
+ PyUnicodeObject *u = NULL, *v = NULL;\r
+ int result;\r
+\r
+ /* Coerce the two arguments */\r
+ u = (PyUnicodeObject *)PyUnicode_FromObject(left);\r
+ if (u == NULL)\r
+ goto onError;\r
+ v = (PyUnicodeObject *)PyUnicode_FromObject(right);\r
+ if (v == NULL)\r
+ goto onError;\r
+\r
+ /* Shortcut for empty or interned objects */\r
+ if (v == u) {\r
+ Py_DECREF(u);\r
+ Py_DECREF(v);\r
+ return 0;\r
+ }\r
+\r
+ result = unicode_compare(u, v);\r
+\r
+ Py_DECREF(u);\r
+ Py_DECREF(v);\r
+ return result;\r
+\r
+ onError:\r
+ Py_XDECREF(u);\r
+ Py_XDECREF(v);\r
+ return -1;\r
+}\r
+\r
+PyObject *PyUnicode_RichCompare(PyObject *left,\r
+ PyObject *right,\r
+ int op)\r
+{\r
+ int result;\r
+\r
+ result = PyUnicode_Compare(left, right);\r
+ if (result == -1 && PyErr_Occurred())\r
+ goto onError;\r
+\r
+ /* Convert the return value to a Boolean */\r
+ switch (op) {\r
+ case Py_EQ:\r
+ result = (result == 0);\r
+ break;\r
+ case Py_NE:\r
+ result = (result != 0);\r
+ break;\r
+ case Py_LE:\r
+ result = (result <= 0);\r
+ break;\r
+ case Py_GE:\r
+ result = (result >= 0);\r
+ break;\r
+ case Py_LT:\r
+ result = (result == -1);\r
+ break;\r
+ case Py_GT:\r
+ result = (result == 1);\r
+ break;\r
+ }\r
+ return PyBool_FromLong(result);\r
+\r
+ onError:\r
+\r
+ /* Standard case\r
+\r
+ Type errors mean that PyUnicode_FromObject() could not convert\r
+ one of the arguments (usually the right hand side) to Unicode,\r
+ ie. we can't handle the comparison request. However, it is\r
+ possible that the other object knows a comparison method, which\r
+ is why we return Py_NotImplemented to give the other object a\r
+ chance.\r
+\r
+ */\r
+ if (PyErr_ExceptionMatches(PyExc_TypeError)) {\r
+ PyErr_Clear();\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ if (op != Py_EQ && op != Py_NE)\r
+ return NULL;\r
+\r
+ /* Equality comparison.\r
+\r
+ This is a special case: we silence any PyExc_UnicodeDecodeError\r
+ and instead turn it into a PyErr_UnicodeWarning.\r
+\r
+ */\r
+ if (!PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))\r
+ return NULL;\r
+ PyErr_Clear();\r
+ if (PyErr_Warn(PyExc_UnicodeWarning,\r
+ (op == Py_EQ) ?\r
+ "Unicode equal comparison "\r
+ "failed to convert both arguments to Unicode - "\r
+ "interpreting them as being unequal" :\r
+ "Unicode unequal comparison "\r
+ "failed to convert both arguments to Unicode - "\r
+ "interpreting them as being unequal"\r
+ ) < 0)\r
+ return NULL;\r
+ result = (op == Py_NE);\r
+ return PyBool_FromLong(result);\r
+}\r
+\r
+int PyUnicode_Contains(PyObject *container,\r
+ PyObject *element)\r
+{\r
+ PyObject *str, *sub;\r
+ int result;\r
+\r
+ /* Coerce the two arguments */\r
+ sub = PyUnicode_FromObject(element);\r
+ if (!sub) {\r
+ return -1;\r
+ }\r
+\r
+ str = PyUnicode_FromObject(container);\r
+ if (!str) {\r
+ Py_DECREF(sub);\r
+ return -1;\r
+ }\r
+\r
+ result = stringlib_contains_obj(str, sub);\r
+\r
+ Py_DECREF(str);\r
+ Py_DECREF(sub);\r
+\r
+ return result;\r
+}\r
+\r
+/* Concat to string or Unicode object giving a new Unicode object. */\r
+\r
+PyObject *PyUnicode_Concat(PyObject *left,\r
+ PyObject *right)\r
+{\r
+ PyUnicodeObject *u = NULL, *v = NULL, *w;\r
+\r
+ /* Coerce the two arguments */\r
+ u = (PyUnicodeObject *)PyUnicode_FromObject(left);\r
+ if (u == NULL)\r
+ goto onError;\r
+ v = (PyUnicodeObject *)PyUnicode_FromObject(right);\r
+ if (v == NULL)\r
+ goto onError;\r
+\r
+ /* Shortcuts */\r
+ if (v == unicode_empty) {\r
+ Py_DECREF(v);\r
+ return (PyObject *)u;\r
+ }\r
+ if (u == unicode_empty) {\r
+ Py_DECREF(u);\r
+ return (PyObject *)v;\r
+ }\r
+\r
+ /* Concat the two Unicode strings */\r
+ w = _PyUnicode_New(u->length + v->length);\r
+ if (w == NULL)\r
+ goto onError;\r
+ Py_UNICODE_COPY(w->str, u->str, u->length);\r
+ Py_UNICODE_COPY(w->str + u->length, v->str, v->length);\r
+\r
+ Py_DECREF(u);\r
+ Py_DECREF(v);\r
+ return (PyObject *)w;\r
+\r
+ onError:\r
+ Py_XDECREF(u);\r
+ Py_XDECREF(v);\r
+ return NULL;\r
+}\r
+\r
+PyDoc_STRVAR(count__doc__,\r
+ "S.count(sub[, start[, end]]) -> int\n\\r
+\n\\r
+Return the number of non-overlapping occurrences of substring sub in\n\\r
+Unicode string S[start:end]. Optional arguments start and end are\n\\r
+interpreted as in slice notation.");\r
+\r
+static PyObject *\r
+unicode_count(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ PyUnicodeObject *substring;\r
+ Py_ssize_t start = 0;\r
+ Py_ssize_t end = PY_SSIZE_T_MAX;\r
+ PyObject *result;\r
+\r
+ if (!stringlib_parse_args_finds_unicode("count", args, &substring,\r
+ &start, &end))\r
+ return NULL;\r
+\r
+ ADJUST_INDICES(start, end, self->length);\r
+ result = PyInt_FromSsize_t(\r
+ stringlib_count(self->str + start, end - start,\r
+ substring->str, substring->length,\r
+ PY_SSIZE_T_MAX)\r
+ );\r
+\r
+ Py_DECREF(substring);\r
+\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(encode__doc__,\r
+ "S.encode([encoding[,errors]]) -> string or unicode\n\\r
+\n\\r
+Encodes S using the codec registered for encoding. encoding defaults\n\\r
+to the default encoding. errors may be given to set a different error\n\\r
+handling scheme. Default is 'strict' meaning that encoding errors raise\n\\r
+a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and\n\\r
+'xmlcharrefreplace' as well as any other name registered with\n\\r
+codecs.register_error that can handle UnicodeEncodeErrors.");\r
+\r
+static PyObject *\r
+unicode_encode(PyUnicodeObject *self, PyObject *args, PyObject *kwargs)\r
+{\r
+ static char *kwlist[] = {"encoding", "errors", 0};\r
+ char *encoding = NULL;\r
+ char *errors = NULL;\r
+ PyObject *v;\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:encode",\r
+ kwlist, &encoding, &errors))\r
+ return NULL;\r
+ v = PyUnicode_AsEncodedObject((PyObject *)self, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (!PyString_Check(v) && !PyUnicode_Check(v)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "encoder did not return a string/unicode object "\r
+ "(type=%.400s)",\r
+ Py_TYPE(v)->tp_name);\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+PyDoc_STRVAR(decode__doc__,\r
+ "S.decode([encoding[,errors]]) -> string or unicode\n\\r
+\n\\r
+Decodes S using the codec registered for encoding. encoding defaults\n\\r
+to the default encoding. errors may be given to set a different error\n\\r
+handling scheme. Default is 'strict' meaning that encoding errors raise\n\\r
+a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'\n\\r
+as well as any other name registered with codecs.register_error that is\n\\r
+able to handle UnicodeDecodeErrors.");\r
+\r
+static PyObject *\r
+unicode_decode(PyUnicodeObject *self, PyObject *args, PyObject *kwargs)\r
+{\r
+ static char *kwlist[] = {"encoding", "errors", 0};\r
+ char *encoding = NULL;\r
+ char *errors = NULL;\r
+ PyObject *v;\r
+\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode",\r
+ kwlist, &encoding, &errors))\r
+ return NULL;\r
+ v = PyUnicode_AsDecodedObject((PyObject *)self, encoding, errors);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (!PyString_Check(v) && !PyUnicode_Check(v)) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "decoder did not return a string/unicode object "\r
+ "(type=%.400s)",\r
+ Py_TYPE(v)->tp_name);\r
+ Py_DECREF(v);\r
+ return NULL;\r
+ }\r
+ return v;\r
+\r
+ onError:\r
+ return NULL;\r
+}\r
+\r
+PyDoc_STRVAR(expandtabs__doc__,\r
+ "S.expandtabs([tabsize]) -> unicode\n\\r
+\n\\r
+Return a copy of S where all tab characters are expanded using spaces.\n\\r
+If tabsize is not given, a tab size of 8 characters is assumed.");\r
+\r
+static PyObject*\r
+unicode_expandtabs(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ Py_UNICODE *e;\r
+ Py_UNICODE *p;\r
+ Py_UNICODE *q;\r
+ Py_UNICODE *qe;\r
+ Py_ssize_t i, j, incr;\r
+ PyUnicodeObject *u;\r
+ int tabsize = 8;\r
+\r
+ if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))\r
+ return NULL;\r
+\r
+ /* First pass: determine size of output string */\r
+ i = 0; /* chars up to and including most recent \n or \r */\r
+ j = 0; /* chars since most recent \n or \r (use in tab calculations) */\r
+ e = self->str + self->length; /* end of input */\r
+ for (p = self->str; p < e; p++)\r
+ if (*p == '\t') {\r
+ if (tabsize > 0) {\r
+ incr = tabsize - (j % tabsize); /* cannot overflow */\r
+ if (j > PY_SSIZE_T_MAX - incr)\r
+ goto overflow1;\r
+ j += incr;\r
+ }\r
+ }\r
+ else {\r
+ if (j > PY_SSIZE_T_MAX - 1)\r
+ goto overflow1;\r
+ j++;\r
+ if (*p == '\n' || *p == '\r') {\r
+ if (i > PY_SSIZE_T_MAX - j)\r
+ goto overflow1;\r
+ i += j;\r
+ j = 0;\r
+ }\r
+ }\r
+\r
+ if (i > PY_SSIZE_T_MAX - j)\r
+ goto overflow1;\r
+\r
+ /* Second pass: create output string and fill it */\r
+ u = _PyUnicode_New(i + j);\r
+ if (!u)\r
+ return NULL;\r
+\r
+ j = 0; /* same as in first pass */\r
+ q = u->str; /* next output char */\r
+ qe = u->str + u->length; /* end of output */\r
+\r
+ for (p = self->str; p < e; p++)\r
+ if (*p == '\t') {\r
+ if (tabsize > 0) {\r
+ i = tabsize - (j % tabsize);\r
+ j += i;\r
+ while (i--) {\r
+ if (q >= qe)\r
+ goto overflow2;\r
+ *q++ = ' ';\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ if (q >= qe)\r
+ goto overflow2;\r
+ *q++ = *p;\r
+ j++;\r
+ if (*p == '\n' || *p == '\r')\r
+ j = 0;\r
+ }\r
+\r
+ return (PyObject*) u;\r
+\r
+ overflow2:\r
+ Py_DECREF(u);\r
+ overflow1:\r
+ PyErr_SetString(PyExc_OverflowError, "new string is too long");\r
+ return NULL;\r
+}\r
+\r
+PyDoc_STRVAR(find__doc__,\r
+ "S.find(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Return the lowest index in S where substring sub is found,\n\\r
+such that sub is contained within S[start:end]. Optional\n\\r
+arguments start and end are interpreted as in slice notation.\n\\r
+\n\\r
+Return -1 on failure.");\r
+\r
+static PyObject *\r
+unicode_find(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ PyUnicodeObject *substring;\r
+ Py_ssize_t start;\r
+ Py_ssize_t end;\r
+ Py_ssize_t result;\r
+\r
+ if (!stringlib_parse_args_finds_unicode("find", args, &substring,\r
+ &start, &end))\r
+ return NULL;\r
+\r
+ result = stringlib_find_slice(\r
+ PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),\r
+ PyUnicode_AS_UNICODE(substring), PyUnicode_GET_SIZE(substring),\r
+ start, end\r
+ );\r
+\r
+ Py_DECREF(substring);\r
+\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+static PyObject *\r
+unicode_getitem(PyUnicodeObject *self, Py_ssize_t index)\r
+{\r
+ if (index < 0 || index >= self->length) {\r
+ PyErr_SetString(PyExc_IndexError, "string index out of range");\r
+ return NULL;\r
+ }\r
+\r
+ return (PyObject*) PyUnicode_FromUnicode(&self->str[index], 1);\r
+}\r
+\r
+static long\r
+unicode_hash(PyUnicodeObject *self)\r
+{\r
+ /* Since Unicode objects compare equal to their ASCII string\r
+ counterparts, they should use the individual character values\r
+ as basis for their hash value. This is needed to assure that\r
+ strings and Unicode objects behave in the same way as\r
+ dictionary keys. */\r
+\r
+ register Py_ssize_t len;\r
+ register Py_UNICODE *p;\r
+ register long x;\r
+\r
+#ifdef Py_DEBUG\r
+ assert(_Py_HashSecret_Initialized);\r
+#endif\r
+ if (self->hash != -1)\r
+ return self->hash;\r
+ len = PyUnicode_GET_SIZE(self);\r
+ /*\r
+ We make the hash of the empty string be 0, rather than using\r
+ (prefix ^ suffix), since this slightly obfuscates the hash secret\r
+ */\r
+ if (len == 0) {\r
+ self->hash = 0;\r
+ return 0;\r
+ }\r
+ p = PyUnicode_AS_UNICODE(self);\r
+ x = _Py_HashSecret.prefix;\r
+ x ^= *p << 7;\r
+ while (--len >= 0)\r
+ x = (1000003*x) ^ *p++;\r
+ x ^= PyUnicode_GET_SIZE(self);\r
+ x ^= _Py_HashSecret.suffix;\r
+ if (x == -1)\r
+ x = -2;\r
+ self->hash = x;\r
+ return x;\r
+}\r
+\r
+PyDoc_STRVAR(index__doc__,\r
+ "S.index(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Like S.find() but raise ValueError when the substring is not found.");\r
+\r
+static PyObject *\r
+unicode_index(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t result;\r
+ PyUnicodeObject *substring;\r
+ Py_ssize_t start;\r
+ Py_ssize_t end;\r
+\r
+ if (!stringlib_parse_args_finds_unicode("index", args, &substring,\r
+ &start, &end))\r
+ return NULL;\r
+\r
+ result = stringlib_find_slice(\r
+ PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),\r
+ PyUnicode_AS_UNICODE(substring), PyUnicode_GET_SIZE(substring),\r
+ start, end\r
+ );\r
+\r
+ Py_DECREF(substring);\r
+\r
+ if (result < 0) {\r
+ PyErr_SetString(PyExc_ValueError, "substring not found");\r
+ return NULL;\r
+ }\r
+\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+PyDoc_STRVAR(islower__doc__,\r
+ "S.islower() -> bool\n\\r
+\n\\r
+Return True if all cased characters in S are lowercase and there is\n\\r
+at least one cased character in S, False otherwise.");\r
+\r
+static PyObject*\r
+unicode_islower(PyUnicodeObject *self)\r
+{\r
+ register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register const Py_UNICODE *e;\r
+ int cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1)\r
+ return PyBool_FromLong(Py_UNICODE_ISLOWER(*p));\r
+\r
+ /* Special case for empty strings */\r
+ if (PyUnicode_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ cased = 0;\r
+ for (; p < e; p++) {\r
+ register const Py_UNICODE ch = *p;\r
+\r
+ if (Py_UNICODE_ISUPPER(ch) || Py_UNICODE_ISTITLE(ch))\r
+ return PyBool_FromLong(0);\r
+ else if (!cased && Py_UNICODE_ISLOWER(ch))\r
+ cased = 1;\r
+ }\r
+ return PyBool_FromLong(cased);\r
+}\r
+\r
+PyDoc_STRVAR(isupper__doc__,\r
+ "S.isupper() -> bool\n\\r
+\n\\r
+Return True if all cased characters in S are uppercase and there is\n\\r
+at least one cased character in S, False otherwise.");\r
+\r
+static PyObject*\r
+unicode_isupper(PyUnicodeObject *self)\r
+{\r
+ register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register const Py_UNICODE *e;\r
+ int cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1)\r
+ return PyBool_FromLong(Py_UNICODE_ISUPPER(*p) != 0);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyUnicode_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ cased = 0;\r
+ for (; p < e; p++) {\r
+ register const Py_UNICODE ch = *p;\r
+\r
+ if (Py_UNICODE_ISLOWER(ch) || Py_UNICODE_ISTITLE(ch))\r
+ return PyBool_FromLong(0);\r
+ else if (!cased && Py_UNICODE_ISUPPER(ch))\r
+ cased = 1;\r
+ }\r
+ return PyBool_FromLong(cased);\r
+}\r
+\r
+PyDoc_STRVAR(istitle__doc__,\r
+ "S.istitle() -> bool\n\\r
+\n\\r
+Return True if S is a titlecased string and there is at least one\n\\r
+character in S, i.e. upper- and titlecase characters may only\n\\r
+follow uncased characters and lowercase characters only cased ones.\n\\r
+Return False otherwise.");\r
+\r
+static PyObject*\r
+unicode_istitle(PyUnicodeObject *self)\r
+{\r
+ register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register const Py_UNICODE *e;\r
+ int cased, previous_is_cased;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1)\r
+ return PyBool_FromLong((Py_UNICODE_ISTITLE(*p) != 0) ||\r
+ (Py_UNICODE_ISUPPER(*p) != 0));\r
+\r
+ /* Special case for empty strings */\r
+ if (PyUnicode_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ cased = 0;\r
+ previous_is_cased = 0;\r
+ for (; p < e; p++) {\r
+ register const Py_UNICODE ch = *p;\r
+\r
+ if (Py_UNICODE_ISUPPER(ch) || Py_UNICODE_ISTITLE(ch)) {\r
+ if (previous_is_cased)\r
+ return PyBool_FromLong(0);\r
+ previous_is_cased = 1;\r
+ cased = 1;\r
+ }\r
+ else if (Py_UNICODE_ISLOWER(ch)) {\r
+ if (!previous_is_cased)\r
+ return PyBool_FromLong(0);\r
+ previous_is_cased = 1;\r
+ cased = 1;\r
+ }\r
+ else\r
+ previous_is_cased = 0;\r
+ }\r
+ return PyBool_FromLong(cased);\r
+}\r
+\r
+PyDoc_STRVAR(isspace__doc__,\r
+ "S.isspace() -> bool\n\\r
+\n\\r
+Return True if all characters in S are whitespace\n\\r
+and there is at least one character in S, False otherwise.");\r
+\r
+static PyObject*\r
+unicode_isspace(PyUnicodeObject *self)\r
+{\r
+ register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register const Py_UNICODE *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1 &&\r
+ Py_UNICODE_ISSPACE(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyUnicode_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!Py_UNICODE_ISSPACE(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+PyDoc_STRVAR(isalpha__doc__,\r
+ "S.isalpha() -> bool\n\\r
+\n\\r
+Return True if all characters in S are alphabetic\n\\r
+and there is at least one character in S, False otherwise.");\r
+\r
+static PyObject*\r
+unicode_isalpha(PyUnicodeObject *self)\r
+{\r
+ register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register const Py_UNICODE *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1 &&\r
+ Py_UNICODE_ISALPHA(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyUnicode_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!Py_UNICODE_ISALPHA(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+PyDoc_STRVAR(isalnum__doc__,\r
+ "S.isalnum() -> bool\n\\r
+\n\\r
+Return True if all characters in S are alphanumeric\n\\r
+and there is at least one character in S, False otherwise.");\r
+\r
+static PyObject*\r
+unicode_isalnum(PyUnicodeObject *self)\r
+{\r
+ register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register const Py_UNICODE *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1 &&\r
+ Py_UNICODE_ISALNUM(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyUnicode_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!Py_UNICODE_ISALNUM(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+PyDoc_STRVAR(isdecimal__doc__,\r
+ "S.isdecimal() -> bool\n\\r
+\n\\r
+Return True if there are only decimal characters in S,\n\\r
+False otherwise.");\r
+\r
+static PyObject*\r
+unicode_isdecimal(PyUnicodeObject *self)\r
+{\r
+ register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register const Py_UNICODE *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1 &&\r
+ Py_UNICODE_ISDECIMAL(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyUnicode_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!Py_UNICODE_ISDECIMAL(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+PyDoc_STRVAR(isdigit__doc__,\r
+ "S.isdigit() -> bool\n\\r
+\n\\r
+Return True if all characters in S are digits\n\\r
+and there is at least one character in S, False otherwise.");\r
+\r
+static PyObject*\r
+unicode_isdigit(PyUnicodeObject *self)\r
+{\r
+ register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register const Py_UNICODE *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1 &&\r
+ Py_UNICODE_ISDIGIT(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyUnicode_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!Py_UNICODE_ISDIGIT(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+PyDoc_STRVAR(isnumeric__doc__,\r
+ "S.isnumeric() -> bool\n\\r
+\n\\r
+Return True if there are only numeric characters in S,\n\\r
+False otherwise.");\r
+\r
+static PyObject*\r
+unicode_isnumeric(PyUnicodeObject *self)\r
+{\r
+ register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);\r
+ register const Py_UNICODE *e;\r
+\r
+ /* Shortcut for single character strings */\r
+ if (PyUnicode_GET_SIZE(self) == 1 &&\r
+ Py_UNICODE_ISNUMERIC(*p))\r
+ return PyBool_FromLong(1);\r
+\r
+ /* Special case for empty strings */\r
+ if (PyUnicode_GET_SIZE(self) == 0)\r
+ return PyBool_FromLong(0);\r
+\r
+ e = p + PyUnicode_GET_SIZE(self);\r
+ for (; p < e; p++) {\r
+ if (!Py_UNICODE_ISNUMERIC(*p))\r
+ return PyBool_FromLong(0);\r
+ }\r
+ return PyBool_FromLong(1);\r
+}\r
+\r
+PyDoc_STRVAR(join__doc__,\r
+ "S.join(iterable) -> unicode\n\\r
+\n\\r
+Return a string which is the concatenation of the strings in the\n\\r
+iterable. The separator between elements is S.");\r
+\r
+static PyObject*\r
+unicode_join(PyObject *self, PyObject *data)\r
+{\r
+ return PyUnicode_Join(self, data);\r
+}\r
+\r
+static Py_ssize_t\r
+unicode_length(PyUnicodeObject *self)\r
+{\r
+ return self->length;\r
+}\r
+\r
+PyDoc_STRVAR(ljust__doc__,\r
+ "S.ljust(width[, fillchar]) -> int\n\\r
+\n\\r
+Return S left-justified in a Unicode string of length width. Padding is\n\\r
+done using the specified fill character (default is a space).");\r
+\r
+static PyObject *\r
+unicode_ljust(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t width;\r
+ Py_UNICODE fillchar = ' ';\r
+\r
+ if (!PyArg_ParseTuple(args, "n|O&:ljust", &width, convert_uc, &fillchar))\r
+ return NULL;\r
+\r
+ if (self->length >= width && PyUnicode_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+ }\r
+\r
+ return (PyObject*) pad(self, 0, width - self->length, fillchar);\r
+}\r
+\r
+PyDoc_STRVAR(lower__doc__,\r
+ "S.lower() -> unicode\n\\r
+\n\\r
+Return a copy of the string S converted to lowercase.");\r
+\r
+static PyObject*\r
+unicode_lower(PyUnicodeObject *self)\r
+{\r
+ return fixup(self, fixlower);\r
+}\r
+\r
+#define LEFTSTRIP 0\r
+#define RIGHTSTRIP 1\r
+#define BOTHSTRIP 2\r
+\r
+/* Arrays indexed by above */\r
+static const char *stripformat[] = {"|O:lstrip", "|O:rstrip", "|O:strip"};\r
+\r
+#define STRIPNAME(i) (stripformat[i]+3)\r
+\r
+/* externally visible for str.strip(unicode) */\r
+PyObject *\r
+_PyUnicode_XStrip(PyUnicodeObject *self, int striptype, PyObject *sepobj)\r
+{\r
+ Py_UNICODE *s = PyUnicode_AS_UNICODE(self);\r
+ Py_ssize_t len = PyUnicode_GET_SIZE(self);\r
+ Py_UNICODE *sep = PyUnicode_AS_UNICODE(sepobj);\r
+ Py_ssize_t seplen = PyUnicode_GET_SIZE(sepobj);\r
+ Py_ssize_t i, j;\r
+\r
+ BLOOM_MASK sepmask = make_bloom_mask(sep, seplen);\r
+\r
+ i = 0;\r
+ if (striptype != RIGHTSTRIP) {\r
+ while (i < len && BLOOM_MEMBER(sepmask, s[i], sep, seplen)) {\r
+ i++;\r
+ }\r
+ }\r
+\r
+ j = len;\r
+ if (striptype != LEFTSTRIP) {\r
+ do {\r
+ j--;\r
+ } while (j >= i && BLOOM_MEMBER(sepmask, s[j], sep, seplen));\r
+ j++;\r
+ }\r
+\r
+ if (i == 0 && j == len && PyUnicode_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*)self;\r
+ }\r
+ else\r
+ return PyUnicode_FromUnicode(s+i, j-i);\r
+}\r
+\r
+\r
+static PyObject *\r
+do_strip(PyUnicodeObject *self, int striptype)\r
+{\r
+ Py_UNICODE *s = PyUnicode_AS_UNICODE(self);\r
+ Py_ssize_t len = PyUnicode_GET_SIZE(self), i, j;\r
+\r
+ i = 0;\r
+ if (striptype != RIGHTSTRIP) {\r
+ while (i < len && Py_UNICODE_ISSPACE(s[i])) {\r
+ i++;\r
+ }\r
+ }\r
+\r
+ j = len;\r
+ if (striptype != LEFTSTRIP) {\r
+ do {\r
+ j--;\r
+ } while (j >= i && Py_UNICODE_ISSPACE(s[j]));\r
+ j++;\r
+ }\r
+\r
+ if (i == 0 && j == len && PyUnicode_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*)self;\r
+ }\r
+ else\r
+ return PyUnicode_FromUnicode(s+i, j-i);\r
+}\r
+\r
+\r
+static PyObject *\r
+do_argstrip(PyUnicodeObject *self, int striptype, PyObject *args)\r
+{\r
+ PyObject *sep = NULL;\r
+\r
+ if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sep))\r
+ return NULL;\r
+\r
+ if (sep != NULL && sep != Py_None) {\r
+ if (PyUnicode_Check(sep))\r
+ return _PyUnicode_XStrip(self, striptype, sep);\r
+ else if (PyString_Check(sep)) {\r
+ PyObject *res;\r
+ sep = PyUnicode_FromObject(sep);\r
+ if (sep==NULL)\r
+ return NULL;\r
+ res = _PyUnicode_XStrip(self, striptype, sep);\r
+ Py_DECREF(sep);\r
+ return res;\r
+ }\r
+ else {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%s arg must be None, unicode or str",\r
+ STRIPNAME(striptype));\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ return do_strip(self, striptype);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(strip__doc__,\r
+ "S.strip([chars]) -> unicode\n\\r
+\n\\r
+Return a copy of the string S with leading and trailing\n\\r
+whitespace removed.\n\\r
+If chars is given and not None, remove characters in chars instead.\n\\r
+If chars is a str, it will be converted to unicode before stripping");\r
+\r
+static PyObject *\r
+unicode_strip(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ if (PyTuple_GET_SIZE(args) == 0)\r
+ return do_strip(self, BOTHSTRIP); /* Common case */\r
+ else\r
+ return do_argstrip(self, BOTHSTRIP, args);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(lstrip__doc__,\r
+ "S.lstrip([chars]) -> unicode\n\\r
+\n\\r
+Return a copy of the string S with leading whitespace removed.\n\\r
+If chars is given and not None, remove characters in chars instead.\n\\r
+If chars is a str, it will be converted to unicode before stripping");\r
+\r
+static PyObject *\r
+unicode_lstrip(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ if (PyTuple_GET_SIZE(args) == 0)\r
+ return do_strip(self, LEFTSTRIP); /* Common case */\r
+ else\r
+ return do_argstrip(self, LEFTSTRIP, args);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(rstrip__doc__,\r
+ "S.rstrip([chars]) -> unicode\n\\r
+\n\\r
+Return a copy of the string S with trailing whitespace removed.\n\\r
+If chars is given and not None, remove characters in chars instead.\n\\r
+If chars is a str, it will be converted to unicode before stripping");\r
+\r
+static PyObject *\r
+unicode_rstrip(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ if (PyTuple_GET_SIZE(args) == 0)\r
+ return do_strip(self, RIGHTSTRIP); /* Common case */\r
+ else\r
+ return do_argstrip(self, RIGHTSTRIP, args);\r
+}\r
+\r
+\r
+static PyObject*\r
+unicode_repeat(PyUnicodeObject *str, Py_ssize_t len)\r
+{\r
+ PyUnicodeObject *u;\r
+ Py_UNICODE *p;\r
+ Py_ssize_t nchars;\r
+ size_t nbytes;\r
+\r
+ if (len < 0)\r
+ len = 0;\r
+\r
+ if (len == 1 && PyUnicode_CheckExact(str)) {\r
+ /* no repeat, return original string */\r
+ Py_INCREF(str);\r
+ return (PyObject*) str;\r
+ }\r
+\r
+ /* ensure # of chars needed doesn't overflow int and # of bytes\r
+ * needed doesn't overflow size_t\r
+ */\r
+ nchars = len * str->length;\r
+ if (len && nchars / len != str->length) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "repeated string is too long");\r
+ return NULL;\r
+ }\r
+ nbytes = (nchars + 1) * sizeof(Py_UNICODE);\r
+ if (nbytes / sizeof(Py_UNICODE) != (size_t)(nchars + 1)) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "repeated string is too long");\r
+ return NULL;\r
+ }\r
+ u = _PyUnicode_New(nchars);\r
+ if (!u)\r
+ return NULL;\r
+\r
+ p = u->str;\r
+\r
+ if (str->length == 1 && len > 0) {\r
+ Py_UNICODE_FILL(p, str->str[0], len);\r
+ } else {\r
+ Py_ssize_t done = 0; /* number of characters copied this far */\r
+ if (done < nchars) {\r
+ Py_UNICODE_COPY(p, str->str, str->length);\r
+ done = str->length;\r
+ }\r
+ while (done < nchars) {\r
+ Py_ssize_t n = (done <= nchars-done) ? done : nchars-done;\r
+ Py_UNICODE_COPY(p+done, p, n);\r
+ done += n;\r
+ }\r
+ }\r
+\r
+ return (PyObject*) u;\r
+}\r
+\r
+PyObject *PyUnicode_Replace(PyObject *obj,\r
+ PyObject *subobj,\r
+ PyObject *replobj,\r
+ Py_ssize_t maxcount)\r
+{\r
+ PyObject *self;\r
+ PyObject *str1;\r
+ PyObject *str2;\r
+ PyObject *result;\r
+\r
+ self = PyUnicode_FromObject(obj);\r
+ if (self == NULL)\r
+ return NULL;\r
+ str1 = PyUnicode_FromObject(subobj);\r
+ if (str1 == NULL) {\r
+ Py_DECREF(self);\r
+ return NULL;\r
+ }\r
+ str2 = PyUnicode_FromObject(replobj);\r
+ if (str2 == NULL) {\r
+ Py_DECREF(self);\r
+ Py_DECREF(str1);\r
+ return NULL;\r
+ }\r
+ result = replace((PyUnicodeObject *)self,\r
+ (PyUnicodeObject *)str1,\r
+ (PyUnicodeObject *)str2,\r
+ maxcount);\r
+ Py_DECREF(self);\r
+ Py_DECREF(str1);\r
+ Py_DECREF(str2);\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(replace__doc__,\r
+ "S.replace(old, new[, count]) -> unicode\n\\r
+\n\\r
+Return a copy of S with all occurrences of substring\n\\r
+old replaced by new. If the optional argument count is\n\\r
+given, only the first count occurrences are replaced.");\r
+\r
+static PyObject*\r
+unicode_replace(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ PyUnicodeObject *str1;\r
+ PyUnicodeObject *str2;\r
+ Py_ssize_t maxcount = -1;\r
+ PyObject *result;\r
+\r
+ if (!PyArg_ParseTuple(args, "OO|n:replace", &str1, &str2, &maxcount))\r
+ return NULL;\r
+ str1 = (PyUnicodeObject *)PyUnicode_FromObject((PyObject *)str1);\r
+ if (str1 == NULL)\r
+ return NULL;\r
+ str2 = (PyUnicodeObject *)PyUnicode_FromObject((PyObject *)str2);\r
+ if (str2 == NULL) {\r
+ Py_DECREF(str1);\r
+ return NULL;\r
+ }\r
+\r
+ result = replace(self, str1, str2, maxcount);\r
+\r
+ Py_DECREF(str1);\r
+ Py_DECREF(str2);\r
+ return result;\r
+}\r
+\r
+static\r
+PyObject *unicode_repr(PyObject *unicode)\r
+{\r
+ return unicodeescape_string(PyUnicode_AS_UNICODE(unicode),\r
+ PyUnicode_GET_SIZE(unicode),\r
+ 1);\r
+}\r
+\r
+PyDoc_STRVAR(rfind__doc__,\r
+ "S.rfind(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Return the highest index in S where substring sub is found,\n\\r
+such that sub is contained within S[start:end]. Optional\n\\r
+arguments start and end are interpreted as in slice notation.\n\\r
+\n\\r
+Return -1 on failure.");\r
+\r
+static PyObject *\r
+unicode_rfind(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ PyUnicodeObject *substring;\r
+ Py_ssize_t start;\r
+ Py_ssize_t end;\r
+ Py_ssize_t result;\r
+\r
+ if (!stringlib_parse_args_finds_unicode("rfind", args, &substring,\r
+ &start, &end))\r
+ return NULL;\r
+\r
+ result = stringlib_rfind_slice(\r
+ PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),\r
+ PyUnicode_AS_UNICODE(substring), PyUnicode_GET_SIZE(substring),\r
+ start, end\r
+ );\r
+\r
+ Py_DECREF(substring);\r
+\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+PyDoc_STRVAR(rindex__doc__,\r
+ "S.rindex(sub [,start [,end]]) -> int\n\\r
+\n\\r
+Like S.rfind() but raise ValueError when the substring is not found.");\r
+\r
+static PyObject *\r
+unicode_rindex(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ PyUnicodeObject *substring;\r
+ Py_ssize_t start;\r
+ Py_ssize_t end;\r
+ Py_ssize_t result;\r
+\r
+ if (!stringlib_parse_args_finds_unicode("rindex", args, &substring,\r
+ &start, &end))\r
+ return NULL;\r
+\r
+ result = stringlib_rfind_slice(\r
+ PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),\r
+ PyUnicode_AS_UNICODE(substring), PyUnicode_GET_SIZE(substring),\r
+ start, end\r
+ );\r
+\r
+ Py_DECREF(substring);\r
+\r
+ if (result < 0) {\r
+ PyErr_SetString(PyExc_ValueError, "substring not found");\r
+ return NULL;\r
+ }\r
+ return PyInt_FromSsize_t(result);\r
+}\r
+\r
+PyDoc_STRVAR(rjust__doc__,\r
+ "S.rjust(width[, fillchar]) -> unicode\n\\r
+\n\\r
+Return S right-justified in a Unicode string of length width. Padding is\n\\r
+done using the specified fill character (default is a space).");\r
+\r
+static PyObject *\r
+unicode_rjust(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t width;\r
+ Py_UNICODE fillchar = ' ';\r
+\r
+ if (!PyArg_ParseTuple(args, "n|O&:rjust", &width, convert_uc, &fillchar))\r
+ return NULL;\r
+\r
+ if (self->length >= width && PyUnicode_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+ }\r
+\r
+ return (PyObject*) pad(self, width - self->length, 0, fillchar);\r
+}\r
+\r
+static PyObject*\r
+unicode_slice(PyUnicodeObject *self, Py_ssize_t start, Py_ssize_t end)\r
+{\r
+ /* standard clamping */\r
+ if (start < 0)\r
+ start = 0;\r
+ if (end < 0)\r
+ end = 0;\r
+ if (end > self->length)\r
+ end = self->length;\r
+ if (start == 0 && end == self->length && PyUnicode_CheckExact(self)) {\r
+ /* full slice, return original string */\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+ }\r
+ if (start > end)\r
+ start = end;\r
+ /* copy slice */\r
+ return (PyObject*) PyUnicode_FromUnicode(self->str + start,\r
+ end - start);\r
+}\r
+\r
+PyObject *PyUnicode_Split(PyObject *s,\r
+ PyObject *sep,\r
+ Py_ssize_t maxsplit)\r
+{\r
+ PyObject *result;\r
+\r
+ s = PyUnicode_FromObject(s);\r
+ if (s == NULL)\r
+ return NULL;\r
+ if (sep != NULL) {\r
+ sep = PyUnicode_FromObject(sep);\r
+ if (sep == NULL) {\r
+ Py_DECREF(s);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ result = split((PyUnicodeObject *)s, (PyUnicodeObject *)sep, maxsplit);\r
+\r
+ Py_DECREF(s);\r
+ Py_XDECREF(sep);\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(split__doc__,\r
+ "S.split([sep [,maxsplit]]) -> list of strings\n\\r
+\n\\r
+Return a list of the words in S, using sep as the\n\\r
+delimiter string. If maxsplit is given, at most maxsplit\n\\r
+splits are done. If sep is not specified or is None, any\n\\r
+whitespace string is a separator and empty strings are\n\\r
+removed from the result.");\r
+\r
+static PyObject*\r
+unicode_split(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ PyObject *substring = Py_None;\r
+ Py_ssize_t maxcount = -1;\r
+\r
+ if (!PyArg_ParseTuple(args, "|On:split", &substring, &maxcount))\r
+ return NULL;\r
+\r
+ if (substring == Py_None)\r
+ return split(self, NULL, maxcount);\r
+ else if (PyUnicode_Check(substring))\r
+ return split(self, (PyUnicodeObject *)substring, maxcount);\r
+ else\r
+ return PyUnicode_Split((PyObject *)self, substring, maxcount);\r
+}\r
+\r
+PyObject *\r
+PyUnicode_Partition(PyObject *str_in, PyObject *sep_in)\r
+{\r
+ PyObject* str_obj;\r
+ PyObject* sep_obj;\r
+ PyObject* out;\r
+\r
+ str_obj = PyUnicode_FromObject(str_in);\r
+ if (!str_obj)\r
+ return NULL;\r
+ sep_obj = PyUnicode_FromObject(sep_in);\r
+ if (!sep_obj) {\r
+ Py_DECREF(str_obj);\r
+ return NULL;\r
+ }\r
+\r
+ out = stringlib_partition(\r
+ str_obj, PyUnicode_AS_UNICODE(str_obj), PyUnicode_GET_SIZE(str_obj),\r
+ sep_obj, PyUnicode_AS_UNICODE(sep_obj), PyUnicode_GET_SIZE(sep_obj)\r
+ );\r
+\r
+ Py_DECREF(sep_obj);\r
+ Py_DECREF(str_obj);\r
+\r
+ return out;\r
+}\r
+\r
+\r
+PyObject *\r
+PyUnicode_RPartition(PyObject *str_in, PyObject *sep_in)\r
+{\r
+ PyObject* str_obj;\r
+ PyObject* sep_obj;\r
+ PyObject* out;\r
+\r
+ str_obj = PyUnicode_FromObject(str_in);\r
+ if (!str_obj)\r
+ return NULL;\r
+ sep_obj = PyUnicode_FromObject(sep_in);\r
+ if (!sep_obj) {\r
+ Py_DECREF(str_obj);\r
+ return NULL;\r
+ }\r
+\r
+ out = stringlib_rpartition(\r
+ str_obj, PyUnicode_AS_UNICODE(str_obj), PyUnicode_GET_SIZE(str_obj),\r
+ sep_obj, PyUnicode_AS_UNICODE(sep_obj), PyUnicode_GET_SIZE(sep_obj)\r
+ );\r
+\r
+ Py_DECREF(sep_obj);\r
+ Py_DECREF(str_obj);\r
+\r
+ return out;\r
+}\r
+\r
+PyDoc_STRVAR(partition__doc__,\r
+ "S.partition(sep) -> (head, sep, tail)\n\\r
+\n\\r
+Search for the separator sep in S, and return the part before it,\n\\r
+the separator itself, and the part after it. If the separator is not\n\\r
+found, return S and two empty strings.");\r
+\r
+static PyObject*\r
+unicode_partition(PyUnicodeObject *self, PyObject *separator)\r
+{\r
+ return PyUnicode_Partition((PyObject *)self, separator);\r
+}\r
+\r
+PyDoc_STRVAR(rpartition__doc__,\r
+ "S.rpartition(sep) -> (head, sep, tail)\n\\r
+\n\\r
+Search for the separator sep in S, starting at the end of S, and return\n\\r
+the part before it, the separator itself, and the part after it. If the\n\\r
+separator is not found, return two empty strings and S.");\r
+\r
+static PyObject*\r
+unicode_rpartition(PyUnicodeObject *self, PyObject *separator)\r
+{\r
+ return PyUnicode_RPartition((PyObject *)self, separator);\r
+}\r
+\r
+PyObject *PyUnicode_RSplit(PyObject *s,\r
+ PyObject *sep,\r
+ Py_ssize_t maxsplit)\r
+{\r
+ PyObject *result;\r
+\r
+ s = PyUnicode_FromObject(s);\r
+ if (s == NULL)\r
+ return NULL;\r
+ if (sep != NULL) {\r
+ sep = PyUnicode_FromObject(sep);\r
+ if (sep == NULL) {\r
+ Py_DECREF(s);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ result = rsplit((PyUnicodeObject *)s, (PyUnicodeObject *)sep, maxsplit);\r
+\r
+ Py_DECREF(s);\r
+ Py_XDECREF(sep);\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(rsplit__doc__,\r
+ "S.rsplit([sep [,maxsplit]]) -> list of strings\n\\r
+\n\\r
+Return a list of the words in S, using sep as the\n\\r
+delimiter string, starting at the end of the string and\n\\r
+working to the front. If maxsplit is given, at most maxsplit\n\\r
+splits are done. If sep is not specified, any whitespace string\n\\r
+is a separator.");\r
+\r
+static PyObject*\r
+unicode_rsplit(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ PyObject *substring = Py_None;\r
+ Py_ssize_t maxcount = -1;\r
+\r
+ if (!PyArg_ParseTuple(args, "|On:rsplit", &substring, &maxcount))\r
+ return NULL;\r
+\r
+ if (substring == Py_None)\r
+ return rsplit(self, NULL, maxcount);\r
+ else if (PyUnicode_Check(substring))\r
+ return rsplit(self, (PyUnicodeObject *)substring, maxcount);\r
+ else\r
+ return PyUnicode_RSplit((PyObject *)self, substring, maxcount);\r
+}\r
+\r
+PyDoc_STRVAR(splitlines__doc__,\r
+ "S.splitlines(keepends=False) -> list of strings\n\\r
+\n\\r
+Return a list of the lines in S, breaking at line boundaries.\n\\r
+Line breaks are not included in the resulting list unless keepends\n\\r
+is given and true.");\r
+\r
+static PyObject*\r
+unicode_splitlines(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ int keepends = 0;\r
+\r
+ if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends))\r
+ return NULL;\r
+\r
+ return PyUnicode_Splitlines((PyObject *)self, keepends);\r
+}\r
+\r
+static\r
+PyObject *unicode_str(PyUnicodeObject *self)\r
+{\r
+ return PyUnicode_AsEncodedString((PyObject *)self, NULL, NULL);\r
+}\r
+\r
+PyDoc_STRVAR(swapcase__doc__,\r
+ "S.swapcase() -> unicode\n\\r
+\n\\r
+Return a copy of S with uppercase characters converted to lowercase\n\\r
+and vice versa.");\r
+\r
+static PyObject*\r
+unicode_swapcase(PyUnicodeObject *self)\r
+{\r
+ return fixup(self, fixswapcase);\r
+}\r
+\r
+PyDoc_STRVAR(translate__doc__,\r
+ "S.translate(table) -> unicode\n\\r
+\n\\r
+Return a copy of the string S, where all characters have been mapped\n\\r
+through the given translation table, which must be a mapping of\n\\r
+Unicode ordinals to Unicode ordinals, Unicode strings or None.\n\\r
+Unmapped characters are left untouched. Characters mapped to None\n\\r
+are deleted.");\r
+\r
+static PyObject*\r
+unicode_translate(PyUnicodeObject *self, PyObject *table)\r
+{\r
+ return PyUnicode_TranslateCharmap(self->str,\r
+ self->length,\r
+ table,\r
+ "ignore");\r
+}\r
+\r
+PyDoc_STRVAR(upper__doc__,\r
+ "S.upper() -> unicode\n\\r
+\n\\r
+Return a copy of S converted to uppercase.");\r
+\r
+static PyObject*\r
+unicode_upper(PyUnicodeObject *self)\r
+{\r
+ return fixup(self, fixupper);\r
+}\r
+\r
+PyDoc_STRVAR(zfill__doc__,\r
+ "S.zfill(width) -> unicode\n\\r
+\n\\r
+Pad a numeric string S with zeros on the left, to fill a field\n\\r
+of the specified width. The string S is never truncated.");\r
+\r
+static PyObject *\r
+unicode_zfill(PyUnicodeObject *self, PyObject *args)\r
+{\r
+ Py_ssize_t fill;\r
+ PyUnicodeObject *u;\r
+\r
+ Py_ssize_t width;\r
+ if (!PyArg_ParseTuple(args, "n:zfill", &width))\r
+ return NULL;\r
+\r
+ if (self->length >= width) {\r
+ if (PyUnicode_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject*) self;\r
+ }\r
+ else\r
+ return PyUnicode_FromUnicode(\r
+ PyUnicode_AS_UNICODE(self),\r
+ PyUnicode_GET_SIZE(self)\r
+ );\r
+ }\r
+\r
+ fill = width - self->length;\r
+\r
+ u = pad(self, fill, 0, '0');\r
+\r
+ if (u == NULL)\r
+ return NULL;\r
+\r
+ if (u->str[fill] == '+' || u->str[fill] == '-') {\r
+ /* move sign to beginning of string */\r
+ u->str[0] = u->str[fill];\r
+ u->str[fill] = '0';\r
+ }\r
+\r
+ return (PyObject*) u;\r
+}\r
+\r
+#if 0\r
+static PyObject*\r
+free_listsize(PyUnicodeObject *self)\r
+{\r
+ return PyInt_FromLong(numfree);\r
+}\r
+#endif\r
+\r
+PyDoc_STRVAR(startswith__doc__,\r
+ "S.startswith(prefix[, start[, end]]) -> bool\n\\r
+\n\\r
+Return True if S starts with the specified prefix, False otherwise.\n\\r
+With optional start, test S beginning at that position.\n\\r
+With optional end, stop comparing S at that position.\n\\r
+prefix can also be a tuple of strings to try.");\r
+\r
+static PyObject *\r
+unicode_startswith(PyUnicodeObject *self,\r
+ PyObject *args)\r
+{\r
+ PyObject *subobj;\r
+ PyUnicodeObject *substring;\r
+ Py_ssize_t start = 0;\r
+ Py_ssize_t end = PY_SSIZE_T_MAX;\r
+ int result;\r
+\r
+ if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))\r
+ return NULL;\r
+ if (PyTuple_Check(subobj)) {\r
+ Py_ssize_t i;\r
+ for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {\r
+ substring = (PyUnicodeObject *)PyUnicode_FromObject(\r
+ PyTuple_GET_ITEM(subobj, i));\r
+ if (substring == NULL)\r
+ return NULL;\r
+ result = tailmatch(self, substring, start, end, -1);\r
+ Py_DECREF(substring);\r
+ if (result) {\r
+ Py_RETURN_TRUE;\r
+ }\r
+ }\r
+ /* nothing matched */\r
+ Py_RETURN_FALSE;\r
+ }\r
+ substring = (PyUnicodeObject *)PyUnicode_FromObject(subobj);\r
+ if (substring == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_TypeError))\r
+ PyErr_Format(PyExc_TypeError, "startswith first arg must be str, "\r
+ "unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name);\r
+ return NULL;\r
+ }\r
+ result = tailmatch(self, substring, start, end, -1);\r
+ Py_DECREF(substring);\r
+ return PyBool_FromLong(result);\r
+}\r
+\r
+\r
+PyDoc_STRVAR(endswith__doc__,\r
+ "S.endswith(suffix[, start[, end]]) -> bool\n\\r
+\n\\r
+Return True if S ends with the specified suffix, False otherwise.\n\\r
+With optional start, test S beginning at that position.\n\\r
+With optional end, stop comparing S at that position.\n\\r
+suffix can also be a tuple of strings to try.");\r
+\r
+static PyObject *\r
+unicode_endswith(PyUnicodeObject *self,\r
+ PyObject *args)\r
+{\r
+ PyObject *subobj;\r
+ PyUnicodeObject *substring;\r
+ Py_ssize_t start = 0;\r
+ Py_ssize_t end = PY_SSIZE_T_MAX;\r
+ int result;\r
+\r
+ if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))\r
+ return NULL;\r
+ if (PyTuple_Check(subobj)) {\r
+ Py_ssize_t i;\r
+ for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {\r
+ substring = (PyUnicodeObject *)PyUnicode_FromObject(\r
+ PyTuple_GET_ITEM(subobj, i));\r
+ if (substring == NULL)\r
+ return NULL;\r
+ result = tailmatch(self, substring, start, end, +1);\r
+ Py_DECREF(substring);\r
+ if (result) {\r
+ Py_RETURN_TRUE;\r
+ }\r
+ }\r
+ Py_RETURN_FALSE;\r
+ }\r
+ substring = (PyUnicodeObject *)PyUnicode_FromObject(subobj);\r
+ if (substring == NULL) {\r
+ if (PyErr_ExceptionMatches(PyExc_TypeError))\r
+ PyErr_Format(PyExc_TypeError, "endswith first arg must be str, "\r
+ "unicode, or tuple, not %s", Py_TYPE(subobj)->tp_name);\r
+ return NULL;\r
+ }\r
+ result = tailmatch(self, substring, start, end, +1);\r
+ Py_DECREF(substring);\r
+ return PyBool_FromLong(result);\r
+}\r
+\r
+\r
+/* Implements do_string_format, which is unicode because of stringlib */\r
+#include "stringlib/string_format.h"\r
+\r
+PyDoc_STRVAR(format__doc__,\r
+ "S.format(*args, **kwargs) -> unicode\n\\r
+\n\\r
+Return a formatted version of S, using substitutions from args and kwargs.\n\\r
+The substitutions are identified by braces ('{' and '}').");\r
+\r
+static PyObject *\r
+unicode__format__(PyObject *self, PyObject *args)\r
+{\r
+ PyObject *format_spec;\r
+ PyObject *result = NULL;\r
+ PyObject *tmp = NULL;\r
+\r
+ /* If 2.x, convert format_spec to the same type as value */\r
+ /* This is to allow things like u''.format('') */\r
+ if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))\r
+ goto done;\r
+ if (!(PyBytes_Check(format_spec) || PyUnicode_Check(format_spec))) {\r
+ PyErr_Format(PyExc_TypeError, "__format__ arg must be str "\r
+ "or unicode, not %s", Py_TYPE(format_spec)->tp_name);\r
+ goto done;\r
+ }\r
+ tmp = PyObject_Unicode(format_spec);\r
+ if (tmp == NULL)\r
+ goto done;\r
+ format_spec = tmp;\r
+\r
+ result = _PyUnicode_FormatAdvanced(self,\r
+ PyUnicode_AS_UNICODE(format_spec),\r
+ PyUnicode_GET_SIZE(format_spec));\r
+ done:\r
+ Py_XDECREF(tmp);\r
+ return result;\r
+}\r
+\r
+PyDoc_STRVAR(p_format__doc__,\r
+ "S.__format__(format_spec) -> unicode\n\\r
+\n\\r
+Return a formatted version of S as described by format_spec.");\r
+\r
+static PyObject *\r
+unicode__sizeof__(PyUnicodeObject *v)\r
+{\r
+ return PyInt_FromSsize_t(sizeof(PyUnicodeObject) +\r
+ sizeof(Py_UNICODE) * (v->length + 1));\r
+}\r
+\r
+PyDoc_STRVAR(sizeof__doc__,\r
+ "S.__sizeof__() -> size of S in memory, in bytes\n\\r
+\n\\r
+");\r
+\r
+static PyObject *\r
+unicode_getnewargs(PyUnicodeObject *v)\r
+{\r
+ return Py_BuildValue("(u#)", v->str, v->length);\r
+}\r
+\r
+\r
+static PyMethodDef unicode_methods[] = {\r
+ {"encode", (PyCFunction) unicode_encode, METH_VARARGS | METH_KEYWORDS, encode__doc__},\r
+ {"replace", (PyCFunction) unicode_replace, METH_VARARGS, replace__doc__},\r
+ {"split", (PyCFunction) unicode_split, METH_VARARGS, split__doc__},\r
+ {"rsplit", (PyCFunction) unicode_rsplit, METH_VARARGS, rsplit__doc__},\r
+ {"join", (PyCFunction) unicode_join, METH_O, join__doc__},\r
+ {"capitalize", (PyCFunction) unicode_capitalize, METH_NOARGS, capitalize__doc__},\r
+ {"title", (PyCFunction) unicode_title, METH_NOARGS, title__doc__},\r
+ {"center", (PyCFunction) unicode_center, METH_VARARGS, center__doc__},\r
+ {"count", (PyCFunction) unicode_count, METH_VARARGS, count__doc__},\r
+ {"expandtabs", (PyCFunction) unicode_expandtabs, METH_VARARGS, expandtabs__doc__},\r
+ {"find", (PyCFunction) unicode_find, METH_VARARGS, find__doc__},\r
+ {"partition", (PyCFunction) unicode_partition, METH_O, partition__doc__},\r
+ {"index", (PyCFunction) unicode_index, METH_VARARGS, index__doc__},\r
+ {"ljust", (PyCFunction) unicode_ljust, METH_VARARGS, ljust__doc__},\r
+ {"lower", (PyCFunction) unicode_lower, METH_NOARGS, lower__doc__},\r
+ {"lstrip", (PyCFunction) unicode_lstrip, METH_VARARGS, lstrip__doc__},\r
+ {"decode", (PyCFunction) unicode_decode, METH_VARARGS | METH_KEYWORDS, decode__doc__},\r
+/* {"maketrans", (PyCFunction) unicode_maketrans, METH_VARARGS, maketrans__doc__}, */\r
+ {"rfind", (PyCFunction) unicode_rfind, METH_VARARGS, rfind__doc__},\r
+ {"rindex", (PyCFunction) unicode_rindex, METH_VARARGS, rindex__doc__},\r
+ {"rjust", (PyCFunction) unicode_rjust, METH_VARARGS, rjust__doc__},\r
+ {"rstrip", (PyCFunction) unicode_rstrip, METH_VARARGS, rstrip__doc__},\r
+ {"rpartition", (PyCFunction) unicode_rpartition, METH_O, rpartition__doc__},\r
+ {"splitlines", (PyCFunction) unicode_splitlines, METH_VARARGS, splitlines__doc__},\r
+ {"strip", (PyCFunction) unicode_strip, METH_VARARGS, strip__doc__},\r
+ {"swapcase", (PyCFunction) unicode_swapcase, METH_NOARGS, swapcase__doc__},\r
+ {"translate", (PyCFunction) unicode_translate, METH_O, translate__doc__},\r
+ {"upper", (PyCFunction) unicode_upper, METH_NOARGS, upper__doc__},\r
+ {"startswith", (PyCFunction) unicode_startswith, METH_VARARGS, startswith__doc__},\r
+ {"endswith", (PyCFunction) unicode_endswith, METH_VARARGS, endswith__doc__},\r
+ {"islower", (PyCFunction) unicode_islower, METH_NOARGS, islower__doc__},\r
+ {"isupper", (PyCFunction) unicode_isupper, METH_NOARGS, isupper__doc__},\r
+ {"istitle", (PyCFunction) unicode_istitle, METH_NOARGS, istitle__doc__},\r
+ {"isspace", (PyCFunction) unicode_isspace, METH_NOARGS, isspace__doc__},\r
+ {"isdecimal", (PyCFunction) unicode_isdecimal, METH_NOARGS, isdecimal__doc__},\r
+ {"isdigit", (PyCFunction) unicode_isdigit, METH_NOARGS, isdigit__doc__},\r
+ {"isnumeric", (PyCFunction) unicode_isnumeric, METH_NOARGS, isnumeric__doc__},\r
+ {"isalpha", (PyCFunction) unicode_isalpha, METH_NOARGS, isalpha__doc__},\r
+ {"isalnum", (PyCFunction) unicode_isalnum, METH_NOARGS, isalnum__doc__},\r
+ {"zfill", (PyCFunction) unicode_zfill, METH_VARARGS, zfill__doc__},\r
+ {"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__},\r
+ {"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__},\r
+ {"_formatter_field_name_split", (PyCFunction) formatter_field_name_split, METH_NOARGS},\r
+ {"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS},\r
+ {"__sizeof__", (PyCFunction) unicode__sizeof__, METH_NOARGS, sizeof__doc__},\r
+#if 0\r
+ {"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__},\r
+#endif\r
+\r
+#if 0\r
+ /* This one is just used for debugging the implementation. */\r
+ {"freelistsize", (PyCFunction) free_listsize, METH_NOARGS},\r
+#endif\r
+\r
+ {"__getnewargs__", (PyCFunction)unicode_getnewargs, METH_NOARGS},\r
+ {NULL, NULL}\r
+};\r
+\r
+static PyObject *\r
+unicode_mod(PyObject *v, PyObject *w)\r
+{\r
+ if (!PyUnicode_Check(v)) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ return PyUnicode_Format(v, w);\r
+}\r
+\r
+static PyNumberMethods unicode_as_number = {\r
+ 0, /*nb_add*/\r
+ 0, /*nb_subtract*/\r
+ 0, /*nb_multiply*/\r
+ 0, /*nb_divide*/\r
+ unicode_mod, /*nb_remainder*/\r
+};\r
+\r
+static PySequenceMethods unicode_as_sequence = {\r
+ (lenfunc) unicode_length, /* sq_length */\r
+ PyUnicode_Concat, /* sq_concat */\r
+ (ssizeargfunc) unicode_repeat, /* sq_repeat */\r
+ (ssizeargfunc) unicode_getitem, /* sq_item */\r
+ (ssizessizeargfunc) unicode_slice, /* sq_slice */\r
+ 0, /* sq_ass_item */\r
+ 0, /* sq_ass_slice */\r
+ PyUnicode_Contains, /* sq_contains */\r
+};\r
+\r
+static PyObject*\r
+unicode_subscript(PyUnicodeObject* self, PyObject* item)\r
+{\r
+ if (PyIndex_Check(item)) {\r
+ Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);\r
+ if (i == -1 && PyErr_Occurred())\r
+ return NULL;\r
+ if (i < 0)\r
+ i += PyUnicode_GET_SIZE(self);\r
+ return unicode_getitem(self, i);\r
+ } else if (PySlice_Check(item)) {\r
+ Py_ssize_t start, stop, step, slicelength, cur, i;\r
+ Py_UNICODE* source_buf;\r
+ Py_UNICODE* result_buf;\r
+ PyObject* result;\r
+\r
+ if (PySlice_GetIndicesEx((PySliceObject*)item, PyUnicode_GET_SIZE(self),\r
+ &start, &stop, &step, &slicelength) < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ if (slicelength <= 0) {\r
+ return PyUnicode_FromUnicode(NULL, 0);\r
+ } else if (start == 0 && step == 1 && slicelength == self->length &&\r
+ PyUnicode_CheckExact(self)) {\r
+ Py_INCREF(self);\r
+ return (PyObject *)self;\r
+ } else if (step == 1) {\r
+ return PyUnicode_FromUnicode(self->str + start, slicelength);\r
+ } else {\r
+ source_buf = PyUnicode_AS_UNICODE((PyObject*)self);\r
+ result_buf = (Py_UNICODE *)PyObject_MALLOC(slicelength*\r
+ sizeof(Py_UNICODE));\r
+\r
+ if (result_buf == NULL)\r
+ return PyErr_NoMemory();\r
+\r
+ for (cur = start, i = 0; i < slicelength; cur += step, i++) {\r
+ result_buf[i] = source_buf[cur];\r
+ }\r
+\r
+ result = PyUnicode_FromUnicode(result_buf, slicelength);\r
+ PyObject_FREE(result_buf);\r
+ return result;\r
+ }\r
+ } else {\r
+ PyErr_SetString(PyExc_TypeError, "string indices must be integers");\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static PyMappingMethods unicode_as_mapping = {\r
+ (lenfunc)unicode_length, /* mp_length */\r
+ (binaryfunc)unicode_subscript, /* mp_subscript */\r
+ (objobjargproc)0, /* mp_ass_subscript */\r
+};\r
+\r
+static Py_ssize_t\r
+unicode_buffer_getreadbuf(PyUnicodeObject *self,\r
+ Py_ssize_t index,\r
+ const void **ptr)\r
+{\r
+ if (index != 0) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent unicode segment");\r
+ return -1;\r
+ }\r
+ *ptr = (void *) self->str;\r
+ return PyUnicode_GET_DATA_SIZE(self);\r
+}\r
+\r
+static Py_ssize_t\r
+unicode_buffer_getwritebuf(PyUnicodeObject *self, Py_ssize_t index,\r
+ const void **ptr)\r
+{\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "cannot use unicode as modifiable buffer");\r
+ return -1;\r
+}\r
+\r
+static int\r
+unicode_buffer_getsegcount(PyUnicodeObject *self,\r
+ Py_ssize_t *lenp)\r
+{\r
+ if (lenp)\r
+ *lenp = PyUnicode_GET_DATA_SIZE(self);\r
+ return 1;\r
+}\r
+\r
+static Py_ssize_t\r
+unicode_buffer_getcharbuf(PyUnicodeObject *self,\r
+ Py_ssize_t index,\r
+ const void **ptr)\r
+{\r
+ PyObject *str;\r
+\r
+ if (index != 0) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "accessing non-existent unicode segment");\r
+ return -1;\r
+ }\r
+ str = _PyUnicode_AsDefaultEncodedString((PyObject *)self, NULL);\r
+ if (str == NULL)\r
+ return -1;\r
+ *ptr = (void *) PyString_AS_STRING(str);\r
+ return PyString_GET_SIZE(str);\r
+}\r
+\r
+/* Helpers for PyUnicode_Format() */\r
+\r
+static PyObject *\r
+getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx)\r
+{\r
+ Py_ssize_t argidx = *p_argidx;\r
+ if (argidx < arglen) {\r
+ (*p_argidx)++;\r
+ if (arglen < 0)\r
+ return args;\r
+ else\r
+ return PyTuple_GetItem(args, argidx);\r
+ }\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "not enough arguments for format string");\r
+ return NULL;\r
+}\r
+\r
+#define F_LJUST (1<<0)\r
+#define F_SIGN (1<<1)\r
+#define F_BLANK (1<<2)\r
+#define F_ALT (1<<3)\r
+#define F_ZERO (1<<4)\r
+\r
+static Py_ssize_t\r
+strtounicode(Py_UNICODE *buffer, const char *charbuffer)\r
+{\r
+ register Py_ssize_t i;\r
+ Py_ssize_t len = strlen(charbuffer);\r
+ for (i = len - 1; i >= 0; i--)\r
+ buffer[i] = (Py_UNICODE) charbuffer[i];\r
+\r
+ return len;\r
+}\r
+\r
+static int\r
+longtounicode(Py_UNICODE *buffer, size_t len, const char *format, long x)\r
+{\r
+ Py_ssize_t result;\r
+\r
+ PyOS_snprintf((char *)buffer, len, format, x);\r
+ result = strtounicode(buffer, (char *)buffer);\r
+ return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);\r
+}\r
+\r
+/* XXX To save some code duplication, formatfloat/long/int could have been\r
+ shared with stringobject.c, converting from 8-bit to Unicode after the\r
+ formatting is done. */\r
+\r
+/* Returns a new reference to a PyUnicode object, or NULL on failure. */\r
+\r
+static PyObject *\r
+formatfloat(PyObject *v, int flags, int prec, int type)\r
+{\r
+ char *p;\r
+ PyObject *result;\r
+ double x;\r
+\r
+ x = PyFloat_AsDouble(v);\r
+ if (x == -1.0 && PyErr_Occurred())\r
+ return NULL;\r
+\r
+ if (prec < 0)\r
+ prec = 6;\r
+\r
+ p = PyOS_double_to_string(x, type, prec,\r
+ (flags & F_ALT) ? Py_DTSF_ALT : 0, NULL);\r
+ if (p == NULL)\r
+ return NULL;\r
+ result = PyUnicode_FromStringAndSize(p, strlen(p));\r
+ PyMem_Free(p);\r
+ return result;\r
+}\r
+\r
+static PyObject*\r
+formatlong(PyObject *val, int flags, int prec, int type)\r
+{\r
+ char *buf;\r
+ int i, len;\r
+ PyObject *str; /* temporary string object. */\r
+ PyUnicodeObject *result;\r
+\r
+ str = _PyString_FormatLong(val, flags, prec, type, &buf, &len);\r
+ if (!str)\r
+ return NULL;\r
+ result = _PyUnicode_New(len);\r
+ if (!result) {\r
+ Py_DECREF(str);\r
+ return NULL;\r
+ }\r
+ for (i = 0; i < len; i++)\r
+ result->str[i] = buf[i];\r
+ result->str[len] = 0;\r
+ Py_DECREF(str);\r
+ return (PyObject*)result;\r
+}\r
+\r
+static int\r
+formatint(Py_UNICODE *buf,\r
+ size_t buflen,\r
+ int flags,\r
+ int prec,\r
+ int type,\r
+ PyObject *v)\r
+{\r
+ /* fmt = '%#.' + `prec` + 'l' + `type`\r
+ * worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)\r
+ * + 1 + 1\r
+ * = 24\r
+ */\r
+ char fmt[64]; /* plenty big enough! */\r
+ char *sign;\r
+ long x;\r
+\r
+ x = PyInt_AsLong(v);\r
+ if (x == -1 && PyErr_Occurred())\r
+ return -1;\r
+ if (x < 0 && type == 'u') {\r
+ type = 'd';\r
+ }\r
+ if (x < 0 && (type == 'x' || type == 'X' || type == 'o'))\r
+ sign = "-";\r
+ else\r
+ sign = "";\r
+ if (prec < 0)\r
+ prec = 1;\r
+\r
+ /* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal))\r
+ * worst case buf = '-0x' + [0-9]*prec, where prec >= 11\r
+ */\r
+ if (buflen <= 14 || buflen <= (size_t)3 + (size_t)prec) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "formatted integer is too long (precision too large?)");\r
+ return -1;\r
+ }\r
+\r
+ if ((flags & F_ALT) &&\r
+ (type == 'x' || type == 'X')) {\r
+ /* When converting under %#x or %#X, there are a number\r
+ * of issues that cause pain:\r
+ * - when 0 is being converted, the C standard leaves off\r
+ * the '0x' or '0X', which is inconsistent with other\r
+ * %#x/%#X conversions and inconsistent with Python's\r
+ * hex() function\r
+ * - there are platforms that violate the standard and\r
+ * convert 0 with the '0x' or '0X'\r
+ * (Metrowerks, Compaq Tru64)\r
+ * - there are platforms that give '0x' when converting\r
+ * under %#X, but convert 0 in accordance with the\r
+ * standard (OS/2 EMX)\r
+ *\r
+ * We can achieve the desired consistency by inserting our\r
+ * own '0x' or '0X' prefix, and substituting %x/%X in place\r
+ * of %#x/%#X.\r
+ *\r
+ * Note that this is the same approach as used in\r
+ * formatint() in stringobject.c\r
+ */\r
+ PyOS_snprintf(fmt, sizeof(fmt), "%s0%c%%.%dl%c",\r
+ sign, type, prec, type);\r
+ }\r
+ else {\r
+ PyOS_snprintf(fmt, sizeof(fmt), "%s%%%s.%dl%c",\r
+ sign, (flags&F_ALT) ? "#" : "",\r
+ prec, type);\r
+ }\r
+ if (sign[0])\r
+ return longtounicode(buf, buflen, fmt, -x);\r
+ else\r
+ return longtounicode(buf, buflen, fmt, x);\r
+}\r
+\r
+static int\r
+formatchar(Py_UNICODE *buf,\r
+ size_t buflen,\r
+ PyObject *v)\r
+{\r
+ PyObject *unistr;\r
+ char *str;\r
+ /* presume that the buffer is at least 2 characters long */\r
+ if (PyUnicode_Check(v)) {\r
+ if (PyUnicode_GET_SIZE(v) != 1)\r
+ goto onError;\r
+ buf[0] = PyUnicode_AS_UNICODE(v)[0];\r
+ }\r
+\r
+ else if (PyString_Check(v)) {\r
+ if (PyString_GET_SIZE(v) != 1)\r
+ goto onError;\r
+ /* #7649: "u'%c' % char" should behave like "u'%s' % char" and fail\r
+ with a UnicodeDecodeError if 'char' is not decodable with the\r
+ default encoding (usually ASCII, but it might be something else) */\r
+ str = PyString_AS_STRING(v);\r
+ if ((unsigned char)str[0] > 0x7F) {\r
+ /* the char is not ASCII; try to decode the string using the\r
+ default encoding and return -1 to let the UnicodeDecodeError\r
+ be raised if the string can't be decoded */\r
+ unistr = PyUnicode_Decode(str, 1, NULL, "strict");\r
+ if (unistr == NULL)\r
+ return -1;\r
+ buf[0] = PyUnicode_AS_UNICODE(unistr)[0];\r
+ Py_DECREF(unistr);\r
+ }\r
+ else\r
+ buf[0] = (Py_UNICODE)str[0];\r
+ }\r
+\r
+ else {\r
+ /* Integer input truncated to a character */\r
+ long x;\r
+ x = PyInt_AsLong(v);\r
+ if (x == -1 && PyErr_Occurred())\r
+ goto onError;\r
+#ifdef Py_UNICODE_WIDE\r
+ if (x < 0 || x > 0x10ffff) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "%c arg not in range(0x110000) "\r
+ "(wide Python build)");\r
+ return -1;\r
+ }\r
+#else\r
+ if (x < 0 || x > 0xffff) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "%c arg not in range(0x10000) "\r
+ "(narrow Python build)");\r
+ return -1;\r
+ }\r
+#endif\r
+ buf[0] = (Py_UNICODE) x;\r
+ }\r
+ buf[1] = '\0';\r
+ return 1;\r
+\r
+ onError:\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "%c requires int or char");\r
+ return -1;\r
+}\r
+\r
+/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...)\r
+\r
+ FORMATBUFLEN is the length of the buffer in which the ints &\r
+ chars are formatted. XXX This is a magic number. Each formatting\r
+ routine does bounds checking to ensure no overflow, but a better\r
+ solution may be to malloc a buffer of appropriate size for each\r
+ format. For now, the current solution is sufficient.\r
+*/\r
+#define FORMATBUFLEN (size_t)120\r
+\r
+PyObject *PyUnicode_Format(PyObject *format,\r
+ PyObject *args)\r
+{\r
+ Py_UNICODE *fmt, *res;\r
+ Py_ssize_t fmtcnt, rescnt, reslen, arglen, argidx;\r
+ int args_owned = 0;\r
+ PyUnicodeObject *result = NULL;\r
+ PyObject *dict = NULL;\r
+ PyObject *uformat;\r
+\r
+ if (format == NULL || args == NULL) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ uformat = PyUnicode_FromObject(format);\r
+ if (uformat == NULL)\r
+ return NULL;\r
+ fmt = PyUnicode_AS_UNICODE(uformat);\r
+ fmtcnt = PyUnicode_GET_SIZE(uformat);\r
+\r
+ reslen = rescnt = fmtcnt + 100;\r
+ result = _PyUnicode_New(reslen);\r
+ if (result == NULL)\r
+ goto onError;\r
+ res = PyUnicode_AS_UNICODE(result);\r
+\r
+ if (PyTuple_Check(args)) {\r
+ arglen = PyTuple_Size(args);\r
+ argidx = 0;\r
+ }\r
+ else {\r
+ arglen = -1;\r
+ argidx = -2;\r
+ }\r
+ if (Py_TYPE(args)->tp_as_mapping && Py_TYPE(args)->tp_as_mapping->mp_subscript &&\r
+ !PyTuple_Check(args) && !PyObject_TypeCheck(args, &PyBaseString_Type))\r
+ dict = args;\r
+\r
+ while (--fmtcnt >= 0) {\r
+ if (*fmt != '%') {\r
+ if (--rescnt < 0) {\r
+ rescnt = fmtcnt + 100;\r
+ reslen += rescnt;\r
+ if (_PyUnicode_Resize(&result, reslen) < 0)\r
+ goto onError;\r
+ res = PyUnicode_AS_UNICODE(result) + reslen - rescnt;\r
+ --rescnt;\r
+ }\r
+ *res++ = *fmt++;\r
+ }\r
+ else {\r
+ /* Got a format specifier */\r
+ int flags = 0;\r
+ Py_ssize_t width = -1;\r
+ int prec = -1;\r
+ Py_UNICODE c = '\0';\r
+ Py_UNICODE fill;\r
+ int isnumok;\r
+ PyObject *v = NULL;\r
+ PyObject *temp = NULL;\r
+ Py_UNICODE *pbuf;\r
+ Py_UNICODE sign;\r
+ Py_ssize_t len;\r
+ Py_UNICODE formatbuf[FORMATBUFLEN]; /* For format{int,char}() */\r
+\r
+ fmt++;\r
+ if (*fmt == '(') {\r
+ Py_UNICODE *keystart;\r
+ Py_ssize_t keylen;\r
+ PyObject *key;\r
+ int pcount = 1;\r
+\r
+ if (dict == NULL) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "format requires a mapping");\r
+ goto onError;\r
+ }\r
+ ++fmt;\r
+ --fmtcnt;\r
+ keystart = fmt;\r
+ /* Skip over balanced parentheses */\r
+ while (pcount > 0 && --fmtcnt >= 0) {\r
+ if (*fmt == ')')\r
+ --pcount;\r
+ else if (*fmt == '(')\r
+ ++pcount;\r
+ fmt++;\r
+ }\r
+ keylen = fmt - keystart - 1;\r
+ if (fmtcnt < 0 || pcount > 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "incomplete format key");\r
+ goto onError;\r
+ }\r
+#if 0\r
+ /* keys are converted to strings using UTF-8 and\r
+ then looked up since Python uses strings to hold\r
+ variables names etc. in its namespaces and we\r
+ wouldn't want to break common idioms. */\r
+ key = PyUnicode_EncodeUTF8(keystart,\r
+ keylen,\r
+ NULL);\r
+#else\r
+ key = PyUnicode_FromUnicode(keystart, keylen);\r
+#endif\r
+ if (key == NULL)\r
+ goto onError;\r
+ if (args_owned) {\r
+ Py_DECREF(args);\r
+ args_owned = 0;\r
+ }\r
+ args = PyObject_GetItem(dict, key);\r
+ Py_DECREF(key);\r
+ if (args == NULL) {\r
+ goto onError;\r
+ }\r
+ args_owned = 1;\r
+ arglen = -1;\r
+ argidx = -2;\r
+ }\r
+ while (--fmtcnt >= 0) {\r
+ switch (c = *fmt++) {\r
+ case '-': flags |= F_LJUST; continue;\r
+ case '+': flags |= F_SIGN; continue;\r
+ case ' ': flags |= F_BLANK; continue;\r
+ case '#': flags |= F_ALT; continue;\r
+ case '0': flags |= F_ZERO; continue;\r
+ }\r
+ break;\r
+ }\r
+ if (c == '*') {\r
+ v = getnextarg(args, arglen, &argidx);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (!PyInt_Check(v)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "* wants int");\r
+ goto onError;\r
+ }\r
+ width = PyInt_AsSsize_t(v);\r
+ if (width == -1 && PyErr_Occurred())\r
+ goto onError;\r
+ if (width < 0) {\r
+ flags |= F_LJUST;\r
+ width = -width;\r
+ }\r
+ if (--fmtcnt >= 0)\r
+ c = *fmt++;\r
+ }\r
+ else if (c >= '0' && c <= '9') {\r
+ width = c - '0';\r
+ while (--fmtcnt >= 0) {\r
+ c = *fmt++;\r
+ if (c < '0' || c > '9')\r
+ break;\r
+ if (width > (PY_SSIZE_T_MAX - ((int)c - '0')) / 10) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "width too big");\r
+ goto onError;\r
+ }\r
+ width = width*10 + (c - '0');\r
+ }\r
+ }\r
+ if (c == '.') {\r
+ prec = 0;\r
+ if (--fmtcnt >= 0)\r
+ c = *fmt++;\r
+ if (c == '*') {\r
+ v = getnextarg(args, arglen, &argidx);\r
+ if (v == NULL)\r
+ goto onError;\r
+ if (!PyInt_Check(v)) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "* wants int");\r
+ goto onError;\r
+ }\r
+ prec = _PyInt_AsInt(v);\r
+ if (prec == -1 && PyErr_Occurred())\r
+ goto onError;\r
+ if (prec < 0)\r
+ prec = 0;\r
+ if (--fmtcnt >= 0)\r
+ c = *fmt++;\r
+ }\r
+ else if (c >= '0' && c <= '9') {\r
+ prec = c - '0';\r
+ while (--fmtcnt >= 0) {\r
+ c = *fmt++;\r
+ if (c < '0' || c > '9')\r
+ break;\r
+ if (prec > (INT_MAX - ((int)c - '0')) / 10) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "prec too big");\r
+ goto onError;\r
+ }\r
+ prec = prec*10 + (c - '0');\r
+ }\r
+ }\r
+ } /* prec */\r
+ if (fmtcnt >= 0) {\r
+ if (c == 'h' || c == 'l' || c == 'L') {\r
+ if (--fmtcnt >= 0)\r
+ c = *fmt++;\r
+ }\r
+ }\r
+ if (fmtcnt < 0) {\r
+ PyErr_SetString(PyExc_ValueError,\r
+ "incomplete format");\r
+ goto onError;\r
+ }\r
+ if (c != '%') {\r
+ v = getnextarg(args, arglen, &argidx);\r
+ if (v == NULL)\r
+ goto onError;\r
+ }\r
+ sign = 0;\r
+ fill = ' ';\r
+ switch (c) {\r
+\r
+ case '%':\r
+ pbuf = formatbuf;\r
+ /* presume that buffer length is at least 1 */\r
+ pbuf[0] = '%';\r
+ len = 1;\r
+ break;\r
+\r
+ case 's':\r
+ case 'r':\r
+ if (PyUnicode_CheckExact(v) && c == 's') {\r
+ temp = v;\r
+ Py_INCREF(temp);\r
+ }\r
+ else {\r
+ PyObject *unicode;\r
+ if (c == 's')\r
+ temp = PyObject_Unicode(v);\r
+ else\r
+ temp = PyObject_Repr(v);\r
+ if (temp == NULL)\r
+ goto onError;\r
+ if (PyUnicode_Check(temp))\r
+ /* nothing to do */;\r
+ else if (PyString_Check(temp)) {\r
+ /* convert to string to Unicode */\r
+ unicode = PyUnicode_Decode(PyString_AS_STRING(temp),\r
+ PyString_GET_SIZE(temp),\r
+ NULL,\r
+ "strict");\r
+ Py_DECREF(temp);\r
+ temp = unicode;\r
+ if (temp == NULL)\r
+ goto onError;\r
+ }\r
+ else {\r
+ Py_DECREF(temp);\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "%s argument has non-string str()");\r
+ goto onError;\r
+ }\r
+ }\r
+ pbuf = PyUnicode_AS_UNICODE(temp);\r
+ len = PyUnicode_GET_SIZE(temp);\r
+ if (prec >= 0 && len > prec)\r
+ len = prec;\r
+ break;\r
+\r
+ case 'i':\r
+ case 'd':\r
+ case 'u':\r
+ case 'o':\r
+ case 'x':\r
+ case 'X':\r
+ if (c == 'i')\r
+ c = 'd';\r
+ isnumok = 0;\r
+ if (PyNumber_Check(v)) {\r
+ PyObject *iobj=NULL;\r
+\r
+ if (PyInt_Check(v) || (PyLong_Check(v))) {\r
+ iobj = v;\r
+ Py_INCREF(iobj);\r
+ }\r
+ else {\r
+ iobj = PyNumber_Int(v);\r
+ if (iobj==NULL) iobj = PyNumber_Long(v);\r
+ }\r
+ if (iobj!=NULL) {\r
+ if (PyInt_Check(iobj)) {\r
+ isnumok = 1;\r
+ pbuf = formatbuf;\r
+ len = formatint(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE),\r
+ flags, prec, c, iobj);\r
+ Py_DECREF(iobj);\r
+ if (len < 0)\r
+ goto onError;\r
+ sign = 1;\r
+ }\r
+ else if (PyLong_Check(iobj)) {\r
+ isnumok = 1;\r
+ temp = formatlong(iobj, flags, prec, c);\r
+ Py_DECREF(iobj);\r
+ if (!temp)\r
+ goto onError;\r
+ pbuf = PyUnicode_AS_UNICODE(temp);\r
+ len = PyUnicode_GET_SIZE(temp);\r
+ sign = 1;\r
+ }\r
+ else {\r
+ Py_DECREF(iobj);\r
+ }\r
+ }\r
+ }\r
+ if (!isnumok) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "%%%c format: a number is required, "\r
+ "not %.200s", (char)c, Py_TYPE(v)->tp_name);\r
+ goto onError;\r
+ }\r
+ if (flags & F_ZERO)\r
+ fill = '0';\r
+ break;\r
+\r
+ case 'e':\r
+ case 'E':\r
+ case 'f':\r
+ case 'F':\r
+ case 'g':\r
+ case 'G':\r
+ temp = formatfloat(v, flags, prec, c);\r
+ if (temp == NULL)\r
+ goto onError;\r
+ pbuf = PyUnicode_AS_UNICODE(temp);\r
+ len = PyUnicode_GET_SIZE(temp);\r
+ sign = 1;\r
+ if (flags & F_ZERO)\r
+ fill = '0';\r
+ break;\r
+\r
+ case 'c':\r
+ pbuf = formatbuf;\r
+ len = formatchar(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE), v);\r
+ if (len < 0)\r
+ goto onError;\r
+ break;\r
+\r
+ default:\r
+ PyErr_Format(PyExc_ValueError,\r
+ "unsupported format character '%c' (0x%x) "\r
+ "at index %zd",\r
+ (31<=c && c<=126) ? (char)c : '?',\r
+ (int)c,\r
+ (Py_ssize_t)(fmt - 1 -\r
+ PyUnicode_AS_UNICODE(uformat)));\r
+ goto onError;\r
+ }\r
+ if (sign) {\r
+ if (*pbuf == '-' || *pbuf == '+') {\r
+ sign = *pbuf++;\r
+ len--;\r
+ }\r
+ else if (flags & F_SIGN)\r
+ sign = '+';\r
+ else if (flags & F_BLANK)\r
+ sign = ' ';\r
+ else\r
+ sign = 0;\r
+ }\r
+ if (width < len)\r
+ width = len;\r
+ if (rescnt - (sign != 0) < width) {\r
+ reslen -= rescnt;\r
+ rescnt = width + fmtcnt + 100;\r
+ reslen += rescnt;\r
+ if (reslen < 0) {\r
+ Py_XDECREF(temp);\r
+ PyErr_NoMemory();\r
+ goto onError;\r
+ }\r
+ if (_PyUnicode_Resize(&result, reslen) < 0) {\r
+ Py_XDECREF(temp);\r
+ goto onError;\r
+ }\r
+ res = PyUnicode_AS_UNICODE(result)\r
+ + reslen - rescnt;\r
+ }\r
+ if (sign) {\r
+ if (fill != ' ')\r
+ *res++ = sign;\r
+ rescnt--;\r
+ if (width > len)\r
+ width--;\r
+ }\r
+ if ((flags & F_ALT) && (c == 'x' || c == 'X')) {\r
+ assert(pbuf[0] == '0');\r
+ assert(pbuf[1] == c);\r
+ if (fill != ' ') {\r
+ *res++ = *pbuf++;\r
+ *res++ = *pbuf++;\r
+ }\r
+ rescnt -= 2;\r
+ width -= 2;\r
+ if (width < 0)\r
+ width = 0;\r
+ len -= 2;\r
+ }\r
+ if (width > len && !(flags & F_LJUST)) {\r
+ do {\r
+ --rescnt;\r
+ *res++ = fill;\r
+ } while (--width > len);\r
+ }\r
+ if (fill == ' ') {\r
+ if (sign)\r
+ *res++ = sign;\r
+ if ((flags & F_ALT) && (c == 'x' || c == 'X')) {\r
+ assert(pbuf[0] == '0');\r
+ assert(pbuf[1] == c);\r
+ *res++ = *pbuf++;\r
+ *res++ = *pbuf++;\r
+ }\r
+ }\r
+ Py_UNICODE_COPY(res, pbuf, len);\r
+ res += len;\r
+ rescnt -= len;\r
+ while (--width >= len) {\r
+ --rescnt;\r
+ *res++ = ' ';\r
+ }\r
+ if (dict && (argidx < arglen) && c != '%') {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "not all arguments converted during string formatting");\r
+ Py_XDECREF(temp);\r
+ goto onError;\r
+ }\r
+ Py_XDECREF(temp);\r
+ } /* '%' */\r
+ } /* until end */\r
+ if (argidx < arglen && !dict) {\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "not all arguments converted during string formatting");\r
+ goto onError;\r
+ }\r
+\r
+ if (_PyUnicode_Resize(&result, reslen - rescnt) < 0)\r
+ goto onError;\r
+ if (args_owned) {\r
+ Py_DECREF(args);\r
+ }\r
+ Py_DECREF(uformat);\r
+ return (PyObject *)result;\r
+\r
+ onError:\r
+ Py_XDECREF(result);\r
+ Py_DECREF(uformat);\r
+ if (args_owned) {\r
+ Py_DECREF(args);\r
+ }\r
+ return NULL;\r
+}\r
+\r
+static PyBufferProcs unicode_as_buffer = {\r
+ (readbufferproc) unicode_buffer_getreadbuf,\r
+ (writebufferproc) unicode_buffer_getwritebuf,\r
+ (segcountproc) unicode_buffer_getsegcount,\r
+ (charbufferproc) unicode_buffer_getcharbuf,\r
+};\r
+\r
+static PyObject *\r
+unicode_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);\r
+\r
+static PyObject *\r
+unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyObject *x = NULL;\r
+ static char *kwlist[] = {"string", "encoding", "errors", 0};\r
+ char *encoding = NULL;\r
+ char *errors = NULL;\r
+\r
+ if (type != &PyUnicode_Type)\r
+ return unicode_subtype_new(type, args, kwds);\r
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:unicode",\r
+ kwlist, &x, &encoding, &errors))\r
+ return NULL;\r
+ if (x == NULL)\r
+ return (PyObject *)_PyUnicode_New(0);\r
+ if (encoding == NULL && errors == NULL)\r
+ return PyObject_Unicode(x);\r
+ else\r
+ return PyUnicode_FromEncodedObject(x, encoding, errors);\r
+}\r
+\r
+static PyObject *\r
+unicode_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
+{\r
+ PyUnicodeObject *tmp, *pnew;\r
+ Py_ssize_t n;\r
+\r
+ assert(PyType_IsSubtype(type, &PyUnicode_Type));\r
+ tmp = (PyUnicodeObject *)unicode_new(&PyUnicode_Type, args, kwds);\r
+ if (tmp == NULL)\r
+ return NULL;\r
+ assert(PyUnicode_Check(tmp));\r
+ pnew = (PyUnicodeObject *) type->tp_alloc(type, n = tmp->length);\r
+ if (pnew == NULL) {\r
+ Py_DECREF(tmp);\r
+ return NULL;\r
+ }\r
+ pnew->str = (Py_UNICODE*) PyObject_MALLOC(sizeof(Py_UNICODE) * (n+1));\r
+ if (pnew->str == NULL) {\r
+ _Py_ForgetReference((PyObject *)pnew);\r
+ PyObject_Del(pnew);\r
+ Py_DECREF(tmp);\r
+ return PyErr_NoMemory();\r
+ }\r
+ Py_UNICODE_COPY(pnew->str, tmp->str, n+1);\r
+ pnew->length = n;\r
+ pnew->hash = tmp->hash;\r
+ Py_DECREF(tmp);\r
+ return (PyObject *)pnew;\r
+}\r
+\r
+PyDoc_STRVAR(unicode_doc,\r
+ "unicode(object='') -> unicode object\n\\r
+unicode(string[, encoding[, errors]]) -> unicode object\n\\r
+\n\\r
+Create a new Unicode object from the given encoded string.\n\\r
+encoding defaults to the current default string encoding.\n\\r
+errors can be 'strict', 'replace' or 'ignore' and defaults to 'strict'.");\r
+\r
+PyTypeObject PyUnicode_Type = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "unicode", /* tp_name */\r
+ sizeof(PyUnicodeObject), /* tp_size */\r
+ 0, /* tp_itemsize */\r
+ /* Slots */\r
+ (destructor)unicode_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ 0, /* tp_compare */\r
+ unicode_repr, /* tp_repr */\r
+ &unicode_as_number, /* tp_as_number */\r
+ &unicode_as_sequence, /* tp_as_sequence */\r
+ &unicode_as_mapping, /* tp_as_mapping */\r
+ (hashfunc) unicode_hash, /* tp_hash*/\r
+ 0, /* tp_call*/\r
+ (reprfunc) unicode_str, /* tp_str */\r
+ PyObject_GenericGetAttr, /* tp_getattro */\r
+ 0, /* tp_setattro */\r
+ &unicode_as_buffer, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |\r
+ Py_TPFLAGS_BASETYPE | Py_TPFLAGS_UNICODE_SUBCLASS, /* tp_flags */\r
+ unicode_doc, /* tp_doc */\r
+ 0, /* tp_traverse */\r
+ 0, /* tp_clear */\r
+ PyUnicode_RichCompare, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ 0, /* tp_iter */\r
+ 0, /* tp_iternext */\r
+ unicode_methods, /* tp_methods */\r
+ 0, /* tp_members */\r
+ 0, /* tp_getset */\r
+ &PyBaseString_Type, /* tp_base */\r
+ 0, /* tp_dict */\r
+ 0, /* tp_descr_get */\r
+ 0, /* tp_descr_set */\r
+ 0, /* tp_dictoffset */\r
+ 0, /* tp_init */\r
+ 0, /* tp_alloc */\r
+ unicode_new, /* tp_new */\r
+ PyObject_Del, /* tp_free */\r
+};\r
+\r
+/* Initialize the Unicode implementation */\r
+\r
+void _PyUnicode_Init(void)\r
+{\r
+ /* XXX - move this array to unicodectype.c ? */\r
+ Py_UNICODE linebreak[] = {\r
+ 0x000A, /* LINE FEED */\r
+ 0x000D, /* CARRIAGE RETURN */\r
+ 0x001C, /* FILE SEPARATOR */\r
+ 0x001D, /* GROUP SEPARATOR */\r
+ 0x001E, /* RECORD SEPARATOR */\r
+ 0x0085, /* NEXT LINE */\r
+ 0x2028, /* LINE SEPARATOR */\r
+ 0x2029, /* PARAGRAPH SEPARATOR */\r
+ };\r
+\r
+ /* Init the implementation */\r
+ if (!unicode_empty) {\r
+ unicode_empty = _PyUnicode_New(0);\r
+ if (!unicode_empty)\r
+ return;\r
+ }\r
+\r
+ if (PyType_Ready(&PyUnicode_Type) < 0)\r
+ Py_FatalError("Can't initialize 'unicode'");\r
+\r
+ /* initialize the linebreak bloom filter */\r
+ bloom_linebreak = make_bloom_mask(\r
+ linebreak, sizeof(linebreak) / sizeof(linebreak[0])\r
+ );\r
+\r
+ PyType_Ready(&EncodingMapType);\r
+\r
+ if (PyType_Ready(&PyFieldNameIter_Type) < 0)\r
+ Py_FatalError("Can't initialize field name iterator type");\r
+\r
+ if (PyType_Ready(&PyFormatterIter_Type) < 0)\r
+ Py_FatalError("Can't initialize formatter iter type");\r
+}\r
+\r
+/* Finalize the Unicode implementation */\r
+\r
+int\r
+PyUnicode_ClearFreeList(void)\r
+{\r
+ int freelist_size = numfree;\r
+ PyUnicodeObject *u;\r
+\r
+ for (u = free_list; u != NULL;) {\r
+ PyUnicodeObject *v = u;\r
+ u = *(PyUnicodeObject **)u;\r
+ if (v->str)\r
+ PyObject_DEL(v->str);\r
+ Py_XDECREF(v->defenc);\r
+ PyObject_Del(v);\r
+ numfree--;\r
+ }\r
+ free_list = NULL;\r
+ assert(numfree == 0);\r
+ return freelist_size;\r
+}\r
+\r
+void\r
+_PyUnicode_Fini(void)\r
+{\r
+ int i;\r
+\r
+ Py_CLEAR(unicode_empty);\r
+\r
+ for (i = 0; i < 256; i++)\r
+ Py_CLEAR(unicode_latin1[i]);\r
+\r
+ (void)PyUnicode_ClearFreeList();\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+/* this file was generated by Tools/unicode/makeunicodedata.py 2.6 */\r
+\r
+/* a list of unique character type descriptors */\r
+const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = {\r
+ {0, 0, 0, 0, 0, 0},\r
+ {0, 0, 0, 0, 0, 0},\r
+ {0, 0, 0, 0, 0, 32},\r
+ {0, 0, 0, 0, 0, 48},\r
+ {0, 0, 0, 0, 0, 518},\r
+ {0, 0, 0, 1, 1, 518},\r
+ {0, 0, 0, 2, 2, 518},\r
+ {0, 0, 0, 3, 3, 518},\r
+ {0, 0, 0, 4, 4, 518},\r
+ {0, 0, 0, 5, 5, 518},\r
+ {0, 0, 0, 6, 6, 518},\r
+ {0, 0, 0, 7, 7, 518},\r
+ {0, 0, 0, 8, 8, 518},\r
+ {0, 0, 0, 9, 9, 518},\r
+ {0, 32, 0, 0, 0, 129},\r
+ {65504, 0, 65504, 0, 0, 9},\r
+ {0, 0, 0, 0, 0, 9},\r
+ {0, 0, 0, 0, 2, 516},\r
+ {0, 0, 0, 0, 3, 516},\r
+ {743, 0, 743, 0, 0, 9},\r
+ {0, 0, 0, 0, 1, 516},\r
+ {0, 0, 0, 0, 0, 512},\r
+ {121, 0, 121, 0, 0, 9},\r
+ {0, 1, 0, 0, 0, 129},\r
+ {65535, 0, 65535, 0, 0, 9},\r
+ {0, 65337, 0, 0, 0, 129},\r
+ {65304, 0, 65304, 0, 0, 9},\r
+ {0, 65415, 0, 0, 0, 129},\r
+ {65236, 0, 65236, 0, 0, 9},\r
+ {195, 0, 195, 0, 0, 9},\r
+ {0, 210, 0, 0, 0, 129},\r
+ {0, 206, 0, 0, 0, 129},\r
+ {0, 205, 0, 0, 0, 129},\r
+ {0, 79, 0, 0, 0, 129},\r
+ {0, 202, 0, 0, 0, 129},\r
+ {0, 203, 0, 0, 0, 129},\r
+ {0, 207, 0, 0, 0, 129},\r
+ {97, 0, 97, 0, 0, 9},\r
+ {0, 211, 0, 0, 0, 129},\r
+ {0, 209, 0, 0, 0, 129},\r
+ {163, 0, 163, 0, 0, 9},\r
+ {0, 213, 0, 0, 0, 129},\r
+ {130, 0, 130, 0, 0, 9},\r
+ {0, 214, 0, 0, 0, 129},\r
+ {0, 218, 0, 0, 0, 129},\r
+ {0, 217, 0, 0, 0, 129},\r
+ {0, 219, 0, 0, 0, 129},\r
+ {0, 0, 0, 0, 0, 1},\r
+ {56, 0, 56, 0, 0, 9},\r
+ {0, 2, 1, 0, 0, 129},\r
+ {65535, 1, 0, 0, 0, 65},\r
+ {65534, 0, 65535, 0, 0, 9},\r
+ {65457, 0, 65457, 0, 0, 9},\r
+ {0, 65439, 0, 0, 0, 129},\r
+ {0, 65480, 0, 0, 0, 129},\r
+ {0, 65406, 0, 0, 0, 129},\r
+ {0, 10795, 0, 0, 0, 129},\r
+ {0, 65373, 0, 0, 0, 129},\r
+ {0, 10792, 0, 0, 0, 129},\r
+ {10815, 0, 10815, 0, 0, 9},\r
+ {0, 65341, 0, 0, 0, 129},\r
+ {0, 69, 0, 0, 0, 129},\r
+ {0, 71, 0, 0, 0, 129},\r
+ {10783, 0, 10783, 0, 0, 9},\r
+ {10780, 0, 10780, 0, 0, 9},\r
+ {10782, 0, 10782, 0, 0, 9},\r
+ {65326, 0, 65326, 0, 0, 9},\r
+ {65330, 0, 65330, 0, 0, 9},\r
+ {65331, 0, 65331, 0, 0, 9},\r
+ {65334, 0, 65334, 0, 0, 9},\r
+ {65333, 0, 65333, 0, 0, 9},\r
+ {65329, 0, 65329, 0, 0, 9},\r
+ {65327, 0, 65327, 0, 0, 9},\r
+ {65325, 0, 65325, 0, 0, 9},\r
+ {10743, 0, 10743, 0, 0, 9},\r
+ {10749, 0, 10749, 0, 0, 9},\r
+ {65323, 0, 65323, 0, 0, 9},\r
+ {65322, 0, 65322, 0, 0, 9},\r
+ {10727, 0, 10727, 0, 0, 9},\r
+ {65318, 0, 65318, 0, 0, 9},\r
+ {65467, 0, 65467, 0, 0, 9},\r
+ {65319, 0, 65319, 0, 0, 9},\r
+ {65465, 0, 65465, 0, 0, 9},\r
+ {65317, 0, 65317, 0, 0, 9},\r
+ {84, 0, 84, 0, 0, 0},\r
+ {0, 38, 0, 0, 0, 129},\r
+ {0, 37, 0, 0, 0, 129},\r
+ {0, 64, 0, 0, 0, 129},\r
+ {0, 63, 0, 0, 0, 129},\r
+ {65498, 0, 65498, 0, 0, 9},\r
+ {65499, 0, 65499, 0, 0, 9},\r
+ {65505, 0, 65505, 0, 0, 9},\r
+ {65472, 0, 65472, 0, 0, 9},\r
+ {65473, 0, 65473, 0, 0, 9},\r
+ {0, 8, 0, 0, 0, 129},\r
+ {65474, 0, 65474, 0, 0, 9},\r
+ {65479, 0, 65479, 0, 0, 9},\r
+ {0, 0, 0, 0, 0, 129},\r
+ {65489, 0, 65489, 0, 0, 9},\r
+ {65482, 0, 65482, 0, 0, 9},\r
+ {65528, 0, 65528, 0, 0, 9},\r
+ {65450, 0, 65450, 0, 0, 9},\r
+ {65456, 0, 65456, 0, 0, 9},\r
+ {7, 0, 7, 0, 0, 9},\r
+ {0, 65476, 0, 0, 0, 129},\r
+ {65440, 0, 65440, 0, 0, 9},\r
+ {0, 65529, 0, 0, 0, 129},\r
+ {0, 80, 0, 0, 0, 129},\r
+ {0, 15, 0, 0, 0, 129},\r
+ {65521, 0, 65521, 0, 0, 9},\r
+ {0, 48, 0, 0, 0, 129},\r
+ {65488, 0, 65488, 0, 0, 9},\r
+ {0, 7264, 0, 0, 0, 129},\r
+ {0, 0, 0, 0, 4, 516},\r
+ {0, 0, 0, 0, 5, 516},\r
+ {0, 0, 0, 0, 6, 516},\r
+ {0, 0, 0, 0, 7, 516},\r
+ {0, 0, 0, 0, 8, 516},\r
+ {0, 0, 0, 0, 9, 516},\r
+ {42877, 7545, 42877, 0, 0, 265},\r
+ {3814, 0, 3814, 0, 0, 9},\r
+ {65477, 0, 65477, 0, 0, 9},\r
+ {0, 57921, 0, 0, 0, 129},\r
+ {8, 0, 8, 0, 0, 9},\r
+ {0, 65528, 0, 0, 0, 129},\r
+ {74, 0, 74, 0, 0, 9},\r
+ {86, 0, 86, 0, 0, 9},\r
+ {100, 0, 100, 0, 0, 9},\r
+ {128, 0, 128, 0, 0, 9},\r
+ {112, 0, 112, 0, 0, 9},\r
+ {126, 0, 126, 0, 0, 9},\r
+ {0, 65528, 0, 0, 0, 65},\r
+ {9, 0, 9, 0, 0, 9},\r
+ {0, 65462, 0, 0, 0, 129},\r
+ {0, 65527, 0, 0, 0, 65},\r
+ {58331, 0, 58331, 0, 0, 9},\r
+ {0, 65450, 0, 0, 0, 129},\r
+ {0, 65436, 0, 0, 0, 129},\r
+ {0, 65424, 0, 0, 0, 129},\r
+ {0, 65408, 0, 0, 0, 129},\r
+ {0, 65410, 0, 0, 0, 129},\r
+ {0, 0, 0, 0, 0, 516},\r
+ {0, 58019, 0, 0, 0, 129},\r
+ {0, 57153, 0, 0, 0, 129},\r
+ {0, 57274, 0, 0, 0, 129},\r
+ {0, 28, 0, 0, 0, 129},\r
+ {65508, 0, 65508, 0, 0, 9},\r
+ {0, 16, 0, 0, 0, 512},\r
+ {65520, 0, 65520, 0, 0, 512},\r
+ {0, 26, 0, 0, 0, 0},\r
+ {65510, 0, 65510, 0, 0, 0},\r
+ {0, 54793, 0, 0, 0, 129},\r
+ {0, 61722, 0, 0, 0, 129},\r
+ {0, 54809, 0, 0, 0, 129},\r
+ {54741, 0, 54741, 0, 0, 9},\r
+ {54744, 0, 54744, 0, 0, 9},\r
+ {0, 54756, 0, 0, 0, 129},\r
+ {0, 54787, 0, 0, 0, 129},\r
+ {0, 54753, 0, 0, 0, 129},\r
+ {0, 54754, 0, 0, 0, 129},\r
+ {0, 54721, 0, 0, 0, 129},\r
+ {58272, 0, 58272, 0, 0, 9},\r
+ {0, 0, 0, 0, 0, 513},\r
+ {42877, 7545, 42877, 0, 0, 385},\r
+ {0, 40, 0, 0, 0, 129},\r
+ {65496, 0, 65496, 0, 0, 9},\r
+};\r
+\r
+/* type indexes */\r
+#define SHIFT 7\r
+static unsigned char index1[] = {\r
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, \r
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 34, 35, 36, 37, \r
+ 38, 39, 34, 34, 34, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, \r
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 65, 66, 67, 64, \r
+ 64, 64, 68, 69, 70, 64, 64, 64, 64, 64, 64, 71, 17, 72, 73, 74, 75, 76, \r
+ 77, 64, 78, 79, 80, 81, 82, 83, 84, 64, 64, 85, 86, 34, 34, 34, 34, 34, \r
+ 34, 87, 34, 34, 34, 34, 34, 88, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 89, 90, 91, 92, 34, 34, 34, 93, 34, 34, \r
+ 34, 94, 95, 34, 34, 34, 34, 34, 96, 34, 34, 34, 97, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 98, 99, 100, 34, 34, 34, 34, 34, 34, 101, 102, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 103, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 104, 34, 34, 34, 34, 34, 34, 34, 34, 105, 34, 34, 34, 34, \r
+ 101, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 104, 34, 34, 34, 34, 34, 34, 106, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 107, 108, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 109, 110, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 111, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 112, 34, 34, 113, 114, 115, 116, 117, 118, 119, 120, 121, \r
+ 122, 17, 123, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 124, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 125, 126, 127, 128, \r
+ 129, 130, 34, 34, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 17, \r
+ 141, 142, 143, 144, 145, 17, 17, 17, 17, 17, 17, 146, 17, 147, 17, 148, \r
+ 17, 149, 17, 150, 17, 17, 17, 151, 17, 17, 17, 17, 152, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 34, 34, 34, 34, 34, 34, 153, 17, 154, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 34, 34, 34, 34, 34, 34, 34, 34, 155, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 64, 156, 157, 158, 159, 17, 160, 17, 161, 162, 163, 164, 165, 166, 167, \r
+ 168, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 169, 170, 171, 172, \r
+ 173, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 174, 175, 176, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 87, 177, 34, 178, 179, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 180, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 181, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 182, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 183, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 184, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, \r
+ 185, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 34, 180, 34, 34, 186, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 187, 17, 64, 188, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, \r
+ 17, 17, 17, 17, 17, 17, 17, 17, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 189, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, \r
+ 64, 64, 64, 64, 64, 189, \r
+};\r
+\r
+static unsigned char index2[] = {\r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 1, 1, 1, 1, 1, 14, 14, 14, 14, \r
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, \r
+ 14, 14, 14, 14, 1, 1, 1, 1, 1, 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, \r
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, \r
+ 1, 1, 1, 1, 17, 18, 1, 19, 1, 1, 1, 20, 16, 1, 21, 21, 21, 1, 14, 14, 14, \r
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, \r
+ 14, 14, 1, 14, 14, 14, 14, 14, 14, 14, 16, 15, 15, 15, 15, 15, 15, 15, \r
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 15, \r
+ 15, 15, 15, 15, 15, 15, 22, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 25, 26, 23, 24, 23, 24, 23, 24, 16, 23, 24, 23, 24, 23, 24, 23, 24, \r
+ 23, 24, 23, 24, 23, 24, 23, 24, 16, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 27, 23, 24, 23, 24, 23, 24, 28, 29, 30, 23, 24, 23, 24, 31, 23, 24, \r
+ 32, 32, 23, 24, 16, 33, 34, 35, 23, 24, 32, 36, 37, 38, 39, 23, 24, 40, \r
+ 16, 38, 41, 42, 43, 23, 24, 23, 24, 23, 24, 44, 23, 24, 44, 16, 16, 23, \r
+ 24, 44, 23, 24, 45, 45, 23, 24, 23, 24, 46, 23, 24, 16, 47, 23, 24, 16, \r
+ 48, 47, 47, 47, 47, 49, 50, 51, 49, 50, 51, 49, 50, 51, 23, 24, 23, 24, \r
+ 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 52, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 16, 49, 50, 51, 23, \r
+ 24, 53, 54, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 55, 16, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 16, 16, 16, 16, 16, 16, 56, 23, 24, \r
+ 57, 58, 59, 59, 23, 24, 60, 61, 62, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 63, 64, 65, 66, 67, 16, 68, 68, 16, 69, 16, 70, 16, 16, 16, 16, 68, \r
+ 16, 16, 71, 16, 16, 16, 16, 72, 73, 16, 74, 16, 16, 16, 73, 16, 75, 76, \r
+ 16, 16, 77, 16, 16, 16, 16, 16, 16, 16, 78, 16, 16, 79, 16, 16, 79, 16, \r
+ 16, 16, 16, 79, 80, 81, 81, 82, 16, 16, 16, 16, 16, 83, 16, 47, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 47, 47, 47, \r
+ 47, 1, 1, 1, 1, 1, 1, 1, 47, 1, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 24, \r
+ 23, 24, 47, 1, 23, 24, 0, 0, 47, 42, 42, 42, 1, 0, 0, 0, 0, 0, 1, 1, 85, \r
+ 1, 86, 86, 86, 0, 87, 0, 88, 88, 16, 14, 14, 14, 14, 14, 14, 14, 14, 14, \r
+ 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, \r
+ 89, 90, 90, 90, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, \r
+ 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 93, 93, 94, \r
+ 95, 96, 97, 97, 97, 98, 99, 100, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, \r
+ 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 101, 102, 103, \r
+ 16, 104, 105, 1, 23, 24, 106, 23, 24, 16, 55, 55, 55, 107, 107, 107, 107, \r
+ 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 14, 14, 14, \r
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, \r
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, \r
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, \r
+ 15, 15, 15, 15, 15, 15, 15, 102, 102, 102, 102, 102, 102, 102, 102, 102, \r
+ 102, 102, 102, 102, 102, 102, 102, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 1, 1, 1, 1, 1, 1, 1, 1, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 108, 23, 24, 23, 24, \r
+ 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 109, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 110, \r
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, \r
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, \r
+ 110, 110, 110, 110, 110, 110, 110, 110, 0, 0, 47, 1, 1, 1, 1, 1, 1, 0, \r
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, \r
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, \r
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 16, 0, 1, 1, 0, 0, 0, \r
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 0, 0, 0, 0, 0, 47, 47, 47, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, 5, 6, 7, 8, 9, 10, \r
+ 11, 12, 13, 1, 1, 1, 1, 47, 47, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 1, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 47, 1, 1, 1, 1, \r
+ 1, 1, 1, 47, 47, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 47, 47, 47, 1, 1, 47, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 47, 1, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, \r
+ 12, 13, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 47, 47, 1, 1, 1, 1, 47, 0, 0, 0, 0, 0, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 1, 1, 1, 1, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 1, 1, 1, 47, 1, 1, 1, \r
+ 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 0, 0, 1, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 47, 1, \r
+ 1, 1, 1, 1, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 4, \r
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 47, 47, 0, 0, 0, 0, 0, 0, 47, 47, 47, \r
+ 47, 47, 47, 47, 0, 1, 1, 1, 0, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 47, \r
+ 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, 0, 0, 0, \r
+ 47, 47, 47, 47, 0, 0, 1, 47, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, \r
+ 1, 47, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 47, 47, 0, 47, 47, 47, 1, \r
+ 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 47, 47, 1, 1, 21, 21, 21, 21, \r
+ 21, 21, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 47, 47, 47, 47, 47, 47, 0, 0, 0, \r
+ 0, 47, 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, \r
+ 0, 47, 47, 0, 47, 47, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, \r
+ 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 0, 47, 0, 0, 0, \r
+ 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 47, 47, 47, 1, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 0, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, \r
+ 47, 0, 47, 47, 47, 47, 47, 0, 0, 1, 47, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, \r
+ 1, 0, 1, 1, 1, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, \r
+ 47, 1, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 1, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 47, 47, 47, 47, 47, 47, 47, 47, 0, \r
+ 0, 47, 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, \r
+ 0, 47, 47, 47, 47, 47, 0, 0, 1, 47, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, \r
+ 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 47, 47, 0, 47, 47, \r
+ 47, 1, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 47, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 47, 0, 47, 47, 47, 47, 47, 47, 0, 0, \r
+ 0, 47, 47, 47, 0, 47, 47, 47, 47, 0, 0, 0, 47, 47, 0, 47, 0, 47, 47, 0, \r
+ 0, 0, 47, 47, 0, 0, 0, 47, 47, 47, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, \r
+ 1, 1, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, \r
+ 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 0, 47, 47, 47, 47, 47, 0, 0, 0, 47, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, \r
+ 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 47, 47, 0, 0, 0, 0, 0, 0, \r
+ 47, 47, 1, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 21, 21, 21, 21, 21, 21, 21, 1, 0, 0, 1, 1, 0, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 0, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 0, 0, 1, 47, 1, 1, 1, 1, 1, 1, \r
+ 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, \r
+ 0, 0, 47, 0, 47, 47, 1, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 1, \r
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 0, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 47, 1, 1, 1, 1, \r
+ 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 47, 47, 1, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, \r
+ 21, 21, 21, 21, 21, 21, 0, 0, 0, 1, 47, 47, 47, 47, 47, 47, 0, 0, 1, 1, \r
+ 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 0, 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 1, 0, 0, 0, 0, 1, \r
+ 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 47, 47, 1, 1, 1, \r
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 47, 47, 0, 47, 0, 0, 47, 47, 0, 47, 0, 0, 47, 0, 0, 0, 0, \r
+ 0, 0, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 0, \r
+ 47, 0, 47, 0, 0, 47, 47, 0, 47, 47, 47, 47, 1, 47, 47, 1, 1, 1, 1, 1, 1, \r
+ 0, 1, 1, 47, 0, 0, 47, 47, 47, 47, 47, 0, 47, 0, 1, 1, 1, 1, 1, 1, 0, 0, \r
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 47, 47, 47, 0, 0, 0, 0, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 4, 5, 6, 7, 8, \r
+ 9, 10, 11, 12, 13, 1, 1, 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, \r
+ 47, 47, 47, 47, 1, 1, 1, 47, 1, 1, 1, 47, 47, 1, 1, 1, 1, 1, 1, 1, 47, \r
+ 47, 47, 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, \r
+ 13, 1, 1, 1, 1, 1, 1, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, \r
+ 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, \r
+ 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 47, 0, 0, 0, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 0, 47, 47, 47, 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, \r
+ 0, 47, 47, 47, 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 0, 0, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, \r
+ 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, 0, 47, 47, 47, 47, 0, 0, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 0, 47, 47, 47, 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 17, 18, 113, 114, 115, \r
+ 116, 117, 118, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 2, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 1, 1, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 21, 21, 21, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 0, 47, 47, 47, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 47, 1, 1, 1, 1, 47, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, \r
+ 13, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, \r
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 4, 5, 6, 7, 8, 9, \r
+ 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, \r
+ 47, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 4, 5, 6, \r
+ 7, 8, 9, 10, 11, 12, 13, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 0, 0, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, 1, 1, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, \r
+ 8, 9, 10, 11, 12, 13, 5, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 1, 1, 1, 1, 1, 0, 0, 1, 1, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 0, 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, \r
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, \r
+ 47, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, \r
+ 10, 11, 12, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, \r
+ 0, 0, 47, 47, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 4, 5, 6, 7, 8, 9, 10, \r
+ 11, 12, 13, 0, 0, 0, 47, 47, 47, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 47, 47, 47, 1, 47, 47, 47, 47, 1, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 47, 119, 16, 16, 16, 120, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 16, 16, 16, 16, 16, 121, 16, 16, 122, 16, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 123, \r
+ 123, 123, 123, 123, 123, 123, 123, 124, 124, 124, 124, 124, 124, 124, \r
+ 124, 123, 123, 123, 123, 123, 123, 0, 0, 124, 124, 124, 124, 124, 124, 0, \r
+ 0, 123, 123, 123, 123, 123, 123, 123, 123, 124, 124, 124, 124, 124, 124, \r
+ 124, 124, 123, 123, 123, 123, 123, 123, 123, 123, 124, 124, 124, 124, \r
+ 124, 124, 124, 124, 123, 123, 123, 123, 123, 123, 0, 0, 124, 124, 124, \r
+ 124, 124, 124, 0, 0, 16, 123, 16, 123, 16, 123, 16, 123, 0, 124, 0, 124, \r
+ 0, 124, 0, 124, 123, 123, 123, 123, 123, 123, 123, 123, 124, 124, 124, \r
+ 124, 124, 124, 124, 124, 125, 125, 126, 126, 126, 126, 127, 127, 128, \r
+ 128, 129, 129, 130, 130, 0, 0, 123, 123, 123, 123, 123, 123, 123, 123, \r
+ 131, 131, 131, 131, 131, 131, 131, 131, 123, 123, 123, 123, 123, 123, \r
+ 123, 123, 131, 131, 131, 131, 131, 131, 131, 131, 123, 123, 123, 123, \r
+ 123, 123, 123, 123, 131, 131, 131, 131, 131, 131, 131, 131, 123, 123, 16, \r
+ 132, 16, 0, 16, 16, 124, 124, 133, 133, 134, 1, 135, 1, 1, 1, 16, 132, \r
+ 16, 0, 16, 16, 136, 136, 136, 136, 134, 1, 1, 1, 123, 123, 16, 16, 0, 0, \r
+ 16, 16, 124, 124, 137, 137, 0, 1, 1, 1, 123, 123, 16, 16, 16, 103, 16, \r
+ 16, 124, 124, 138, 138, 106, 1, 1, 1, 0, 0, 16, 132, 16, 0, 16, 16, 139, \r
+ 139, 140, 140, 134, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 3, 3, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, \r
+ 1, 141, 47, 0, 0, 113, 114, 115, 116, 117, 118, 1, 1, 1, 1, 1, 47, 141, \r
+ 20, 17, 18, 113, 114, 115, 116, 117, 118, 1, 1, 1, 1, 1, 0, 47, 47, 47, \r
+ 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 97, 1, 1, 1, 1, 97, 1, 1, \r
+ 16, 97, 97, 97, 16, 16, 97, 97, 97, 16, 1, 97, 1, 1, 1, 97, 97, 97, 97, \r
+ 97, 1, 1, 1, 1, 1, 1, 97, 1, 142, 1, 97, 1, 143, 144, 97, 97, 1, 16, 97, \r
+ 97, 145, 97, 16, 47, 47, 47, 47, 16, 1, 1, 16, 16, 97, 97, 1, 1, 1, 1, 1, \r
+ 97, 16, 16, 16, 16, 1, 1, 1, 1, 146, 1, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 147, 147, 147, 147, 147, 147, 147, 147, \r
+ 147, 147, 147, 147, 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, \r
+ 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 21, 21, 21, 23, 24, 21, \r
+ 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 17, 18, 113, \r
+ 114, 115, 116, 117, 118, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, \r
+ 17, 18, 113, 114, 115, 116, 117, 118, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 20, 17, 18, 113, 114, 115, 116, 117, 118, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, \r
+ 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, \r
+ 149, 149, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, \r
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, \r
+ 141, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 17, 18, 113, 114, 115, \r
+ 116, 117, 118, 21, 141, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, \r
+ 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, \r
+ 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 17, 18, 113, 114, 115, 116, \r
+ 117, 118, 21, 20, 17, 18, 113, 114, 115, 116, 117, 118, 21, 20, 17, 18, \r
+ 113, 114, 115, 116, 117, 118, 21, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, \r
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, \r
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, \r
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 0, 111, 111, 111, 111, 111, \r
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, \r
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, \r
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 0, \r
+ 23, 24, 151, 152, 153, 154, 155, 23, 24, 23, 24, 23, 24, 156, 157, 158, \r
+ 159, 16, 23, 24, 16, 23, 24, 16, 16, 16, 16, 16, 16, 47, 160, 160, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 16, 1, 1, 1, 1, 1, 1, 23, 24, 23, 24, \r
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 21, 1, 1, 161, 161, 161, 161, \r
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, \r
+ 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, \r
+ 161, 161, 161, 161, 161, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 0, \r
+ 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, \r
+ 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, \r
+ 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 47, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 47, 47, 21, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 47, 47, 47, 47, 47, 1, 1, 21, 21, \r
+ 21, 47, 47, 1, 1, 1, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 0, 0, 1, 1, 1, 1, 47, 47, 47, 1, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 47, 47, 47, 47, 0, 0, 0, 0, 0, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 1, 1, 21, 21, 21, 21, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 0, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 162, 47, 47, 162, \r
+ 47, 47, 47, 162, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, \r
+ 162, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 162, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, \r
+ 47, 162, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 162, \r
+ 162, 162, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 162, 162, 162, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, \r
+ 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 162, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 162, 162, 47, 162, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, \r
+ 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 47, \r
+ 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, \r
+ 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, \r
+ 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 0, 0, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 47, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, \r
+ 1, 1, 47, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, \r
+ 23, 24, 23, 24, 23, 24, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 1, 1, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 16, 16, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 47, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 23, 24, 23, 24, 163, 23, 24, 23, 24, 23, 24, 23, 24, 23, \r
+ 24, 47, 1, 1, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, \r
+ 47, 47, 47, 47, 47, 1, 47, 47, 47, 1, 47, 47, 47, 47, 1, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 1, 1, \r
+ 1, 1, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 4, 5, 6, 7, 8, 9, 10, \r
+ 11, 12, 13, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 1, 1, 1, 47, 0, 0, 0, 0, 4, 5, 6, 7, \r
+ 8, 9, 10, 11, 12, 13, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 0, 0, 0, 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 0, 47, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 1, 1, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 1, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 1, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 1, 1, 1, \r
+ 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 1, 1, 1, 47, 1, 0, 0, 0, 0, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 1, 47, 1, 1, 1, 47, 47, 1, 1, 47, 47, 47, 47, \r
+ 47, 1, 1, 47, 1, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, \r
+ 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 162, \r
+ 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 162, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 47, 1, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 0, 47, 47, 47, 47, 47, 0, 47, 0, 47, 47, 0, 47, 47, 0, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 0, 0, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 47, 47, 47, 47, 47, 0, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 1, 1, 1, 1, \r
+ 1, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, \r
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 1, 1, 1, 1, 1, 1, 15, 15, 15, 15, 15, \r
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, \r
+ 15, 15, 15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 47, 47, 47, 47, 47, 47, \r
+ 0, 0, 47, 47, 47, 47, 47, 47, 0, 0, 47, 47, 47, 47, 47, 47, 0, 0, 47, 47, \r
+ 47, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 0, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, \r
+ 0, 1, 1, 1, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 21, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 0, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 21, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 0, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 1, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, \r
+ 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, \r
+ 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 165, \r
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, \r
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, \r
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 0, 0, 47, 0, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 0, 47, 47, 0, 0, 0, 47, 0, 0, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 1, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 21, \r
+ 21, 21, 21, 21, 21, 0, 0, 0, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, \r
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 1, 1, 1, 0, \r
+ 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 47, 47, 47, 47, 0, 47, 47, 47, 0, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 20, \r
+ 17, 18, 113, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 21, 21, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 20, 17, 18, 113, 114, 115, 116, 117, 118, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 0, 1, 1, 1, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 1, 1, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 1, 1, 21, 21, 21, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, \r
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, \r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 16, 16, 16, 16, \r
+ 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 97, 0, 97, 97, 0, 0, 97, 0, 0, 97, 97, 0, 0, 97, 97, 97, 97, 0, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 16, 16, 16, 16, 0, 16, 0, 16, 16, 16, 16, \r
+ 16, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 97, 97, 0, 97, 97, \r
+ 97, 97, 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 0, 97, 97, 97, 97, 97, 97, \r
+ 97, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 97, 97, 0, 97, 97, 97, 97, 0, 97, \r
+ 97, 97, 97, 97, 0, 97, 0, 0, 0, 97, 97, 97, 97, 97, 97, 97, 0, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 16, 16, 16, 16, 16, \r
+ 16, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 16, \r
+ 16, 16, 16, 16, 16, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 1, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 1, 16, 16, 16, 16, 16, 16, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 1, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 1, 16, 16, 16, 16, 16, 16, 97, 97, 97, 97, 97, \r
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, \r
+ 97, 97, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \r
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 16, 16, 16, 16, 16, 16, 97, \r
+ 16, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 5, 6, 7, 8, 9, 10, 11, 12, \r
+ 13, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, \r
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 141, 141, 20, 17, 18, 113, 114, 115, 116, 117, 118, 0, 0, 0, 0, \r
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, \r
+ 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 162, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, \r
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \r
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \r
+};\r
+\r
+/* Returns the numeric value as double for Unicode characters\r
+ * having this property, -1.0 otherwise.\r
+ */\r
+double _PyUnicode_ToNumeric(Py_UNICODE ch)\r
+{\r
+ switch (ch) {\r
+ case 0x0F33:\r
+ return (double) -1.0/2.0;\r
+ case 0x0030:\r
+ case 0x0660:\r
+ case 0x06F0:\r
+ case 0x07C0:\r
+ case 0x0966:\r
+ case 0x09E6:\r
+ case 0x0A66:\r
+ case 0x0AE6:\r
+ case 0x0B66:\r
+ case 0x0BE6:\r
+ case 0x0C66:\r
+ case 0x0C78:\r
+ case 0x0CE6:\r
+ case 0x0D66:\r
+ case 0x0E50:\r
+ case 0x0ED0:\r
+ case 0x0F20:\r
+ case 0x1040:\r
+ case 0x1090:\r
+ case 0x17E0:\r
+ case 0x17F0:\r
+ case 0x1810:\r
+ case 0x1946:\r
+ case 0x19D0:\r
+ case 0x1A80:\r
+ case 0x1A90:\r
+ case 0x1B50:\r
+ case 0x1BB0:\r
+ case 0x1C40:\r
+ case 0x1C50:\r
+ case 0x2070:\r
+ case 0x2080:\r
+ case 0x2189:\r
+ case 0x24EA:\r
+ case 0x24FF:\r
+ case 0x3007:\r
+ case 0x96F6:\r
+ case 0xA620:\r
+ case 0xA6EF:\r
+ case 0xA8D0:\r
+ case 0xA900:\r
+ case 0xA9D0:\r
+ case 0xAA50:\r
+ case 0xABF0:\r
+ case 0xF9B2:\r
+ case 0xFF10:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1018A:\r
+ case 0x104A0:\r
+ case 0x1D7CE:\r
+ case 0x1D7D8:\r
+ case 0x1D7E2:\r
+ case 0x1D7EC:\r
+ case 0x1D7F6:\r
+ case 0x1F100:\r
+ case 0x1F101:\r
+#endif\r
+ return (double) 0.0;\r
+ case 0x0031:\r
+ case 0x00B9:\r
+ case 0x0661:\r
+ case 0x06F1:\r
+ case 0x07C1:\r
+ case 0x0967:\r
+ case 0x09E7:\r
+ case 0x0A67:\r
+ case 0x0AE7:\r
+ case 0x0B67:\r
+ case 0x0BE7:\r
+ case 0x0C67:\r
+ case 0x0C79:\r
+ case 0x0C7C:\r
+ case 0x0CE7:\r
+ case 0x0D67:\r
+ case 0x0E51:\r
+ case 0x0ED1:\r
+ case 0x0F21:\r
+ case 0x1041:\r
+ case 0x1091:\r
+ case 0x1369:\r
+ case 0x17E1:\r
+ case 0x17F1:\r
+ case 0x1811:\r
+ case 0x1947:\r
+ case 0x19D1:\r
+ case 0x19DA:\r
+ case 0x1A81:\r
+ case 0x1A91:\r
+ case 0x1B51:\r
+ case 0x1BB1:\r
+ case 0x1C41:\r
+ case 0x1C51:\r
+ case 0x2081:\r
+ case 0x215F:\r
+ case 0x2160:\r
+ case 0x2170:\r
+ case 0x2460:\r
+ case 0x2474:\r
+ case 0x2488:\r
+ case 0x24F5:\r
+ case 0x2776:\r
+ case 0x2780:\r
+ case 0x278A:\r
+ case 0x3021:\r
+ case 0x3192:\r
+ case 0x3220:\r
+ case 0x3280:\r
+ case 0x4E00:\r
+ case 0x58F1:\r
+ case 0x58F9:\r
+ case 0x5E7A:\r
+ case 0x5F0C:\r
+ case 0xA621:\r
+ case 0xA6E6:\r
+ case 0xA8D1:\r
+ case 0xA901:\r
+ case 0xA9D1:\r
+ case 0xAA51:\r
+ case 0xABF1:\r
+ case 0xFF11:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10107:\r
+ case 0x10142:\r
+ case 0x10158:\r
+ case 0x10159:\r
+ case 0x1015A:\r
+ case 0x10320:\r
+ case 0x103D1:\r
+ case 0x104A1:\r
+ case 0x10858:\r
+ case 0x10916:\r
+ case 0x10A40:\r
+ case 0x10A7D:\r
+ case 0x10B58:\r
+ case 0x10B78:\r
+ case 0x10E60:\r
+ case 0x12415:\r
+ case 0x1241E:\r
+ case 0x1242C:\r
+ case 0x12434:\r
+ case 0x1244F:\r
+ case 0x12458:\r
+ case 0x1D360:\r
+ case 0x1D7CF:\r
+ case 0x1D7D9:\r
+ case 0x1D7E3:\r
+ case 0x1D7ED:\r
+ case 0x1D7F7:\r
+ case 0x1F102:\r
+ case 0x2092A:\r
+#endif\r
+ return (double) 1.0;\r
+ case 0x2152:\r
+ return (double) 1.0/10.0;\r
+ case 0x09F4:\r
+ case 0xA833:\r
+ return (double) 1.0/16.0;\r
+ case 0x00BD:\r
+ case 0x0D74:\r
+ case 0x0F2A:\r
+ case 0x2CFD:\r
+ case 0xA831:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10141:\r
+ case 0x10175:\r
+ case 0x10176:\r
+ case 0x10E7B:\r
+#endif\r
+ return (double) 1.0/2.0;\r
+ case 0x2153:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10E7D:\r
+ case 0x1245A:\r
+ case 0x1245D:\r
+#endif\r
+ return (double) 1.0/3.0;\r
+ case 0x00BC:\r
+ case 0x09F7:\r
+ case 0x0D73:\r
+ case 0xA830:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10140:\r
+ case 0x10E7C:\r
+ case 0x12460:\r
+ case 0x12462:\r
+#endif\r
+ return (double) 1.0/4.0;\r
+ case 0x2155:\r
+ return (double) 1.0/5.0;\r
+ case 0x2159:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x12461:\r
+#endif\r
+ return (double) 1.0/6.0;\r
+ case 0x2150:\r
+ return (double) 1.0/7.0;\r
+ case 0x09F5:\r
+ case 0x215B:\r
+ case 0xA834:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1245F:\r
+#endif\r
+ return (double) 1.0/8.0;\r
+ case 0x2151:\r
+ return (double) 1.0/9.0;\r
+ case 0x0BF0:\r
+ case 0x0D70:\r
+ case 0x1372:\r
+ case 0x2169:\r
+ case 0x2179:\r
+ case 0x2469:\r
+ case 0x247D:\r
+ case 0x2491:\r
+ case 0x24FE:\r
+ case 0x277F:\r
+ case 0x2789:\r
+ case 0x2793:\r
+ case 0x3038:\r
+ case 0x3229:\r
+ case 0x3289:\r
+ case 0x4EC0:\r
+ case 0x5341:\r
+ case 0x62FE:\r
+ case 0xF973:\r
+ case 0xF9FD:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10110:\r
+ case 0x10149:\r
+ case 0x10150:\r
+ case 0x10157:\r
+ case 0x10160:\r
+ case 0x10161:\r
+ case 0x10162:\r
+ case 0x10163:\r
+ case 0x10164:\r
+ case 0x10322:\r
+ case 0x103D3:\r
+ case 0x1085B:\r
+ case 0x10917:\r
+ case 0x10A44:\r
+ case 0x10B5C:\r
+ case 0x10B7C:\r
+ case 0x10E69:\r
+ case 0x1D369:\r
+#endif\r
+ return (double) 10.0;\r
+ case 0x0BF1:\r
+ case 0x0D71:\r
+ case 0x137B:\r
+ case 0x216D:\r
+ case 0x217D:\r
+ case 0x4F70:\r
+ case 0x767E:\r
+ case 0x964C:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10119:\r
+ case 0x1014B:\r
+ case 0x10152:\r
+ case 0x1016A:\r
+ case 0x103D5:\r
+ case 0x1085D:\r
+ case 0x10919:\r
+ case 0x10A46:\r
+ case 0x10B5E:\r
+ case 0x10B7E:\r
+ case 0x10E72:\r
+#endif\r
+ return (double) 100.0;\r
+ case 0x0BF2:\r
+ case 0x0D72:\r
+ case 0x216F:\r
+ case 0x217F:\r
+ case 0x2180:\r
+ case 0x4EDF:\r
+ case 0x5343:\r
+ case 0x9621:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10122:\r
+ case 0x1014D:\r
+ case 0x10154:\r
+ case 0x10171:\r
+ case 0x1085E:\r
+ case 0x10A47:\r
+ case 0x10B5F:\r
+ case 0x10B7F:\r
+#endif\r
+ return (double) 1000.0;\r
+ case 0x137C:\r
+ case 0x2182:\r
+ case 0x4E07:\r
+ case 0x842C:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1012B:\r
+ case 0x10155:\r
+ case 0x1085F:\r
+#endif\r
+ return (double) 10000.0;\r
+ case 0x2188:\r
+ return (double) 100000.0;\r
+ case 0x4EBF:\r
+ case 0x5104:\r
+ return (double) 100000000.0;\r
+ case 0x5146:\r
+ return (double) 1000000000000.0;\r
+ case 0x216A:\r
+ case 0x217A:\r
+ case 0x246A:\r
+ case 0x247E:\r
+ case 0x2492:\r
+ case 0x24EB:\r
+ return (double) 11.0;\r
+ case 0x0F2F:\r
+ return (double) 11.0/2.0;\r
+ case 0x216B:\r
+ case 0x217B:\r
+ case 0x246B:\r
+ case 0x247F:\r
+ case 0x2493:\r
+ case 0x24EC:\r
+ return (double) 12.0;\r
+ case 0x246C:\r
+ case 0x2480:\r
+ case 0x2494:\r
+ case 0x24ED:\r
+ return (double) 13.0;\r
+ case 0x0F30:\r
+ return (double) 13.0/2.0;\r
+ case 0x246D:\r
+ case 0x2481:\r
+ case 0x2495:\r
+ case 0x24EE:\r
+ return (double) 14.0;\r
+ case 0x246E:\r
+ case 0x2482:\r
+ case 0x2496:\r
+ case 0x24EF:\r
+ return (double) 15.0;\r
+ case 0x0F31:\r
+ return (double) 15.0/2.0;\r
+ case 0x09F9:\r
+ case 0x246F:\r
+ case 0x2483:\r
+ case 0x2497:\r
+ case 0x24F0:\r
+ return (double) 16.0;\r
+ case 0x16EE:\r
+ case 0x2470:\r
+ case 0x2484:\r
+ case 0x2498:\r
+ case 0x24F1:\r
+ return (double) 17.0;\r
+ case 0x0F32:\r
+ return (double) 17.0/2.0;\r
+ case 0x16EF:\r
+ case 0x2471:\r
+ case 0x2485:\r
+ case 0x2499:\r
+ case 0x24F2:\r
+ return (double) 18.0;\r
+ case 0x16F0:\r
+ case 0x2472:\r
+ case 0x2486:\r
+ case 0x249A:\r
+ case 0x24F3:\r
+ return (double) 19.0;\r
+ case 0x0032:\r
+ case 0x00B2:\r
+ case 0x0662:\r
+ case 0x06F2:\r
+ case 0x07C2:\r
+ case 0x0968:\r
+ case 0x09E8:\r
+ case 0x0A68:\r
+ case 0x0AE8:\r
+ case 0x0B68:\r
+ case 0x0BE8:\r
+ case 0x0C68:\r
+ case 0x0C7A:\r
+ case 0x0C7D:\r
+ case 0x0CE8:\r
+ case 0x0D68:\r
+ case 0x0E52:\r
+ case 0x0ED2:\r
+ case 0x0F22:\r
+ case 0x1042:\r
+ case 0x1092:\r
+ case 0x136A:\r
+ case 0x17E2:\r
+ case 0x17F2:\r
+ case 0x1812:\r
+ case 0x1948:\r
+ case 0x19D2:\r
+ case 0x1A82:\r
+ case 0x1A92:\r
+ case 0x1B52:\r
+ case 0x1BB2:\r
+ case 0x1C42:\r
+ case 0x1C52:\r
+ case 0x2082:\r
+ case 0x2161:\r
+ case 0x2171:\r
+ case 0x2461:\r
+ case 0x2475:\r
+ case 0x2489:\r
+ case 0x24F6:\r
+ case 0x2777:\r
+ case 0x2781:\r
+ case 0x278B:\r
+ case 0x3022:\r
+ case 0x3193:\r
+ case 0x3221:\r
+ case 0x3281:\r
+ case 0x3483:\r
+ case 0x4E8C:\r
+ case 0x5169:\r
+ case 0x5F0D:\r
+ case 0x5F10:\r
+ case 0x8CAE:\r
+ case 0x8CB3:\r
+ case 0x8D30:\r
+ case 0xA622:\r
+ case 0xA6E7:\r
+ case 0xA8D2:\r
+ case 0xA902:\r
+ case 0xA9D2:\r
+ case 0xAA52:\r
+ case 0xABF2:\r
+ case 0xF978:\r
+ case 0xFF12:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10108:\r
+ case 0x1015B:\r
+ case 0x1015C:\r
+ case 0x1015D:\r
+ case 0x1015E:\r
+ case 0x103D2:\r
+ case 0x104A2:\r
+ case 0x10859:\r
+ case 0x1091A:\r
+ case 0x10A41:\r
+ case 0x10B59:\r
+ case 0x10B79:\r
+ case 0x10E61:\r
+ case 0x12400:\r
+ case 0x12416:\r
+ case 0x1241F:\r
+ case 0x12423:\r
+ case 0x1242D:\r
+ case 0x12435:\r
+ case 0x1244A:\r
+ case 0x12450:\r
+ case 0x12459:\r
+ case 0x1D361:\r
+ case 0x1D7D0:\r
+ case 0x1D7DA:\r
+ case 0x1D7E4:\r
+ case 0x1D7EE:\r
+ case 0x1D7F8:\r
+ case 0x1F103:\r
+ case 0x22390:\r
+#endif\r
+ return (double) 2.0;\r
+ case 0x2154:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10177:\r
+ case 0x10E7E:\r
+ case 0x1245B:\r
+ case 0x1245E:\r
+#endif\r
+ return (double) 2.0/3.0;\r
+ case 0x2156:\r
+ return (double) 2.0/5.0;\r
+ case 0x1373:\r
+ case 0x2473:\r
+ case 0x2487:\r
+ case 0x249B:\r
+ case 0x24F4:\r
+ case 0x3039:\r
+ case 0x5344:\r
+ case 0x5EFF:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10111:\r
+ case 0x103D4:\r
+ case 0x1085C:\r
+ case 0x10918:\r
+ case 0x10A45:\r
+ case 0x10B5D:\r
+ case 0x10B7D:\r
+ case 0x10E6A:\r
+ case 0x1D36A:\r
+#endif\r
+ return (double) 20.0;\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1011A:\r
+ case 0x10E73:\r
+ return (double) 200.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10123:\r
+ return (double) 2000.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1012C:\r
+ return (double) 20000.0;\r
+#endif\r
+ case 0x3251:\r
+ return (double) 21.0;\r
+ case 0x3252:\r
+ return (double) 22.0;\r
+ case 0x3253:\r
+ return (double) 23.0;\r
+ case 0x3254:\r
+ return (double) 24.0;\r
+ case 0x3255:\r
+ return (double) 25.0;\r
+ case 0x3256:\r
+ return (double) 26.0;\r
+ case 0x3257:\r
+ return (double) 27.0;\r
+ case 0x3258:\r
+ return (double) 28.0;\r
+ case 0x3259:\r
+ return (double) 29.0;\r
+ case 0x0033:\r
+ case 0x00B3:\r
+ case 0x0663:\r
+ case 0x06F3:\r
+ case 0x07C3:\r
+ case 0x0969:\r
+ case 0x09E9:\r
+ case 0x0A69:\r
+ case 0x0AE9:\r
+ case 0x0B69:\r
+ case 0x0BE9:\r
+ case 0x0C69:\r
+ case 0x0C7B:\r
+ case 0x0C7E:\r
+ case 0x0CE9:\r
+ case 0x0D69:\r
+ case 0x0E53:\r
+ case 0x0ED3:\r
+ case 0x0F23:\r
+ case 0x1043:\r
+ case 0x1093:\r
+ case 0x136B:\r
+ case 0x17E3:\r
+ case 0x17F3:\r
+ case 0x1813:\r
+ case 0x1949:\r
+ case 0x19D3:\r
+ case 0x1A83:\r
+ case 0x1A93:\r
+ case 0x1B53:\r
+ case 0x1BB3:\r
+ case 0x1C43:\r
+ case 0x1C53:\r
+ case 0x2083:\r
+ case 0x2162:\r
+ case 0x2172:\r
+ case 0x2462:\r
+ case 0x2476:\r
+ case 0x248A:\r
+ case 0x24F7:\r
+ case 0x2778:\r
+ case 0x2782:\r
+ case 0x278C:\r
+ case 0x3023:\r
+ case 0x3194:\r
+ case 0x3222:\r
+ case 0x3282:\r
+ case 0x4E09:\r
+ case 0x4EE8:\r
+ case 0x53C1:\r
+ case 0x53C2:\r
+ case 0x53C3:\r
+ case 0x53C4:\r
+ case 0x5F0E:\r
+ case 0xA623:\r
+ case 0xA6E8:\r
+ case 0xA8D3:\r
+ case 0xA903:\r
+ case 0xA9D3:\r
+ case 0xAA53:\r
+ case 0xABF3:\r
+ case 0xF96B:\r
+ case 0xFF13:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10109:\r
+ case 0x104A3:\r
+ case 0x1085A:\r
+ case 0x1091B:\r
+ case 0x10A42:\r
+ case 0x10B5A:\r
+ case 0x10B7A:\r
+ case 0x10E62:\r
+ case 0x12401:\r
+ case 0x12408:\r
+ case 0x12417:\r
+ case 0x12420:\r
+ case 0x12424:\r
+ case 0x12425:\r
+ case 0x1242E:\r
+ case 0x1242F:\r
+ case 0x12436:\r
+ case 0x12437:\r
+ case 0x1243A:\r
+ case 0x1243B:\r
+ case 0x1244B:\r
+ case 0x12451:\r
+ case 0x1D362:\r
+ case 0x1D7D1:\r
+ case 0x1D7DB:\r
+ case 0x1D7E5:\r
+ case 0x1D7EF:\r
+ case 0x1D7F9:\r
+ case 0x1F104:\r
+ case 0x20AFD:\r
+ case 0x20B19:\r
+ case 0x22998:\r
+ case 0x23B1B:\r
+#endif\r
+ return (double) 3.0;\r
+ case 0x09F6:\r
+ case 0xA835:\r
+ return (double) 3.0/16.0;\r
+ case 0x0F2B:\r
+ return (double) 3.0/2.0;\r
+ case 0x00BE:\r
+ case 0x09F8:\r
+ case 0x0D75:\r
+ case 0xA832:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10178:\r
+#endif\r
+ return (double) 3.0/4.0;\r
+ case 0x2157:\r
+ return (double) 3.0/5.0;\r
+ case 0x215C:\r
+ return (double) 3.0/8.0;\r
+ case 0x1374:\r
+ case 0x303A:\r
+ case 0x325A:\r
+ case 0x5345:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10112:\r
+ case 0x10165:\r
+ case 0x10E6B:\r
+ case 0x1D36B:\r
+ case 0x20983:\r
+#endif\r
+ return (double) 30.0;\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1011B:\r
+ case 0x1016B:\r
+ case 0x10E74:\r
+ return (double) 300.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10124:\r
+ return (double) 3000.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1012D:\r
+ return (double) 30000.0;\r
+#endif\r
+ case 0x325B:\r
+ return (double) 31.0;\r
+ case 0x325C:\r
+ return (double) 32.0;\r
+ case 0x325D:\r
+ return (double) 33.0;\r
+ case 0x325E:\r
+ return (double) 34.0;\r
+ case 0x325F:\r
+ return (double) 35.0;\r
+ case 0x32B1:\r
+ return (double) 36.0;\r
+ case 0x32B2:\r
+ return (double) 37.0;\r
+ case 0x32B3:\r
+ return (double) 38.0;\r
+ case 0x32B4:\r
+ return (double) 39.0;\r
+ case 0x0034:\r
+ case 0x0664:\r
+ case 0x06F4:\r
+ case 0x07C4:\r
+ case 0x096A:\r
+ case 0x09EA:\r
+ case 0x0A6A:\r
+ case 0x0AEA:\r
+ case 0x0B6A:\r
+ case 0x0BEA:\r
+ case 0x0C6A:\r
+ case 0x0CEA:\r
+ case 0x0D6A:\r
+ case 0x0E54:\r
+ case 0x0ED4:\r
+ case 0x0F24:\r
+ case 0x1044:\r
+ case 0x1094:\r
+ case 0x136C:\r
+ case 0x17E4:\r
+ case 0x17F4:\r
+ case 0x1814:\r
+ case 0x194A:\r
+ case 0x19D4:\r
+ case 0x1A84:\r
+ case 0x1A94:\r
+ case 0x1B54:\r
+ case 0x1BB4:\r
+ case 0x1C44:\r
+ case 0x1C54:\r
+ case 0x2074:\r
+ case 0x2084:\r
+ case 0x2163:\r
+ case 0x2173:\r
+ case 0x2463:\r
+ case 0x2477:\r
+ case 0x248B:\r
+ case 0x24F8:\r
+ case 0x2779:\r
+ case 0x2783:\r
+ case 0x278D:\r
+ case 0x3024:\r
+ case 0x3195:\r
+ case 0x3223:\r
+ case 0x3283:\r
+ case 0x4E96:\r
+ case 0x56DB:\r
+ case 0x8086:\r
+ case 0xA624:\r
+ case 0xA6E9:\r
+ case 0xA8D4:\r
+ case 0xA904:\r
+ case 0xA9D4:\r
+ case 0xAA54:\r
+ case 0xABF4:\r
+ case 0xFF14:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1010A:\r
+ case 0x104A4:\r
+ case 0x10A43:\r
+ case 0x10B5B:\r
+ case 0x10B7B:\r
+ case 0x10E63:\r
+ case 0x12402:\r
+ case 0x12409:\r
+ case 0x1240F:\r
+ case 0x12418:\r
+ case 0x12421:\r
+ case 0x12426:\r
+ case 0x12430:\r
+ case 0x12438:\r
+ case 0x1243C:\r
+ case 0x1243D:\r
+ case 0x1243E:\r
+ case 0x1243F:\r
+ case 0x1244C:\r
+ case 0x12452:\r
+ case 0x12453:\r
+ case 0x1D363:\r
+ case 0x1D7D2:\r
+ case 0x1D7DC:\r
+ case 0x1D7E6:\r
+ case 0x1D7F0:\r
+ case 0x1D7FA:\r
+ case 0x1F105:\r
+ case 0x20064:\r
+ case 0x200E2:\r
+ case 0x2626D:\r
+#endif\r
+ return (double) 4.0;\r
+ case 0x2158:\r
+ return (double) 4.0/5.0;\r
+ case 0x1375:\r
+ case 0x32B5:\r
+ case 0x534C:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10113:\r
+ case 0x10E6C:\r
+ case 0x1D36C:\r
+ case 0x2098C:\r
+ case 0x2099C:\r
+#endif\r
+ return (double) 40.0;\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1011C:\r
+ case 0x10E75:\r
+ return (double) 400.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10125:\r
+ return (double) 4000.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1012E:\r
+ return (double) 40000.0;\r
+#endif\r
+ case 0x32B6:\r
+ return (double) 41.0;\r
+ case 0x32B7:\r
+ return (double) 42.0;\r
+ case 0x32B8:\r
+ return (double) 43.0;\r
+ case 0x32B9:\r
+ return (double) 44.0;\r
+ case 0x32BA:\r
+ return (double) 45.0;\r
+ case 0x32BB:\r
+ return (double) 46.0;\r
+ case 0x32BC:\r
+ return (double) 47.0;\r
+ case 0x32BD:\r
+ return (double) 48.0;\r
+ case 0x32BE:\r
+ return (double) 49.0;\r
+ case 0x0035:\r
+ case 0x0665:\r
+ case 0x06F5:\r
+ case 0x07C5:\r
+ case 0x096B:\r
+ case 0x09EB:\r
+ case 0x0A6B:\r
+ case 0x0AEB:\r
+ case 0x0B6B:\r
+ case 0x0BEB:\r
+ case 0x0C6B:\r
+ case 0x0CEB:\r
+ case 0x0D6B:\r
+ case 0x0E55:\r
+ case 0x0ED5:\r
+ case 0x0F25:\r
+ case 0x1045:\r
+ case 0x1095:\r
+ case 0x136D:\r
+ case 0x17E5:\r
+ case 0x17F5:\r
+ case 0x1815:\r
+ case 0x194B:\r
+ case 0x19D5:\r
+ case 0x1A85:\r
+ case 0x1A95:\r
+ case 0x1B55:\r
+ case 0x1BB5:\r
+ case 0x1C45:\r
+ case 0x1C55:\r
+ case 0x2075:\r
+ case 0x2085:\r
+ case 0x2164:\r
+ case 0x2174:\r
+ case 0x2464:\r
+ case 0x2478:\r
+ case 0x248C:\r
+ case 0x24F9:\r
+ case 0x277A:\r
+ case 0x2784:\r
+ case 0x278E:\r
+ case 0x3025:\r
+ case 0x3224:\r
+ case 0x3284:\r
+ case 0x3405:\r
+ case 0x382A:\r
+ case 0x4E94:\r
+ case 0x4F0D:\r
+ case 0xA625:\r
+ case 0xA6EA:\r
+ case 0xA8D5:\r
+ case 0xA905:\r
+ case 0xA9D5:\r
+ case 0xAA55:\r
+ case 0xABF5:\r
+ case 0xFF15:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1010B:\r
+ case 0x10143:\r
+ case 0x10148:\r
+ case 0x1014F:\r
+ case 0x1015F:\r
+ case 0x10173:\r
+ case 0x10321:\r
+ case 0x104A5:\r
+ case 0x10E64:\r
+ case 0x12403:\r
+ case 0x1240A:\r
+ case 0x12410:\r
+ case 0x12419:\r
+ case 0x12422:\r
+ case 0x12427:\r
+ case 0x12431:\r
+ case 0x12439:\r
+ case 0x1244D:\r
+ case 0x12454:\r
+ case 0x12455:\r
+ case 0x1D364:\r
+ case 0x1D7D3:\r
+ case 0x1D7DD:\r
+ case 0x1D7E7:\r
+ case 0x1D7F1:\r
+ case 0x1D7FB:\r
+ case 0x1F106:\r
+ case 0x20121:\r
+#endif\r
+ return (double) 5.0;\r
+ case 0x0F2C:\r
+ return (double) 5.0/2.0;\r
+ case 0x215A:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1245C:\r
+#endif\r
+ return (double) 5.0/6.0;\r
+ case 0x215D:\r
+ return (double) 5.0/8.0;\r
+ case 0x1376:\r
+ case 0x216C:\r
+ case 0x217C:\r
+ case 0x2186:\r
+ case 0x32BF:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10114:\r
+ case 0x10144:\r
+ case 0x1014A:\r
+ case 0x10151:\r
+ case 0x10166:\r
+ case 0x10167:\r
+ case 0x10168:\r
+ case 0x10169:\r
+ case 0x10174:\r
+ case 0x10323:\r
+ case 0x10A7E:\r
+ case 0x10E6D:\r
+ case 0x1D36D:\r
+#endif\r
+ return (double) 50.0;\r
+ case 0x216E:\r
+ case 0x217E:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1011D:\r
+ case 0x10145:\r
+ case 0x1014C:\r
+ case 0x10153:\r
+ case 0x1016C:\r
+ case 0x1016D:\r
+ case 0x1016E:\r
+ case 0x1016F:\r
+ case 0x10170:\r
+ case 0x10E76:\r
+#endif\r
+ return (double) 500.0;\r
+ case 0x2181:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10126:\r
+ case 0x10146:\r
+ case 0x1014E:\r
+ case 0x10172:\r
+#endif\r
+ return (double) 5000.0;\r
+ case 0x2187:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1012F:\r
+ case 0x10147:\r
+ case 0x10156:\r
+#endif\r
+ return (double) 50000.0;\r
+ case 0x0036:\r
+ case 0x0666:\r
+ case 0x06F6:\r
+ case 0x07C6:\r
+ case 0x096C:\r
+ case 0x09EC:\r
+ case 0x0A6C:\r
+ case 0x0AEC:\r
+ case 0x0B6C:\r
+ case 0x0BEC:\r
+ case 0x0C6C:\r
+ case 0x0CEC:\r
+ case 0x0D6C:\r
+ case 0x0E56:\r
+ case 0x0ED6:\r
+ case 0x0F26:\r
+ case 0x1046:\r
+ case 0x1096:\r
+ case 0x136E:\r
+ case 0x17E6:\r
+ case 0x17F6:\r
+ case 0x1816:\r
+ case 0x194C:\r
+ case 0x19D6:\r
+ case 0x1A86:\r
+ case 0x1A96:\r
+ case 0x1B56:\r
+ case 0x1BB6:\r
+ case 0x1C46:\r
+ case 0x1C56:\r
+ case 0x2076:\r
+ case 0x2086:\r
+ case 0x2165:\r
+ case 0x2175:\r
+ case 0x2185:\r
+ case 0x2465:\r
+ case 0x2479:\r
+ case 0x248D:\r
+ case 0x24FA:\r
+ case 0x277B:\r
+ case 0x2785:\r
+ case 0x278F:\r
+ case 0x3026:\r
+ case 0x3225:\r
+ case 0x3285:\r
+ case 0x516D:\r
+ case 0x9646:\r
+ case 0x9678:\r
+ case 0xA626:\r
+ case 0xA6EB:\r
+ case 0xA8D6:\r
+ case 0xA906:\r
+ case 0xA9D6:\r
+ case 0xAA56:\r
+ case 0xABF6:\r
+ case 0xF9D1:\r
+ case 0xF9D3:\r
+ case 0xFF16:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1010C:\r
+ case 0x104A6:\r
+ case 0x10E65:\r
+ case 0x12404:\r
+ case 0x1240B:\r
+ case 0x12411:\r
+ case 0x1241A:\r
+ case 0x12428:\r
+ case 0x12440:\r
+ case 0x1244E:\r
+ case 0x1D365:\r
+ case 0x1D7D4:\r
+ case 0x1D7DE:\r
+ case 0x1D7E8:\r
+ case 0x1D7F2:\r
+ case 0x1D7FC:\r
+ case 0x1F107:\r
+ case 0x20AEA:\r
+#endif\r
+ return (double) 6.0;\r
+ case 0x1377:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10115:\r
+ case 0x10E6E:\r
+ case 0x1D36E:\r
+#endif\r
+ return (double) 60.0;\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1011E:\r
+ case 0x10E77:\r
+ return (double) 600.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10127:\r
+ return (double) 6000.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10130:\r
+ return (double) 60000.0;\r
+#endif\r
+ case 0x0037:\r
+ case 0x0667:\r
+ case 0x06F7:\r
+ case 0x07C7:\r
+ case 0x096D:\r
+ case 0x09ED:\r
+ case 0x0A6D:\r
+ case 0x0AED:\r
+ case 0x0B6D:\r
+ case 0x0BED:\r
+ case 0x0C6D:\r
+ case 0x0CED:\r
+ case 0x0D6D:\r
+ case 0x0E57:\r
+ case 0x0ED7:\r
+ case 0x0F27:\r
+ case 0x1047:\r
+ case 0x1097:\r
+ case 0x136F:\r
+ case 0x17E7:\r
+ case 0x17F7:\r
+ case 0x1817:\r
+ case 0x194D:\r
+ case 0x19D7:\r
+ case 0x1A87:\r
+ case 0x1A97:\r
+ case 0x1B57:\r
+ case 0x1BB7:\r
+ case 0x1C47:\r
+ case 0x1C57:\r
+ case 0x2077:\r
+ case 0x2087:\r
+ case 0x2166:\r
+ case 0x2176:\r
+ case 0x2466:\r
+ case 0x247A:\r
+ case 0x248E:\r
+ case 0x24FB:\r
+ case 0x277C:\r
+ case 0x2786:\r
+ case 0x2790:\r
+ case 0x3027:\r
+ case 0x3226:\r
+ case 0x3286:\r
+ case 0x3B4D:\r
+ case 0x4E03:\r
+ case 0x67D2:\r
+ case 0x6F06:\r
+ case 0xA627:\r
+ case 0xA6EC:\r
+ case 0xA8D7:\r
+ case 0xA907:\r
+ case 0xA9D7:\r
+ case 0xAA57:\r
+ case 0xABF7:\r
+ case 0xFF17:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1010D:\r
+ case 0x104A7:\r
+ case 0x10E66:\r
+ case 0x12405:\r
+ case 0x1240C:\r
+ case 0x12412:\r
+ case 0x1241B:\r
+ case 0x12429:\r
+ case 0x12441:\r
+ case 0x12442:\r
+ case 0x12443:\r
+ case 0x1D366:\r
+ case 0x1D7D5:\r
+ case 0x1D7DF:\r
+ case 0x1D7E9:\r
+ case 0x1D7F3:\r
+ case 0x1D7FD:\r
+ case 0x1F108:\r
+ case 0x20001:\r
+#endif\r
+ return (double) 7.0;\r
+ case 0x0F2D:\r
+ return (double) 7.0/2.0;\r
+ case 0x215E:\r
+ return (double) 7.0/8.0;\r
+ case 0x1378:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10116:\r
+ case 0x10E6F:\r
+ case 0x1D36F:\r
+#endif\r
+ return (double) 70.0;\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1011F:\r
+ case 0x10E78:\r
+ return (double) 700.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10128:\r
+ return (double) 7000.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10131:\r
+ return (double) 70000.0;\r
+#endif\r
+ case 0x0038:\r
+ case 0x0668:\r
+ case 0x06F8:\r
+ case 0x07C8:\r
+ case 0x096E:\r
+ case 0x09EE:\r
+ case 0x0A6E:\r
+ case 0x0AEE:\r
+ case 0x0B6E:\r
+ case 0x0BEE:\r
+ case 0x0C6E:\r
+ case 0x0CEE:\r
+ case 0x0D6E:\r
+ case 0x0E58:\r
+ case 0x0ED8:\r
+ case 0x0F28:\r
+ case 0x1048:\r
+ case 0x1098:\r
+ case 0x1370:\r
+ case 0x17E8:\r
+ case 0x17F8:\r
+ case 0x1818:\r
+ case 0x194E:\r
+ case 0x19D8:\r
+ case 0x1A88:\r
+ case 0x1A98:\r
+ case 0x1B58:\r
+ case 0x1BB8:\r
+ case 0x1C48:\r
+ case 0x1C58:\r
+ case 0x2078:\r
+ case 0x2088:\r
+ case 0x2167:\r
+ case 0x2177:\r
+ case 0x2467:\r
+ case 0x247B:\r
+ case 0x248F:\r
+ case 0x24FC:\r
+ case 0x277D:\r
+ case 0x2787:\r
+ case 0x2791:\r
+ case 0x3028:\r
+ case 0x3227:\r
+ case 0x3287:\r
+ case 0x516B:\r
+ case 0x634C:\r
+ case 0xA628:\r
+ case 0xA6ED:\r
+ case 0xA8D8:\r
+ case 0xA908:\r
+ case 0xA9D8:\r
+ case 0xAA58:\r
+ case 0xABF8:\r
+ case 0xFF18:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1010E:\r
+ case 0x104A8:\r
+ case 0x10E67:\r
+ case 0x12406:\r
+ case 0x1240D:\r
+ case 0x12413:\r
+ case 0x1241C:\r
+ case 0x1242A:\r
+ case 0x12444:\r
+ case 0x12445:\r
+ case 0x1D367:\r
+ case 0x1D7D6:\r
+ case 0x1D7E0:\r
+ case 0x1D7EA:\r
+ case 0x1D7F4:\r
+ case 0x1D7FE:\r
+ case 0x1F109:\r
+#endif\r
+ return (double) 8.0;\r
+ case 0x1379:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10117:\r
+ case 0x10E70:\r
+ case 0x1D370:\r
+#endif\r
+ return (double) 80.0;\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10120:\r
+ case 0x10E79:\r
+ return (double) 800.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10129:\r
+ return (double) 8000.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10132:\r
+ return (double) 80000.0;\r
+#endif\r
+ case 0x0039:\r
+ case 0x0669:\r
+ case 0x06F9:\r
+ case 0x07C9:\r
+ case 0x096F:\r
+ case 0x09EF:\r
+ case 0x0A6F:\r
+ case 0x0AEF:\r
+ case 0x0B6F:\r
+ case 0x0BEF:\r
+ case 0x0C6F:\r
+ case 0x0CEF:\r
+ case 0x0D6F:\r
+ case 0x0E59:\r
+ case 0x0ED9:\r
+ case 0x0F29:\r
+ case 0x1049:\r
+ case 0x1099:\r
+ case 0x1371:\r
+ case 0x17E9:\r
+ case 0x17F9:\r
+ case 0x1819:\r
+ case 0x194F:\r
+ case 0x19D9:\r
+ case 0x1A89:\r
+ case 0x1A99:\r
+ case 0x1B59:\r
+ case 0x1BB9:\r
+ case 0x1C49:\r
+ case 0x1C59:\r
+ case 0x2079:\r
+ case 0x2089:\r
+ case 0x2168:\r
+ case 0x2178:\r
+ case 0x2468:\r
+ case 0x247C:\r
+ case 0x2490:\r
+ case 0x24FD:\r
+ case 0x277E:\r
+ case 0x2788:\r
+ case 0x2792:\r
+ case 0x3029:\r
+ case 0x3228:\r
+ case 0x3288:\r
+ case 0x4E5D:\r
+ case 0x5EFE:\r
+ case 0x7396:\r
+ case 0xA629:\r
+ case 0xA6EE:\r
+ case 0xA8D9:\r
+ case 0xA909:\r
+ case 0xA9D9:\r
+ case 0xAA59:\r
+ case 0xABF9:\r
+ case 0xFF19:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1010F:\r
+ case 0x104A9:\r
+ case 0x10E68:\r
+ case 0x12407:\r
+ case 0x1240E:\r
+ case 0x12414:\r
+ case 0x1241D:\r
+ case 0x1242B:\r
+ case 0x12446:\r
+ case 0x12447:\r
+ case 0x12448:\r
+ case 0x12449:\r
+ case 0x1D368:\r
+ case 0x1D7D7:\r
+ case 0x1D7E1:\r
+ case 0x1D7EB:\r
+ case 0x1D7F5:\r
+ case 0x1D7FF:\r
+ case 0x1F10A:\r
+ case 0x2F890:\r
+#endif\r
+ return (double) 9.0;\r
+ case 0x0F2E:\r
+ return (double) 9.0/2.0;\r
+ case 0x137A:\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10118:\r
+ case 0x10341:\r
+ case 0x10E71:\r
+ case 0x1D371:\r
+#endif\r
+ return (double) 90.0;\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10121:\r
+ case 0x1034A:\r
+ case 0x10E7A:\r
+ return (double) 900.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x1012A:\r
+ return (double) 9000.0;\r
+#endif\r
+#ifdef Py_UNICODE_WIDE\r
+ case 0x10133:\r
+ return (double) 90000.0;\r
+#endif\r
+ }\r
+ return -1.0;\r
+}\r
+\r
+/* Returns 1 for Unicode characters having the bidirectional\r
+ * type 'WS', 'B' or 'S' or the category 'Zs', 0 otherwise.\r
+ */\r
+int _PyUnicode_IsWhitespace(register const Py_UNICODE ch)\r
+{\r
+#ifdef WANT_WCTYPE_FUNCTIONS\r
+ return iswspace(ch);\r
+#else\r
+ switch (ch) {\r
+ case 0x0009:\r
+ case 0x000A:\r
+ case 0x000B:\r
+ case 0x000C:\r
+ case 0x000D:\r
+ case 0x001C:\r
+ case 0x001D:\r
+ case 0x001E:\r
+ case 0x001F:\r
+ case 0x0020:\r
+ case 0x0085:\r
+ case 0x00A0:\r
+ case 0x1680:\r
+ case 0x180E:\r
+ case 0x2000:\r
+ case 0x2001:\r
+ case 0x2002:\r
+ case 0x2003:\r
+ case 0x2004:\r
+ case 0x2005:\r
+ case 0x2006:\r
+ case 0x2007:\r
+ case 0x2008:\r
+ case 0x2009:\r
+ case 0x200A:\r
+ case 0x2028:\r
+ case 0x2029:\r
+ case 0x202F:\r
+ case 0x205F:\r
+ case 0x3000:\r
+ return 1;\r
+ }\r
+ return 0;\r
+#endif\r
+}\r
+\r
+/* Returns 1 for Unicode characters having the line break\r
+ * property 'BK', 'CR', 'LF' or 'NL' or having bidirectional\r
+ * type 'B', 0 otherwise.\r
+ */\r
+int _PyUnicode_IsLinebreak(register const Py_UNICODE ch)\r
+{\r
+ switch (ch) {\r
+ case 0x000A:\r
+ case 0x000B:\r
+ case 0x000C:\r
+ case 0x000D:\r
+ case 0x001C:\r
+ case 0x001D:\r
+ case 0x001E:\r
+ case 0x0085:\r
+ case 0x2028:\r
+ case 0x2029:\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
--- /dev/null
+#include "Python.h"\r
+#include "structmember.h"\r
+\r
+\r
+#define GET_WEAKREFS_LISTPTR(o) \\r
+ ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))\r
+\r
+\r
+Py_ssize_t\r
+_PyWeakref_GetWeakrefCount(PyWeakReference *head)\r
+{\r
+ Py_ssize_t count = 0;\r
+\r
+ while (head != NULL) {\r
+ ++count;\r
+ head = head->wr_next;\r
+ }\r
+ return count;\r
+}\r
+\r
+\r
+static void\r
+init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)\r
+{\r
+ self->hash = -1;\r
+ self->wr_object = ob;\r
+ Py_XINCREF(callback);\r
+ self->wr_callback = callback;\r
+}\r
+\r
+static PyWeakReference *\r
+new_weakref(PyObject *ob, PyObject *callback)\r
+{\r
+ PyWeakReference *result;\r
+\r
+ result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);\r
+ if (result) {\r
+ init_weakref(result, ob, callback);\r
+ PyObject_GC_Track(result);\r
+ }\r
+ return result;\r
+}\r
+\r
+\r
+/* This function clears the passed-in reference and removes it from the\r
+ * list of weak references for the referent. This is the only code that\r
+ * removes an item from the doubly-linked list of weak references for an\r
+ * object; it is also responsible for clearing the callback slot.\r
+ */\r
+static void\r
+clear_weakref(PyWeakReference *self)\r
+{\r
+ PyObject *callback = self->wr_callback;\r
+\r
+ if (self->wr_object != Py_None) {\r
+ PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);\r
+\r
+ if (*list == self)\r
+ /* If 'self' is the end of the list (and thus self->wr_next == NULL)\r
+ then the weakref list itself (and thus the value of *list) will\r
+ end up being set to NULL. */\r
+ *list = self->wr_next;\r
+ self->wr_object = Py_None;\r
+ if (self->wr_prev != NULL)\r
+ self->wr_prev->wr_next = self->wr_next;\r
+ if (self->wr_next != NULL)\r
+ self->wr_next->wr_prev = self->wr_prev;\r
+ self->wr_prev = NULL;\r
+ self->wr_next = NULL;\r
+ }\r
+ if (callback != NULL) {\r
+ Py_DECREF(callback);\r
+ self->wr_callback = NULL;\r
+ }\r
+}\r
+\r
+/* Cyclic gc uses this to *just* clear the passed-in reference, leaving\r
+ * the callback intact and uncalled. It must be possible to call self's\r
+ * tp_dealloc() after calling this, so self has to be left in a sane enough\r
+ * state for that to work. We expect tp_dealloc to decref the callback\r
+ * then. The reason for not letting clear_weakref() decref the callback\r
+ * right now is that if the callback goes away, that may in turn trigger\r
+ * another callback (if a weak reference to the callback exists) -- running\r
+ * arbitrary Python code in the middle of gc is a disaster. The convolution\r
+ * here allows gc to delay triggering such callbacks until the world is in\r
+ * a sane state again.\r
+ */\r
+void\r
+_PyWeakref_ClearRef(PyWeakReference *self)\r
+{\r
+ PyObject *callback;\r
+\r
+ assert(self != NULL);\r
+ assert(PyWeakref_Check(self));\r
+ /* Preserve and restore the callback around clear_weakref. */\r
+ callback = self->wr_callback;\r
+ self->wr_callback = NULL;\r
+ clear_weakref(self);\r
+ self->wr_callback = callback;\r
+}\r
+\r
+static void\r
+weakref_dealloc(PyObject *self)\r
+{\r
+ PyObject_GC_UnTrack(self);\r
+ clear_weakref((PyWeakReference *) self);\r
+ Py_TYPE(self)->tp_free(self);\r
+}\r
+\r
+\r
+static int\r
+gc_traverse(PyWeakReference *self, visitproc visit, void *arg)\r
+{\r
+ Py_VISIT(self->wr_callback);\r
+ return 0;\r
+}\r
+\r
+\r
+static int\r
+gc_clear(PyWeakReference *self)\r
+{\r
+ clear_weakref(self);\r
+ return 0;\r
+}\r
+\r
+\r
+static PyObject *\r
+weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)\r
+{\r
+ static char *kwlist[] = {NULL};\r
+\r
+ if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {\r
+ PyObject *object = PyWeakref_GET_OBJECT(self);\r
+ Py_INCREF(object);\r
+ return (object);\r
+ }\r
+ return NULL;\r
+}\r
+\r
+\r
+static long\r
+weakref_hash(PyWeakReference *self)\r
+{\r
+ if (self->hash != -1)\r
+ return self->hash;\r
+ if (PyWeakref_GET_OBJECT(self) == Py_None) {\r
+ PyErr_SetString(PyExc_TypeError, "weak object has gone away");\r
+ return -1;\r
+ }\r
+ self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));\r
+ return self->hash;\r
+}\r
+\r
+\r
+static PyObject *\r
+weakref_repr(PyWeakReference *self)\r
+{\r
+ char buffer[256];\r
+ if (PyWeakref_GET_OBJECT(self) == Py_None) {\r
+ PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);\r
+ }\r
+ else {\r
+ char *name = NULL;\r
+ PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),\r
+ "__name__");\r
+ if (nameobj == NULL)\r
+ PyErr_Clear();\r
+ else if (PyString_Check(nameobj))\r
+ name = PyString_AS_STRING(nameobj);\r
+ if (name != NULL) {\r
+ PyOS_snprintf(buffer, sizeof(buffer),\r
+ "<weakref at %p; to '%.50s' at %p (%s)>",\r
+ self,\r
+ Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,\r
+ PyWeakref_GET_OBJECT(self),\r
+ name);\r
+ }\r
+ else {\r
+ PyOS_snprintf(buffer, sizeof(buffer),\r
+ "<weakref at %p; to '%.50s' at %p>",\r
+ self,\r
+ Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,\r
+ PyWeakref_GET_OBJECT(self));\r
+ }\r
+ Py_XDECREF(nameobj);\r
+ }\r
+ return PyString_FromString(buffer);\r
+}\r
+\r
+/* Weak references only support equality, not ordering. Two weak references\r
+ are equal if the underlying objects are equal. If the underlying object has\r
+ gone away, they are equal if they are identical. */\r
+\r
+static PyObject *\r
+weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)\r
+{\r
+ if ((op != Py_EQ && op != Py_NE) || self->ob_type != other->ob_type) {\r
+ Py_INCREF(Py_NotImplemented);\r
+ return Py_NotImplemented;\r
+ }\r
+ if (PyWeakref_GET_OBJECT(self) == Py_None\r
+ || PyWeakref_GET_OBJECT(other) == Py_None) {\r
+ int res = (self == other);\r
+ if (op == Py_NE)\r
+ res = !res;\r
+ if (res)\r
+ Py_RETURN_TRUE;\r
+ else\r
+ Py_RETURN_FALSE;\r
+ }\r
+ return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),\r
+ PyWeakref_GET_OBJECT(other), op);\r
+}\r
+\r
+/* Given the head of an object's list of weak references, extract the\r
+ * two callback-less refs (ref and proxy). Used to determine if the\r
+ * shared references exist and to determine the back link for newly\r
+ * inserted references.\r
+ */\r
+static void\r
+get_basic_refs(PyWeakReference *head,\r
+ PyWeakReference **refp, PyWeakReference **proxyp)\r
+{\r
+ *refp = NULL;\r
+ *proxyp = NULL;\r
+\r
+ if (head != NULL && head->wr_callback == NULL) {\r
+ /* We need to be careful that the "basic refs" aren't\r
+ subclasses of the main types. That complicates this a\r
+ little. */\r
+ if (PyWeakref_CheckRefExact(head)) {\r
+ *refp = head;\r
+ head = head->wr_next;\r
+ }\r
+ if (head != NULL\r
+ && head->wr_callback == NULL\r
+ && PyWeakref_CheckProxy(head)) {\r
+ *proxyp = head;\r
+ /* head = head->wr_next; */\r
+ }\r
+ }\r
+}\r
+\r
+/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */\r
+static void\r
+insert_after(PyWeakReference *newref, PyWeakReference *prev)\r
+{\r
+ newref->wr_prev = prev;\r
+ newref->wr_next = prev->wr_next;\r
+ if (prev->wr_next != NULL)\r
+ prev->wr_next->wr_prev = newref;\r
+ prev->wr_next = newref;\r
+}\r
+\r
+/* Insert 'newref' at the head of the list; 'list' points to the variable\r
+ * that stores the head.\r
+ */\r
+static void\r
+insert_head(PyWeakReference *newref, PyWeakReference **list)\r
+{\r
+ PyWeakReference *next = *list;\r
+\r
+ newref->wr_prev = NULL;\r
+ newref->wr_next = next;\r
+ if (next != NULL)\r
+ next->wr_prev = newref;\r
+ *list = newref;\r
+}\r
+\r
+static int\r
+parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,\r
+ PyObject **obp, PyObject **callbackp)\r
+{\r
+ /* XXX Should check that kwargs == NULL or is empty. */\r
+ return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);\r
+}\r
+\r
+static PyObject *\r
+weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)\r
+{\r
+ PyWeakReference *self = NULL;\r
+ PyObject *ob, *callback = NULL;\r
+\r
+ if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {\r
+ PyWeakReference *ref, *proxy;\r
+ PyWeakReference **list;\r
+\r
+ if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "cannot create weak reference to '%s' object",\r
+ Py_TYPE(ob)->tp_name);\r
+ return NULL;\r
+ }\r
+ if (callback == Py_None)\r
+ callback = NULL;\r
+ list = GET_WEAKREFS_LISTPTR(ob);\r
+ get_basic_refs(*list, &ref, &proxy);\r
+ if (callback == NULL && type == &_PyWeakref_RefType) {\r
+ if (ref != NULL) {\r
+ /* We can re-use an existing reference. */\r
+ Py_INCREF(ref);\r
+ return (PyObject *)ref;\r
+ }\r
+ }\r
+ /* We have to create a new reference. */\r
+ /* Note: the tp_alloc() can trigger cyclic GC, so the weakref\r
+ list on ob can be mutated. This means that the ref and\r
+ proxy pointers we got back earlier may have been collected,\r
+ so we need to compute these values again before we use\r
+ them. */\r
+ self = (PyWeakReference *) (type->tp_alloc(type, 0));\r
+ if (self != NULL) {\r
+ init_weakref(self, ob, callback);\r
+ if (callback == NULL && type == &_PyWeakref_RefType) {\r
+ insert_head(self, list);\r
+ }\r
+ else {\r
+ PyWeakReference *prev;\r
+\r
+ get_basic_refs(*list, &ref, &proxy);\r
+ prev = (proxy == NULL) ? ref : proxy;\r
+ if (prev == NULL)\r
+ insert_head(self, list);\r
+ else\r
+ insert_after(self, prev);\r
+ }\r
+ }\r
+ }\r
+ return (PyObject *)self;\r
+}\r
+\r
+static int\r
+weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)\r
+{\r
+ PyObject *tmp;\r
+\r
+ if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))\r
+ return 0;\r
+ else\r
+ return -1;\r
+}\r
+\r
+\r
+PyTypeObject\r
+_PyWeakref_RefType = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "weakref",\r
+ sizeof(PyWeakReference),\r
+ 0,\r
+ weakref_dealloc, /*tp_dealloc*/\r
+ 0, /*tp_print*/\r
+ 0, /*tp_getattr*/\r
+ 0, /*tp_setattr*/\r
+ 0, /*tp_compare*/\r
+ (reprfunc)weakref_repr, /*tp_repr*/\r
+ 0, /*tp_as_number*/\r
+ 0, /*tp_as_sequence*/\r
+ 0, /*tp_as_mapping*/\r
+ (hashfunc)weakref_hash, /*tp_hash*/\r
+ (ternaryfunc)weakref_call, /*tp_call*/\r
+ 0, /*tp_str*/\r
+ 0, /*tp_getattro*/\r
+ 0, /*tp_setattro*/\r
+ 0, /*tp_as_buffer*/\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE\r
+ | Py_TPFLAGS_BASETYPE, /*tp_flags*/\r
+ 0, /*tp_doc*/\r
+ (traverseproc)gc_traverse, /*tp_traverse*/\r
+ (inquiry)gc_clear, /*tp_clear*/\r
+ (richcmpfunc)weakref_richcompare, /*tp_richcompare*/\r
+ 0, /*tp_weaklistoffset*/\r
+ 0, /*tp_iter*/\r
+ 0, /*tp_iternext*/\r
+ 0, /*tp_methods*/\r
+ 0, /*tp_members*/\r
+ 0, /*tp_getset*/\r
+ 0, /*tp_base*/\r
+ 0, /*tp_dict*/\r
+ 0, /*tp_descr_get*/\r
+ 0, /*tp_descr_set*/\r
+ 0, /*tp_dictoffset*/\r
+ weakref___init__, /*tp_init*/\r
+ PyType_GenericAlloc, /*tp_alloc*/\r
+ weakref___new__, /*tp_new*/\r
+ PyObject_GC_Del, /*tp_free*/\r
+};\r
+\r
+\r
+static int\r
+proxy_checkref(PyWeakReference *proxy)\r
+{\r
+ if (PyWeakref_GET_OBJECT(proxy) == Py_None) {\r
+ PyErr_SetString(PyExc_ReferenceError,\r
+ "weakly-referenced object no longer exists");\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+\r
+/* If a parameter is a proxy, check that it is still "live" and wrap it,\r
+ * replacing the original value with the raw object. Raises ReferenceError\r
+ * if the param is a dead proxy.\r
+ */\r
+#define UNWRAP(o) \\r
+ if (PyWeakref_CheckProxy(o)) { \\r
+ if (!proxy_checkref((PyWeakReference *)o)) \\r
+ return NULL; \\r
+ o = PyWeakref_GET_OBJECT(o); \\r
+ }\r
+\r
+#define UNWRAP_I(o) \\r
+ if (PyWeakref_CheckProxy(o)) { \\r
+ if (!proxy_checkref((PyWeakReference *)o)) \\r
+ return -1; \\r
+ o = PyWeakref_GET_OBJECT(o); \\r
+ }\r
+\r
+#define WRAP_UNARY(method, generic) \\r
+ static PyObject * \\r
+ method(PyObject *proxy) { \\r
+ UNWRAP(proxy); \\r
+ return generic(proxy); \\r
+ }\r
+\r
+#define WRAP_BINARY(method, generic) \\r
+ static PyObject * \\r
+ method(PyObject *x, PyObject *y) { \\r
+ UNWRAP(x); \\r
+ UNWRAP(y); \\r
+ return generic(x, y); \\r
+ }\r
+\r
+/* Note that the third arg needs to be checked for NULL since the tp_call\r
+ * slot can receive NULL for this arg.\r
+ */\r
+#define WRAP_TERNARY(method, generic) \\r
+ static PyObject * \\r
+ method(PyObject *proxy, PyObject *v, PyObject *w) { \\r
+ UNWRAP(proxy); \\r
+ UNWRAP(v); \\r
+ if (w != NULL) \\r
+ UNWRAP(w); \\r
+ return generic(proxy, v, w); \\r
+ }\r
+\r
+#define WRAP_METHOD(method, special) \\r
+ static PyObject * \\r
+ method(PyObject *proxy) { \\r
+ UNWRAP(proxy); \\r
+ return PyObject_CallMethod(proxy, special, ""); \\r
+ }\r
+\r
+\r
+/* direct slots */\r
+\r
+WRAP_BINARY(proxy_getattr, PyObject_GetAttr)\r
+WRAP_UNARY(proxy_str, PyObject_Str)\r
+WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)\r
+\r
+static PyObject *\r
+proxy_repr(PyWeakReference *proxy)\r
+{\r
+ char buf[160];\r
+ PyOS_snprintf(buf, sizeof(buf),\r
+ "<weakproxy at %p to %.100s at %p>", proxy,\r
+ Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,\r
+ PyWeakref_GET_OBJECT(proxy));\r
+ return PyString_FromString(buf);\r
+}\r
+\r
+\r
+static int\r
+proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)\r
+{\r
+ if (!proxy_checkref(proxy))\r
+ return -1;\r
+ return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);\r
+}\r
+\r
+static int\r
+proxy_compare(PyObject *proxy, PyObject *v)\r
+{\r
+ UNWRAP_I(proxy);\r
+ UNWRAP_I(v);\r
+ return PyObject_Compare(proxy, v);\r
+}\r
+\r
+/* number slots */\r
+WRAP_BINARY(proxy_add, PyNumber_Add)\r
+WRAP_BINARY(proxy_sub, PyNumber_Subtract)\r
+WRAP_BINARY(proxy_mul, PyNumber_Multiply)\r
+WRAP_BINARY(proxy_div, PyNumber_Divide)\r
+WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)\r
+WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)\r
+WRAP_BINARY(proxy_mod, PyNumber_Remainder)\r
+WRAP_BINARY(proxy_divmod, PyNumber_Divmod)\r
+WRAP_TERNARY(proxy_pow, PyNumber_Power)\r
+WRAP_UNARY(proxy_neg, PyNumber_Negative)\r
+WRAP_UNARY(proxy_pos, PyNumber_Positive)\r
+WRAP_UNARY(proxy_abs, PyNumber_Absolute)\r
+WRAP_UNARY(proxy_invert, PyNumber_Invert)\r
+WRAP_BINARY(proxy_lshift, PyNumber_Lshift)\r
+WRAP_BINARY(proxy_rshift, PyNumber_Rshift)\r
+WRAP_BINARY(proxy_and, PyNumber_And)\r
+WRAP_BINARY(proxy_xor, PyNumber_Xor)\r
+WRAP_BINARY(proxy_or, PyNumber_Or)\r
+WRAP_UNARY(proxy_int, PyNumber_Int)\r
+WRAP_UNARY(proxy_long, PyNumber_Long)\r
+WRAP_UNARY(proxy_float, PyNumber_Float)\r
+WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)\r
+WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)\r
+WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)\r
+WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)\r
+WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)\r
+WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)\r
+WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)\r
+WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)\r
+WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)\r
+WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)\r
+WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)\r
+WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)\r
+WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)\r
+WRAP_UNARY(proxy_index, PyNumber_Index)\r
+\r
+static int\r
+proxy_nonzero(PyWeakReference *proxy)\r
+{\r
+ PyObject *o = PyWeakref_GET_OBJECT(proxy);\r
+ if (!proxy_checkref(proxy))\r
+ return -1;\r
+ return PyObject_IsTrue(o);\r
+}\r
+\r
+static void\r
+proxy_dealloc(PyWeakReference *self)\r
+{\r
+ if (self->wr_callback != NULL)\r
+ PyObject_GC_UnTrack((PyObject *)self);\r
+ clear_weakref(self);\r
+ PyObject_GC_Del(self);\r
+}\r
+\r
+/* sequence slots */\r
+\r
+static PyObject *\r
+proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)\r
+{\r
+ if (!proxy_checkref(proxy))\r
+ return NULL;\r
+ return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);\r
+}\r
+\r
+static int\r
+proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)\r
+{\r
+ if (!proxy_checkref(proxy))\r
+ return -1;\r
+ return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);\r
+}\r
+\r
+static int\r
+proxy_contains(PyWeakReference *proxy, PyObject *value)\r
+{\r
+ if (!proxy_checkref(proxy))\r
+ return -1;\r
+ return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);\r
+}\r
+\r
+\r
+/* mapping slots */\r
+\r
+static Py_ssize_t\r
+proxy_length(PyWeakReference *proxy)\r
+{\r
+ if (!proxy_checkref(proxy))\r
+ return -1;\r
+ return PyObject_Length(PyWeakref_GET_OBJECT(proxy));\r
+}\r
+\r
+WRAP_BINARY(proxy_getitem, PyObject_GetItem)\r
+\r
+static int\r
+proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)\r
+{\r
+ if (!proxy_checkref(proxy))\r
+ return -1;\r
+\r
+ if (value == NULL)\r
+ return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);\r
+ else\r
+ return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);\r
+}\r
+\r
+/* iterator slots */\r
+\r
+static PyObject *\r
+proxy_iter(PyWeakReference *proxy)\r
+{\r
+ if (!proxy_checkref(proxy))\r
+ return NULL;\r
+ return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));\r
+}\r
+\r
+static PyObject *\r
+proxy_iternext(PyWeakReference *proxy)\r
+{\r
+ if (!proxy_checkref(proxy))\r
+ return NULL;\r
+ return PyIter_Next(PyWeakref_GET_OBJECT(proxy));\r
+}\r
+\r
+\r
+WRAP_METHOD(proxy_unicode, "__unicode__");\r
+\r
+\r
+static PyMethodDef proxy_methods[] = {\r
+ {"__unicode__", (PyCFunction)proxy_unicode, METH_NOARGS},\r
+ {NULL, NULL}\r
+};\r
+\r
+\r
+static PyNumberMethods proxy_as_number = {\r
+ proxy_add, /*nb_add*/\r
+ proxy_sub, /*nb_subtract*/\r
+ proxy_mul, /*nb_multiply*/\r
+ proxy_div, /*nb_divide*/\r
+ proxy_mod, /*nb_remainder*/\r
+ proxy_divmod, /*nb_divmod*/\r
+ proxy_pow, /*nb_power*/\r
+ proxy_neg, /*nb_negative*/\r
+ proxy_pos, /*nb_positive*/\r
+ proxy_abs, /*nb_absolute*/\r
+ (inquiry)proxy_nonzero, /*nb_nonzero*/\r
+ proxy_invert, /*nb_invert*/\r
+ proxy_lshift, /*nb_lshift*/\r
+ proxy_rshift, /*nb_rshift*/\r
+ proxy_and, /*nb_and*/\r
+ proxy_xor, /*nb_xor*/\r
+ proxy_or, /*nb_or*/\r
+ 0, /*nb_coerce*/\r
+ proxy_int, /*nb_int*/\r
+ proxy_long, /*nb_long*/\r
+ proxy_float, /*nb_float*/\r
+ 0, /*nb_oct*/\r
+ 0, /*nb_hex*/\r
+ proxy_iadd, /*nb_inplace_add*/\r
+ proxy_isub, /*nb_inplace_subtract*/\r
+ proxy_imul, /*nb_inplace_multiply*/\r
+ proxy_idiv, /*nb_inplace_divide*/\r
+ proxy_imod, /*nb_inplace_remainder*/\r
+ proxy_ipow, /*nb_inplace_power*/\r
+ proxy_ilshift, /*nb_inplace_lshift*/\r
+ proxy_irshift, /*nb_inplace_rshift*/\r
+ proxy_iand, /*nb_inplace_and*/\r
+ proxy_ixor, /*nb_inplace_xor*/\r
+ proxy_ior, /*nb_inplace_or*/\r
+ proxy_floor_div, /*nb_floor_divide*/\r
+ proxy_true_div, /*nb_true_divide*/\r
+ proxy_ifloor_div, /*nb_inplace_floor_divide*/\r
+ proxy_itrue_div, /*nb_inplace_true_divide*/\r
+ proxy_index, /*nb_index*/\r
+};\r
+\r
+static PySequenceMethods proxy_as_sequence = {\r
+ (lenfunc)proxy_length, /*sq_length*/\r
+ 0, /*sq_concat*/\r
+ 0, /*sq_repeat*/\r
+ 0, /*sq_item*/\r
+ (ssizessizeargfunc)proxy_slice, /*sq_slice*/\r
+ 0, /*sq_ass_item*/\r
+ (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/\r
+ (objobjproc)proxy_contains, /* sq_contains */\r
+};\r
+\r
+static PyMappingMethods proxy_as_mapping = {\r
+ (lenfunc)proxy_length, /*mp_length*/\r
+ proxy_getitem, /*mp_subscript*/\r
+ (objobjargproc)proxy_setitem, /*mp_ass_subscript*/\r
+};\r
+\r
+\r
+PyTypeObject\r
+_PyWeakref_ProxyType = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "weakproxy",\r
+ sizeof(PyWeakReference),\r
+ 0,\r
+ /* methods */\r
+ (destructor)proxy_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ proxy_compare, /* tp_compare */\r
+ (reprfunc)proxy_repr, /* tp_repr */\r
+ &proxy_as_number, /* tp_as_number */\r
+ &proxy_as_sequence, /* tp_as_sequence */\r
+ &proxy_as_mapping, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ 0, /* tp_call */\r
+ proxy_str, /* tp_str */\r
+ proxy_getattr, /* tp_getattro */\r
+ (setattrofunc)proxy_setattr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC\r
+ | Py_TPFLAGS_CHECKTYPES, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)gc_traverse, /* tp_traverse */\r
+ (inquiry)gc_clear, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ (getiterfunc)proxy_iter, /* tp_iter */\r
+ (iternextfunc)proxy_iternext, /* tp_iternext */\r
+ proxy_methods, /* tp_methods */\r
+};\r
+\r
+\r
+PyTypeObject\r
+_PyWeakref_CallableProxyType = {\r
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
+ "weakcallableproxy",\r
+ sizeof(PyWeakReference),\r
+ 0,\r
+ /* methods */\r
+ (destructor)proxy_dealloc, /* tp_dealloc */\r
+ 0, /* tp_print */\r
+ 0, /* tp_getattr */\r
+ 0, /* tp_setattr */\r
+ proxy_compare, /* tp_compare */\r
+ (unaryfunc)proxy_repr, /* tp_repr */\r
+ &proxy_as_number, /* tp_as_number */\r
+ &proxy_as_sequence, /* tp_as_sequence */\r
+ &proxy_as_mapping, /* tp_as_mapping */\r
+ 0, /* tp_hash */\r
+ proxy_call, /* tp_call */\r
+ proxy_str, /* tp_str */\r
+ proxy_getattr, /* tp_getattro */\r
+ (setattrofunc)proxy_setattr, /* tp_setattro */\r
+ 0, /* tp_as_buffer */\r
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC\r
+ | Py_TPFLAGS_CHECKTYPES, /* tp_flags */\r
+ 0, /* tp_doc */\r
+ (traverseproc)gc_traverse, /* tp_traverse */\r
+ (inquiry)gc_clear, /* tp_clear */\r
+ 0, /* tp_richcompare */\r
+ 0, /* tp_weaklistoffset */\r
+ (getiterfunc)proxy_iter, /* tp_iter */\r
+ (iternextfunc)proxy_iternext, /* tp_iternext */\r
+};\r
+\r
+\r
+\r
+PyObject *\r
+PyWeakref_NewRef(PyObject *ob, PyObject *callback)\r
+{\r
+ PyWeakReference *result = NULL;\r
+ PyWeakReference **list;\r
+ PyWeakReference *ref, *proxy;\r
+\r
+ if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "cannot create weak reference to '%s' object",\r
+ Py_TYPE(ob)->tp_name);\r
+ return NULL;\r
+ }\r
+ list = GET_WEAKREFS_LISTPTR(ob);\r
+ get_basic_refs(*list, &ref, &proxy);\r
+ if (callback == Py_None)\r
+ callback = NULL;\r
+ if (callback == NULL)\r
+ /* return existing weak reference if it exists */\r
+ result = ref;\r
+ if (result != NULL)\r
+ Py_INCREF(result);\r
+ else {\r
+ /* Note: new_weakref() can trigger cyclic GC, so the weakref\r
+ list on ob can be mutated. This means that the ref and\r
+ proxy pointers we got back earlier may have been collected,\r
+ so we need to compute these values again before we use\r
+ them. */\r
+ result = new_weakref(ob, callback);\r
+ if (result != NULL) {\r
+ get_basic_refs(*list, &ref, &proxy);\r
+ if (callback == NULL) {\r
+ if (ref == NULL)\r
+ insert_head(result, list);\r
+ else {\r
+ /* Someone else added a ref without a callback\r
+ during GC. Return that one instead of this one\r
+ to avoid violating the invariants of the list\r
+ of weakrefs for ob. */\r
+ Py_DECREF(result);\r
+ Py_INCREF(ref);\r
+ result = ref;\r
+ }\r
+ }\r
+ else {\r
+ PyWeakReference *prev;\r
+\r
+ prev = (proxy == NULL) ? ref : proxy;\r
+ if (prev == NULL)\r
+ insert_head(result, list);\r
+ else\r
+ insert_after(result, prev);\r
+ }\r
+ }\r
+ }\r
+ return (PyObject *) result;\r
+}\r
+\r
+\r
+PyObject *\r
+PyWeakref_NewProxy(PyObject *ob, PyObject *callback)\r
+{\r
+ PyWeakReference *result = NULL;\r
+ PyWeakReference **list;\r
+ PyWeakReference *ref, *proxy;\r
+\r
+ if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {\r
+ PyErr_Format(PyExc_TypeError,\r
+ "cannot create weak reference to '%s' object",\r
+ Py_TYPE(ob)->tp_name);\r
+ return NULL;\r
+ }\r
+ list = GET_WEAKREFS_LISTPTR(ob);\r
+ get_basic_refs(*list, &ref, &proxy);\r
+ if (callback == Py_None)\r
+ callback = NULL;\r
+ if (callback == NULL)\r
+ /* attempt to return an existing weak reference if it exists */\r
+ result = proxy;\r
+ if (result != NULL)\r
+ Py_INCREF(result);\r
+ else {\r
+ /* Note: new_weakref() can trigger cyclic GC, so the weakref\r
+ list on ob can be mutated. This means that the ref and\r
+ proxy pointers we got back earlier may have been collected,\r
+ so we need to compute these values again before we use\r
+ them. */\r
+ result = new_weakref(ob, callback);\r
+ if (result != NULL) {\r
+ PyWeakReference *prev;\r
+\r
+ if (PyCallable_Check(ob))\r
+ Py_TYPE(result) = &_PyWeakref_CallableProxyType;\r
+ else\r
+ Py_TYPE(result) = &_PyWeakref_ProxyType;\r
+ get_basic_refs(*list, &ref, &proxy);\r
+ if (callback == NULL) {\r
+ if (proxy != NULL) {\r
+ /* Someone else added a proxy without a callback\r
+ during GC. Return that one instead of this one\r
+ to avoid violating the invariants of the list\r
+ of weakrefs for ob. */\r
+ Py_DECREF(result);\r
+ Py_INCREF(result = proxy);\r
+ goto skip_insert;\r
+ }\r
+ prev = ref;\r
+ }\r
+ else\r
+ prev = (proxy == NULL) ? ref : proxy;\r
+\r
+ if (prev == NULL)\r
+ insert_head(result, list);\r
+ else\r
+ insert_after(result, prev);\r
+ skip_insert:\r
+ ;\r
+ }\r
+ }\r
+ return (PyObject *) result;\r
+}\r
+\r
+\r
+PyObject *\r
+PyWeakref_GetObject(PyObject *ref)\r
+{\r
+ if (ref == NULL || !PyWeakref_Check(ref)) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ return PyWeakref_GET_OBJECT(ref);\r
+}\r
+\r
+/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's\r
+ * handle_weakrefs().\r
+ */\r
+static void\r
+handle_callback(PyWeakReference *ref, PyObject *callback)\r
+{\r
+ PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);\r
+\r
+ if (cbresult == NULL)\r
+ PyErr_WriteUnraisable(callback);\r
+ else\r
+ Py_DECREF(cbresult);\r
+}\r
+\r
+/* This function is called by the tp_dealloc handler to clear weak references.\r
+ *\r
+ * This iterates through the weak references for 'object' and calls callbacks\r
+ * for those references which have one. It returns when all callbacks have\r
+ * been attempted.\r
+ */\r
+void\r
+PyObject_ClearWeakRefs(PyObject *object)\r
+{\r
+ PyWeakReference **list;\r
+\r
+ if (object == NULL\r
+ || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))\r
+ || object->ob_refcnt != 0) {\r
+ PyErr_BadInternalCall();\r
+ return;\r
+ }\r
+ list = GET_WEAKREFS_LISTPTR(object);\r
+ /* Remove the callback-less basic and proxy references */\r
+ if (*list != NULL && (*list)->wr_callback == NULL) {\r
+ clear_weakref(*list);\r
+ if (*list != NULL && (*list)->wr_callback == NULL)\r
+ clear_weakref(*list);\r
+ }\r
+ if (*list != NULL) {\r
+ PyWeakReference *current = *list;\r
+ Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);\r
+ PyObject *err_type, *err_value, *err_tb;\r
+\r
+ PyErr_Fetch(&err_type, &err_value, &err_tb);\r
+ if (count == 1) {\r
+ PyObject *callback = current->wr_callback;\r
+\r
+ current->wr_callback = NULL;\r
+ clear_weakref(current);\r
+ if (callback != NULL) {\r
+ if (current->ob_refcnt > 0)\r
+ handle_callback(current, callback);\r
+ Py_DECREF(callback);\r
+ }\r
+ }\r
+ else {\r
+ PyObject *tuple;\r
+ Py_ssize_t i = 0;\r
+\r
+ tuple = PyTuple_New(count * 2);\r
+ if (tuple == NULL) {\r
+ _PyErr_ReplaceException(err_type, err_value, err_tb);\r
+ return;\r
+ }\r
+\r
+ for (i = 0; i < count; ++i) {\r
+ PyWeakReference *next = current->wr_next;\r
+\r
+ if (current->ob_refcnt > 0)\r
+ {\r
+ Py_INCREF(current);\r
+ PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);\r
+ PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);\r
+ }\r
+ else {\r
+ Py_DECREF(current->wr_callback);\r
+ }\r
+ current->wr_callback = NULL;\r
+ clear_weakref(current);\r
+ current = next;\r
+ }\r
+ for (i = 0; i < count; ++i) {\r
+ PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);\r
+\r
+ /* The tuple may have slots left to NULL */\r
+ if (callback != NULL) {\r
+ PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);\r
+ handle_callback((PyWeakReference *)item, callback);\r
+ }\r
+ }\r
+ Py_DECREF(tuple);\r
+ }\r
+ assert(!PyErr_Occurred());\r
+ PyErr_Restore(err_type, err_value, err_tb);\r
+ }\r
+}\r
--- /dev/null
+This is Python version 2.7.10\r
+=============================\r
+\r
+Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,\r
+2012, 2013, 2014, 2015 Python Software Foundation. All rights reserved.\r
+\r
+Copyright (c) 2000 BeOpen.com.\r
+All rights reserved.\r
+\r
+Copyright (c) 1995-2001 Corporation for National Research Initiatives.\r
+All rights reserved.\r
+\r
+Copyright (c) 1991-1995 Stichting Mathematisch Centrum.\r
+All rights reserved.\r
+\r
+\r
+License information\r
+-------------------\r
+\r
+See the file "LICENSE" for information on the history of this\r
+software, terms & conditions for usage, and a DISCLAIMER OF ALL\r
+WARRANTIES.\r
+\r
+This Python distribution contains no GNU General Public Licensed\r
+(GPLed) code so it may be used in proprietary projects just like prior\r
+Python distributions. There are interfaces to some GNU code but these\r
+are entirely optional.\r
+\r
+All trademarks referenced herein are property of their respective\r
+holders.\r
+\r
+\r
+What's new in this release?\r
+---------------------------\r
+\r
+See the file "Misc/NEWS".\r
+\r
+\r
+If you don't read instructions\r
+------------------------------\r
+\r
+Congratulations on getting this far. :-)\r
+\r
+To start building right away (on UNIX): type "./configure" in the\r
+current directory and when it finishes, type "make". This creates an\r
+executable "./python"; to install in /usr/local, first do "su root"\r
+and then "make install".\r
+\r
+The section `Build instructions' below is still recommended reading.\r
+\r
+\r
+What is Python anyway?\r
+----------------------\r
+\r
+Python is an interpreted, interactive object-oriented programming\r
+language suitable (amongst other uses) for distributed application\r
+development, scripting, numeric computing and system testing. Python\r
+is often compared to Tcl, Perl, Java, JavaScript, Visual Basic or\r
+Scheme. To find out more about what Python can do for you, point your\r
+browser to http://www.python.org/.\r
+\r
+\r
+How do I learn Python?\r
+----------------------\r
+\r
+The official tutorial is still a good place to start; see\r
+http://docs.python.org/ for online and downloadable versions, as well\r
+as a list of other introductions, and reference documentation.\r
+\r
+There's a quickly growing set of books on Python. See\r
+http://wiki.python.org/moin/PythonBooks for a list.\r
+\r
+\r
+Documentation\r
+-------------\r
+\r
+All documentation is provided online in a variety of formats. In\r
+order of importance for new users: Tutorial, Library Reference,\r
+Language Reference, Extending & Embedding, and the Python/C API. The\r
+Library Reference is especially of immense value since much of\r
+Python's power is described there, including the built-in data types\r
+and functions!\r
+\r
+All documentation is also available online at the Python web site\r
+(http://docs.python.org/, see below). It is available online for occasional\r
+reference, or can be downloaded in many formats for faster access. The\r
+documentation is downloadable in HTML, PostScript, PDF, LaTeX, and\r
+reStructuredText (2.6+) formats; the LaTeX and reStructuredText versions are\r
+primarily for documentation authors, translators, and people with special\r
+formatting requirements.\r
+\r
+If you would like to contribute to the development of Python, relevant\r
+documentation is available at:\r
+\r
+ http://docs.python.org/devguide/\r
+\r
+For information about building Python's documentation, refer to Doc/README.txt.\r
+\r
+\r
+Web sites\r
+---------\r
+\r
+New Python releases and related technologies are published at\r
+http://www.python.org/. Come visit us!\r
+\r
+\r
+Newsgroups and Mailing Lists\r
+----------------------------\r
+\r
+Read comp.lang.python, a high-volume discussion newsgroup about\r
+Python, or comp.lang.python.announce, a low-volume moderated newsgroup\r
+for Python-related announcements. These are also accessible as\r
+mailing lists: see http://www.python.org/community/lists/ for an\r
+overview of these and many other Python-related mailing lists.\r
+\r
+Archives are accessible via the Google Groups Usenet archive; see\r
+http://groups.google.com/. The mailing lists are also archived, see\r
+http://www.python.org/community/lists/ for details.\r
+\r
+\r
+Bug reports\r
+-----------\r
+\r
+To report or search for bugs, please use the Python Bug\r
+Tracker at http://bugs.python.org/.\r
+\r
+\r
+Patches and contributions\r
+-------------------------\r
+\r
+To submit a patch or other contribution, please use the Python Patch\r
+Manager at http://bugs.python.org/. Guidelines\r
+for patch submission may be found at http://www.python.org/dev/patches/.\r
+\r
+If you have a proposal to change Python, you may want to send an email to the\r
+comp.lang.python or python-ideas mailing lists for inital feedback. A Python\r
+Enhancement Proposal (PEP) may be submitted if your idea gains ground. All\r
+current PEPs, as well as guidelines for submitting a new PEP, are listed at\r
+http://www.python.org/dev/peps/.\r
+\r
+\r
+Questions\r
+---------\r
+\r
+For help, if you can't find it in the manuals or on the web site, it's\r
+best to post to the comp.lang.python or the Python mailing list (see\r
+above). If you specifically don't want to involve the newsgroup or\r
+mailing list, send questions to help@python.org (a group of volunteers\r
+who answer questions as they can). The newsgroup is the most\r
+efficient way to ask public questions.\r
+\r
+\r
+Build instructions\r
+==================\r
+\r
+Before you can build Python, you must first configure it.\r
+Fortunately, the configuration and build process has been automated\r
+for Unix and Linux installations, so all you usually have to do is\r
+type a few commands and sit back. There are some platforms where\r
+things are not quite as smooth; see the platform specific notes below.\r
+If you want to build for multiple platforms sharing the same source\r
+tree, see the section on VPATH below.\r
+\r
+Start by running the script "./configure", which determines your\r
+system configuration and creates the Makefile. (It takes a minute or\r
+two -- please be patient!) You may want to pass options to the\r
+configure script -- see the section below on configuration options and\r
+variables. When it's done, you are ready to run make.\r
+\r
+To build Python, you normally type "make" in the toplevel directory.\r
+If you have changed the configuration, the Makefile may have to be\r
+rebuilt. In this case, you may have to run make again to correctly\r
+build your desired target. The interpreter executable is built in the\r
+top level directory.\r
+\r
+Once you have built a Python interpreter, see the subsections below on\r
+testing and installation. If you run into trouble, see the next\r
+section.\r
+\r
+Previous versions of Python used a manual configuration process that\r
+involved editing the file Modules/Setup. While this file still exists\r
+and manual configuration is still supported, it is rarely needed any\r
+more: almost all modules are automatically built as appropriate under\r
+guidance of the setup.py script, which is run by Make after the\r
+interpreter has been built.\r
+\r
+\r
+Troubleshooting\r
+---------------\r
+\r
+See also the platform specific notes in the next section.\r
+\r
+If you run into other trouble, see the FAQ\r
+(http://www.python.org/doc/faq/) for hints on what can go wrong, and\r
+how to fix it.\r
+\r
+If you rerun the configure script with different options, remove all\r
+object files by running "make clean" before rebuilding. Believe it or\r
+not, "make clean" sometimes helps to clean up other inexplicable\r
+problems as well. Try it before sending in a bug report!\r
+\r
+If the configure script fails or doesn't seem to find things that\r
+should be there, inspect the config.log file.\r
+\r
+If you get a warning for every file about the -Olimit option being no\r
+longer supported, you can ignore it. There's no foolproof way to know\r
+whether this option is needed; all we can do is test whether it is\r
+accepted without error. On some systems, e.g. older SGI compilers, it\r
+is essential for performance (specifically when compiling ceval.c,\r
+which has more basic blocks than the default limit of 1000). If the\r
+warning bothers you, edit the Makefile to remove "-Olimit 1500" from\r
+the OPT variable.\r
+\r
+If you get failures in test_long, or sys.maxint gets set to -1, you\r
+are probably experiencing compiler bugs, usually related to\r
+optimization. This is a common problem with some versions of gcc, and\r
+some vendor-supplied compilers, which can sometimes be worked around\r
+by turning off optimization. Consider switching to stable versions\r
+(gcc 2.95.2, gcc 3.x, or contact your vendor.)\r
+\r
+From Python 2.0 onward, all Python C code is ANSI C. Compiling using\r
+old K&R-C-only compilers is no longer possible. ANSI C compilers are\r
+available for all modern systems, either in the form of updated\r
+compilers from the vendor, or one of the free compilers (gcc).\r
+\r
+If "make install" fails mysteriously during the "compiling the library"\r
+step, make sure that you don't have any of the PYTHONPATH or PYTHONHOME\r
+environment variables set, as they may interfere with the newly built\r
+executable which is compiling the library.\r
+\r
+Unsupported systems\r
+-------------------\r
+\r
+A number of systems are not supported in Python 2.7 anymore. Some\r
+support code is still present, but will be removed in later versions.\r
+If you still need to use current Python versions on these systems,\r
+please send a message to python-dev@python.org indicating that you\r
+volunteer to support this system. For a more detailed discussion \r
+regarding no-longer-supported and resupporting platforms, as well\r
+as a list of platforms that became or will be unsupported, see PEP 11.\r
+\r
+More specifically, the following systems are not supported any\r
+longer:\r
+- SunOS 4\r
+- DYNIX\r
+- dgux\r
+- Minix\r
+- NeXT\r
+- Irix 4 and --with-sgi-dl\r
+- Linux 1\r
+- Systems defining __d6_pthread_create (configure.ac)\r
+- Systems defining PY_PTHREAD_D4, PY_PTHREAD_D6,\r
+ or PY_PTHREAD_D7 in thread_pthread.h\r
+- Systems using --with-dl-dld\r
+- Systems using --without-universal-newlines\r
+- MacOS 9\r
+- Systems using --with-wctype-functions\r
+- Win9x, WinME\r
+\r
+\r
+Platform specific notes\r
+-----------------------\r
+\r
+(Some of these may no longer apply. If you find you can build Python\r
+on these platforms without the special directions mentioned here,\r
+submit a documentation bug report to SourceForge (see Bug Reports\r
+above) so we can remove them!)\r
+\r
+Unix platforms: If your vendor still ships (and you still use) Berkeley DB\r
+ 1.85 you will need to edit Modules/Setup to build the bsddb185\r
+ module and add a line to sitecustomize.py which makes it the\r
+ default. In Modules/Setup a line like\r
+\r
+ bsddb185 bsddbmodule.c\r
+\r
+ should work. (You may need to add -I, -L or -l flags to direct the\r
+ compiler and linker to your include files and libraries.)\r
+\r
+XXX I think this next bit is out of date:\r
+\r
+64-bit platforms: The modules audioop, and imageop don't work.\r
+ The setup.py script disables them on 64-bit installations.\r
+ Don't try to enable them in the Modules/Setup file. They\r
+ contain code that is quite wordsize sensitive. (If you have a\r
+ fix, let us know!)\r
+\r
+Solaris: When using Sun's C compiler with threads, at least on Solaris\r
+ 2.5.1, you need to add the "-mt" compiler option (the simplest\r
+ way is probably to specify the compiler with this option as\r
+ the "CC" environment variable when running the configure\r
+ script).\r
+\r
+ When using GCC on Solaris, beware of binutils 2.13 or GCC\r
+ versions built using it. This mistakenly enables the\r
+ -zcombreloc option which creates broken shared libraries on\r
+ Solaris. binutils 2.12 works, and the binutils maintainers\r
+ are aware of the problem. Binutils 2.13.1 only partially\r
+ fixed things. It appears that 2.13.2 solves the problem\r
+ completely. This problem is known to occur with Solaris 2.7\r
+ and 2.8, but may also affect earlier and later versions of the\r
+ OS.\r
+\r
+ When the dynamic loader complains about errors finding shared\r
+ libraries, such as\r
+\r
+ ld.so.1: ./python: fatal: libstdc++.so.5: open failed:\r
+ No such file or directory\r
+\r
+ you need to first make sure that the library is available on\r
+ your system. Then, you need to instruct the dynamic loader how\r
+ to find it. You can choose any of the following strategies:\r
+\r
+ 1. When compiling Python, set LD_RUN_PATH to the directories\r
+ containing missing libraries.\r
+ 2. When running Python, set LD_LIBRARY_PATH to these directories.\r
+ 3. Use crle(8) to extend the search path of the loader.\r
+ 4. Modify the installed GCC specs file, adding -R options into the\r
+ *link: section.\r
+\r
+ The complex object fails to compile on Solaris 10 with gcc 3.4 (at\r
+ least up to 3.4.3). To work around it, define Py_HUGE_VAL as\r
+ HUGE_VAL(), e.g.:\r
+\r
+ make CPPFLAGS='-D"Py_HUGE_VAL=HUGE_VAL()" -I. -I$(srcdir)/Include'\r
+ ./python setup.py CPPFLAGS='-D"Py_HUGE_VAL=HUGE_VAL()"'\r
+\r
+Linux: A problem with threads and fork() was tracked down to a bug in\r
+ the pthreads code in glibc version 2.0.5; glibc version 2.0.7\r
+ solves the problem. This causes the popen2 test to fail;\r
+ problem and solution reported by Pablo Bleyer.\r
+\r
+Red Hat Linux: Red Hat 9 built Python2.2 in UCS-4 mode and hacked\r
+ Tcl to support it. To compile Python2.3 with Tkinter, you will\r
+ need to pass --enable-unicode=ucs4 flag to ./configure.\r
+\r
+ There's an executable /usr/bin/python which is Python\r
+ 1.5.2 on most older Red Hat installations; several key Red Hat tools\r
+ require this version. Python 2.1.x may be installed as\r
+ /usr/bin/python2. The Makefile installs Python as\r
+ /usr/local/bin/python, which may or may not take precedence\r
+ over /usr/bin/python, depending on how you have set up $PATH.\r
+\r
+FreeBSD 3.x and probably platforms with NCurses that use libmytinfo or\r
+ similar: When using cursesmodule, the linking is not done in\r
+ the correct order with the defaults. Remove "-ltermcap" from\r
+ the readline entry in Setup, and use as curses entry: "curses\r
+ cursesmodule.c -lmytinfo -lncurses -ltermcap" - "mytinfo" (so\r
+ called on FreeBSD) should be the name of the auxiliary library\r
+ required on your platform. Normally, it would be linked\r
+ automatically, but not necessarily in the correct order.\r
+\r
+BSDI: BSDI versions before 4.1 have known problems with threads,\r
+ which can cause strange errors in a number of modules (for\r
+ instance, the 'test_signal' test script will hang forever.)\r
+ Turning off threads (with --with-threads=no) or upgrading to\r
+ BSDI 4.1 solves this problem.\r
+\r
+DEC Unix: Run configure with --with-dec-threads, or with\r
+ --with-threads=no if no threads are desired (threads are on by\r
+ default). When using GCC, it is possible to get an internal\r
+ compiler error if optimization is used. This was reported for\r
+ GCC 2.7.2.3 on selectmodule.c. Manually compile the affected\r
+ file without optimization to solve the problem.\r
+\r
+DEC Ultrix: compile with GCC to avoid bugs in the native compiler,\r
+ and pass SHELL=/bin/sh5 to Make when installing.\r
+\r
+AIX: A complete overhaul of the shared library support is now in\r
+ place. See Misc/AIX-NOTES for some notes on how it's done.\r
+ (The optimizer bug reported at this place in previous releases\r
+ has been worked around by a minimal code change.) If you get\r
+ errors about pthread_* functions, during compile or during\r
+ testing, try setting CC to a thread-safe (reentrant) compiler,\r
+ like "cc_r". For full C++ module support, set CC="xlC_r" (or\r
+ CC="xlC" without thread support).\r
+\r
+AIX 5.3: To build a 64-bit version with IBM's compiler, I used the\r
+ following:\r
+\r
+ export PATH=/usr/bin:/usr/vacpp/bin\r
+ ./configure --with-gcc="xlc_r -q64" --with-cxx="xlC_r -q64" \\r
+ --disable-ipv6 AR="ar -X64"\r
+ make\r
+\r
+HP-UX: When using threading, you may have to add -D_REENTRANT to the\r
+ OPT variable in the top-level Makefile; reported by Pat Knight,\r
+ this seems to make a difference (at least for HP-UX 10.20)\r
+ even though pyconfig.h defines it. This seems unnecessary when\r
+ using HP/UX 11 and later - threading seems to work "out of the\r
+ box".\r
+\r
+HP-UX ia64: When building on the ia64 (Itanium) platform using HP's\r
+ compiler, some experience has shown that the compiler's\r
+ optimiser produces a completely broken version of python\r
+ (see http://bugs.python.org/814976). To work around this,\r
+ edit the Makefile and remove -O from the OPT line.\r
+\r
+ To build a 64-bit executable on an Itanium 2 system using HP's\r
+ compiler, use these environment variables:\r
+\r
+ CC=cc\r
+ CXX=aCC\r
+ BASECFLAGS="+DD64"\r
+ LDFLAGS="+DD64 -lxnet"\r
+\r
+ and call configure as:\r
+\r
+ ./configure --without-gcc\r
+\r
+ then *unset* the environment variables again before running\r
+ make. (At least one of these flags causes the build to fail\r
+ if it remains set.) You still have to edit the Makefile and\r
+ remove -O from the OPT line.\r
+\r
+HP PA-RISC 2.0: A recent bug report (http://bugs.python.org/546117)\r
+ suggests that the C compiler in this 64-bit system has bugs\r
+ in the optimizer that break Python. Compiling without\r
+ optimization solves the problems.\r
+\r
+SCO: The following apply to SCO 3 only; Python builds out of the box\r
+ on SCO 5 (or so we've heard).\r
+\r
+ 1) Everything works much better if you add -U__STDC__ to the\r
+ defs. This is because all the SCO header files are broken.\r
+ Anything that isn't mentioned in the C standard is\r
+ conditionally excluded when __STDC__ is defined.\r
+\r
+ 2) Due to the U.S. export restrictions, SCO broke the crypt\r
+ stuff out into a separate library, libcrypt_i.a so the LIBS\r
+ needed be set to:\r
+\r
+ LIBS=' -lsocket -lcrypt_i'\r
+\r
+UnixWare: There are known bugs in the math library of the system, as well as\r
+ problems in the handling of threads (calling fork in one\r
+ thread may interrupt system calls in others). Therefore, test_math and\r
+ tests involving threads will fail until those problems are fixed.\r
+\r
+QNX: Chris Herborth (chrish@qnx.com) writes:\r
+ configure works best if you use GNU bash; a port is available on\r
+ ftp.qnx.com in /usr/free. I used the following process to build,\r
+ test and install Python 1.5.x under QNX:\r
+\r
+ 1) CONFIG_SHELL=/usr/local/bin/bash CC=cc RANLIB=: \\r
+ ./configure --verbose --without-gcc --with-libm=""\r
+\r
+ 2) edit Modules/Setup to activate everything that makes sense for\r
+ your system... tested here at QNX with the following modules:\r
+\r
+ array, audioop, binascii, cPickle, cStringIO, cmath,\r
+ crypt, curses, errno, fcntl, gdbm, grp, imageop,\r
+ _locale, math, md5, new, operator, parser, pcre,\r
+ posix, pwd, readline, regex, reop,\r
+ select, signal, socket, soundex, strop, struct,\r
+ syslog, termios, time, timing, zlib, audioop, imageop\r
+\r
+ 3) make SHELL=/usr/local/bin/bash\r
+\r
+ or, if you feel the need for speed:\r
+\r
+ make SHELL=/usr/local/bin/bash OPT="-5 -Oil+nrt"\r
+\r
+ 4) make SHELL=/usr/local/bin/bash test\r
+\r
+ Using GNU readline 2.2 seems to behave strangely, but I\r
+ think that's a problem with my readline 2.2 port. :-\\r
+\r
+ 5) make SHELL=/usr/local/bin/bash install\r
+\r
+ If you get SIGSEGVs while running Python (I haven't yet, but\r
+ I've only run small programs and the test cases), you're\r
+ probably running out of stack; the default 32k could be a\r
+ little tight. To increase the stack size, edit the Makefile\r
+ to read: LDFLAGS = -N 48k\r
+\r
+BeOS: See Misc/BeOS-NOTES for notes about compiling/installing\r
+ Python on BeOS R3 or later. Note that only the PowerPC\r
+ platform is supported for R3; both PowerPC and x86 are\r
+ supported for R4.\r
+\r
+Cray T3E: Mark Hadfield (m.hadfield@niwa.co.nz) writes:\r
+ Python can be built satisfactorily on a Cray T3E but based on\r
+ my experience with the NIWA T3E (2002-05-22, version 2.2.1)\r
+ there are a few bugs and gotchas. For more information see a\r
+ thread on comp.lang.python in May 2002 entitled "Building\r
+ Python on Cray T3E".\r
+\r
+ 1) Use Cray's cc and not gcc. The latter was reported not to\r
+ work by Konrad Hinsen. It may work now, but it may not.\r
+\r
+ 2) To set sys.platform to something sensible, pass the\r
+ following environment variable to the configure script:\r
+\r
+ MACHDEP=unicosmk\r
+\r
+ 2) Run configure with option "--enable-unicode=ucs4".\r
+\r
+ 3) The Cray T3E does not support dynamic linking, so extension\r
+ modules have to be built by adding (or uncommenting) lines\r
+ in Modules/Setup. The minimum set of modules is\r
+\r
+ posix, new, _sre, unicodedata\r
+\r
+ On NIWA's vanilla T3E system the following have also been\r
+ included successfully:\r
+\r
+ _codecs, _locale, _socket, _symtable, _testcapi, _weakref\r
+ array, binascii, cmath, cPickle, crypt, cStringIO, dbm\r
+ errno, fcntl, grp, math, md5, operator, parser, pcre, pwd\r
+ regex, rotor, select, struct, strop, syslog, termios\r
+ time, timing, xreadlines\r
+\r
+ 4) Once the python executable and library have been built, make\r
+ will execute setup.py, which will attempt to build remaining\r
+ extensions and link them dynamically. Each of these attempts\r
+ will fail but should not halt the make process. This is\r
+ normal.\r
+\r
+ 5) Running "make test" uses a lot of resources and causes\r
+ problems on our system. You might want to try running tests\r
+ singly or in small groups.\r
+\r
+SGI: SGI's standard "make" utility (/bin/make or /usr/bin/make)\r
+ does not check whether a command actually changed the file it\r
+ is supposed to build. This means that whenever you say "make"\r
+ it will redo the link step. The remedy is to use SGI's much\r
+ smarter "smake" utility (/usr/sbin/smake), or GNU make. If\r
+ you set the first line of the Makefile to #!/usr/sbin/smake\r
+ smake will be invoked by make (likewise for GNU make).\r
+\r
+ WARNING: There are bugs in the optimizer of some versions of\r
+ SGI's compilers that can cause bus errors or other strange\r
+ behavior, especially on numerical operations. To avoid this,\r
+ try building with "make OPT=".\r
+\r
+OS/2: If you are running Warp3 or Warp4 and have IBM's VisualAge C/C++\r
+ compiler installed, just change into the pc\os2vacpp directory\r
+ and type NMAKE. Threading and sockets are supported by default\r
+ in the resulting binaries of PYTHON15.DLL and PYTHON.EXE.\r
+\r
+Reliant UNIX: The thread support does not compile on Reliant UNIX, and\r
+ there is a (minor) problem in the configure script for that\r
+ platform as well. This should be resolved in time for a\r
+ future release.\r
+\r
+MacOSX: The tests will crash on both 10.1 and 10.2 with SEGV in\r
+ test_re and test_sre due to the small default stack size. If\r
+ you set the stack size to 2048 before doing a "make test" the\r
+ failure can be avoided. If you're using the tcsh or csh shells,\r
+ use "limit stacksize 2048" and for the bash shell (the default\r
+ as of OSX 10.3), use "ulimit -s 2048".\r
+\r
+ On naked Darwin you may want to add the configure option\r
+ "--disable-toolbox-glue" to disable the glue code for the Carbon\r
+ interface modules. The modules themselves are currently only built\r
+ if you add the --enable-framework option, see below.\r
+\r
+ On a clean OSX /usr/local does not exist. Do a\r
+ "sudo mkdir -m 775 /usr/local"\r
+ before you do a make install. It is probably not a good idea to\r
+ do "sudo make install" which installs everything as superuser,\r
+ as this may later cause problems when installing distutils-based\r
+ additions.\r
+\r
+ Some people have reported problems building Python after using "fink"\r
+ to install additional unix software. Disabling fink (remove all \r
+ references to /sw from your .profile or .login) should solve this.\r
+\r
+ You may want to try the configure option "--enable-framework"\r
+ which installs Python as a framework. The location can be set\r
+ as argument to the --enable-framework option (default\r
+ /Library/Frameworks). A framework install is probably needed if you\r
+ want to use any Aqua-based GUI toolkit (whether Tkinter, wxPython,\r
+ Carbon, Cocoa or anything else).\r
+\r
+ You may also want to try the configure option "--enable-universalsdk"\r
+ which builds Python as a universal binary with support for the \r
+ i386 and PPC architetures. This requires Xcode 2.1 or later to build.\r
+\r
+ See Mac/README for more information on framework and \r
+ universal builds.\r
+\r
+Cygwin: With recent (relative to the time of writing, 2001-12-19)\r
+ Cygwin installations, there are problems with the interaction\r
+ of dynamic linking and fork(). This manifests itself in build\r
+ failures during the execution of setup.py.\r
+\r
+ There are two workarounds that both enable Python (albeit\r
+ without threading support) to build and pass all tests on\r
+ NT/2000 (and most likely XP as well, though reports of testing\r
+ on XP would be appreciated).\r
+\r
+ The workarounds:\r
+\r
+ (a) the band-aid fix is to link the _socket module statically\r
+ rather than dynamically (which is the default).\r
+\r
+ To do this, run "./configure --with-threads=no" including any\r
+ other options you need (--prefix, etc.). Then in Modules/Setup\r
+ uncomment the lines:\r
+\r
+ #SSL=/usr/local/ssl\r
+ #_socket socketmodule.c \\r
+ # -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \\r
+ # -L$(SSL)/lib -lssl -lcrypto\r
+\r
+ and remove "local/" from the SSL variable. Finally, just run\r
+ "make"!\r
+\r
+ (b) The "proper" fix is to rebase the Cygwin DLLs to prevent\r
+ base address conflicts. Details on how to do this can be\r
+ found in the following mail:\r
+\r
+ http://sources.redhat.com/ml/cygwin/2001-12/msg00894.html\r
+\r
+ It is hoped that a version of this solution will be\r
+ incorporated into the Cygwin distribution fairly soon.\r
+\r
+ Two additional problems:\r
+\r
+ (1) Threading support should still be disabled due to a known\r
+ bug in Cygwin pthreads that causes test_threadedtempfile to\r
+ hang.\r
+\r
+ (2) The _curses module does not build. This is a known\r
+ Cygwin ncurses problem that should be resolved the next time\r
+ that this package is released.\r
+\r
+ On older versions of Cygwin, test_poll may hang and test_strftime\r
+ may fail.\r
+\r
+ The situation on 9X/Me is not accurately known at present.\r
+ Some time ago, there were reports that the following\r
+ regression tests failed:\r
+\r
+ test_pwd\r
+ test_select (hang)\r
+ test_socket\r
+\r
+ Due to the test_select hang on 9X/Me, one should run the\r
+ regression test using the following:\r
+\r
+ make TESTOPTS='-l -x test_select' test\r
+\r
+ News regarding these platforms with more recent Cygwin\r
+ versions would be appreciated!\r
+\r
+Windows: When executing Python scripts on the command line using file type\r
+ associations (i.e. starting "script.py" instead of "python script.py"),\r
+ redirects may not work unless you set a specific registry key. See\r
+ the Knowledge Base article <http://support.microsoft.com/kb/321788>.\r
+\r
+\r
+Configuring the bsddb and dbm modules\r
+-------------------------------------\r
+\r
+Beginning with Python version 2.3, the PyBsddb package\r
+<http://pybsddb.sf.net/> was adopted into Python as the bsddb package,\r
+exposing a set of package-level functions which provide\r
+backwards-compatible behavior. Only versions 3.3 through 4.4 of\r
+Sleepycat's libraries provide the necessary API, so older versions\r
+aren't supported through this interface. The old bsddb module has\r
+been retained as bsddb185, though it is not built by default. Users\r
+wishing to use it will have to tweak Modules/Setup to build it. The\r
+dbm module will still be built against the Sleepycat libraries if\r
+other preferred alternatives (ndbm, gdbm) are not found.\r
+\r
+Building the sqlite3 module\r
+---------------------------\r
+\r
+To build the sqlite3 module, you'll need the sqlite3 or libsqlite3\r
+packages installed, including the header files. Many modern operating\r
+systems distribute the headers in a separate package to the library -\r
+often it will be the same name as the main package, but with a -dev or\r
+-devel suffix. \r
+\r
+The version of pysqlite2 that's including in Python needs sqlite3 3.0.8\r
+or later. setup.py attempts to check that it can find a correct version.\r
+\r
+Configuring threads\r
+-------------------\r
+\r
+As of Python 2.0, threads are enabled by default. If you wish to\r
+compile without threads, or if your thread support is broken, pass the\r
+--with-threads=no switch to configure. Unfortunately, on some\r
+platforms, additional compiler and/or linker options are required for\r
+threads to work properly. Below is a table of those options,\r
+collected by Bill Janssen. We would love to automate this process\r
+more, but the information below is not enough to write a patch for the\r
+configure.ac file, so manual intervention is required. If you patch\r
+the configure.ac file and are confident that the patch works, please\r
+send in the patch. (Don't bother patching the configure script itself\r
+-- it is regenerated each time the configure.ac file changes.)\r
+\r
+Compiler switches for threads\r
+.............................\r
+\r
+The definition of _REENTRANT should be configured automatically, if\r
+that does not work on your system, or if _REENTRANT is defined\r
+incorrectly, please report that as a bug.\r
+\r
+ OS/Compiler/threads Switches for use with threads\r
+ (POSIX is draft 10, DCE is draft 4) compile & link\r
+\r
+ SunOS 5.{1-5}/{gcc,SunPro cc}/solaris -mt\r
+ SunOS 5.5/{gcc,SunPro cc}/POSIX (nothing)\r
+ DEC OSF/1 3.x/cc/DCE -threads\r
+ (butenhof@zko.dec.com)\r
+ Digital UNIX 4.x/cc/DCE -threads\r
+ (butenhof@zko.dec.com)\r
+ Digital UNIX 4.x/cc/POSIX -pthread\r
+ (butenhof@zko.dec.com)\r
+ AIX 4.1.4/cc_r/d7 (nothing)\r
+ (buhrt@iquest.net)\r
+ AIX 4.1.4/cc_r4/DCE (nothing)\r
+ (buhrt@iquest.net)\r
+ IRIX 6.2/cc/POSIX (nothing)\r
+ (robertl@cwi.nl)\r
+\r
+\r
+Linker (ld) libraries and flags for threads\r
+...........................................\r
+\r
+ OS/threads Libraries/switches for use with threads\r
+\r
+ SunOS 5.{1-5}/solaris -lthread\r
+ SunOS 5.5/POSIX -lpthread\r
+ DEC OSF/1 3.x/DCE -lpthreads -lmach -lc_r -lc\r
+ (butenhof@zko.dec.com)\r
+ Digital UNIX 4.x/DCE -lpthreads -lpthread -lmach -lexc -lc\r
+ (butenhof@zko.dec.com)\r
+ Digital UNIX 4.x/POSIX -lpthread -lmach -lexc -lc\r
+ (butenhof@zko.dec.com)\r
+ AIX 4.1.4/{draft7,DCE} (nothing)\r
+ (buhrt@iquest.net)\r
+ IRIX 6.2/POSIX -lpthread\r
+ (jph@emilia.engr.sgi.com)\r
+\r
+\r
+Building a shared libpython\r
+---------------------------\r
+\r
+Starting with Python 2.3, the majority of the interpreter can be built\r
+into a shared library, which can then be used by the interpreter\r
+executable, and by applications embedding Python. To enable this feature,\r
+configure with --enable-shared.\r
+\r
+If you enable this feature, the same object files will be used to create\r
+a static library. In particular, the static library will contain object\r
+files using position-independent code (PIC) on platforms where PIC flags\r
+are needed for the shared library.\r
+\r
+\r
+Configuring additional built-in modules\r
+---------------------------------------\r
+\r
+Starting with Python 2.1, the setup.py script at the top of the source\r
+distribution attempts to detect which modules can be built and\r
+automatically compiles them. Autodetection doesn't always work, so\r
+you can still customize the configuration by editing the Modules/Setup\r
+file; but this should be considered a last resort. The rest of this\r
+section only applies if you decide to edit the Modules/Setup file.\r
+You also need this to enable static linking of certain modules (which\r
+is needed to enable profiling on some systems).\r
+\r
+This file is initially copied from Setup.dist by the configure script;\r
+if it does not exist yet, create it by copying Modules/Setup.dist\r
+yourself (configure will never overwrite it). Never edit Setup.dist\r
+-- always edit Setup or Setup.local (see below). Read the comments in\r
+the file for information on what kind of edits are allowed. When you\r
+have edited Setup in the Modules directory, the interpreter will\r
+automatically be rebuilt the next time you run make (in the toplevel\r
+directory).\r
+\r
+Many useful modules can be built on any Unix system, but some optional\r
+modules can't be reliably autodetected. Often the quickest way to\r
+determine whether a particular module works or not is to see if it\r
+will build: enable it in Setup, then if you get compilation or link\r
+errors, disable it -- you're either missing support or need to adjust\r
+the compilation and linking parameters for that module.\r
+\r
+On SGI IRIX, there are modules that interface to many SGI specific\r
+system libraries, e.g. the GL library and the audio hardware. These\r
+modules will not be built by the setup.py script.\r
+\r
+In addition to the file Setup, you can also edit the file Setup.local.\r
+(the makesetup script processes both). You may find it more\r
+convenient to edit Setup.local and leave Setup alone. Then, when\r
+installing a new Python version, you can copy your old Setup.local\r
+file.\r
+\r
+\r
+Setting the optimization/debugging options\r
+------------------------------------------\r
+\r
+If you want or need to change the optimization/debugging options for\r
+the C compiler, assign to the OPT variable on the toplevel make\r
+command; e.g. "make OPT=-g" will build a debugging version of Python\r
+on most platforms. The default is OPT=-O; a value for OPT in the\r
+environment when the configure script is run overrides this default\r
+(likewise for CC; and the initial value for LIBS is used as the base\r
+set of libraries to link with).\r
+\r
+When compiling with GCC, the default value of OPT will also include\r
+the -Wall and -Wstrict-prototypes options.\r
+\r
+Additional debugging code to help debug memory management problems can\r
+be enabled by using the --with-pydebug option to the configure script.\r
+\r
+For flags that change binary compatibility, use the EXTRA_CFLAGS\r
+variable.\r
+\r
+\r
+Profiling\r
+---------\r
+\r
+If you want C profiling turned on, the easiest way is to run configure\r
+with the CC environment variable to the necessary compiler\r
+invocation. For example, on Linux, this works for profiling using\r
+gprof(1):\r
+\r
+ CC="gcc -pg" ./configure\r
+\r
+Note that on Linux, gprof apparently does not work for shared\r
+libraries. The Makefile/Setup mechanism can be used to compile and\r
+link most extension modules statically.\r
+\r
+\r
+Coverage checking\r
+-----------------\r
+\r
+For C coverage checking using gcov, run "make coverage". This will\r
+build a Python binary with profiling activated, and a ".gcno" and\r
+".gcda" file for every source file compiled with that option. With\r
+the built binary, now run the code whose coverage you want to check.\r
+Then, you can see coverage statistics for each individual source file\r
+by running gcov, e.g.\r
+\r
+ gcov -o Modules zlibmodule\r
+\r
+This will create a "zlibmodule.c.gcov" file in the current directory\r
+containing coverage info for that source file.\r
+\r
+This works only for source files statically compiled into the\r
+executable; use the Makefile/Setup mechanism to compile and link\r
+extension modules you want to coverage-check statically.\r
+\r
+\r
+Testing\r
+-------\r
+\r
+To test the interpreter, type "make test" in the top-level directory.\r
+This runs the test set twice (once with no compiled files, once with\r
+the compiled files left by the previous test run). The test set\r
+produces some output. You can generally ignore the messages about\r
+skipped tests due to optional features which can't be imported.\r
+If a message is printed about a failed test or a traceback or core\r
+dump is produced, something is wrong. On some Linux systems (those\r
+that are not yet using glibc 6), test_strftime fails due to a\r
+non-standard implementation of strftime() in the C library. Please\r
+ignore this, or upgrade to glibc version 6.\r
+\r
+By default, tests are prevented from overusing resources like disk space and\r
+memory. To enable these tests, run "make testall".\r
+\r
+IMPORTANT: If the tests fail and you decide to mail a bug report,\r
+*don't* include the output of "make test". It is useless. Run the\r
+failing test manually, as follows:\r
+\r
+ ./python Lib/test/regrtest.py -v test_whatever\r
+\r
+(substituting the top of the source tree for '.' if you built in a\r
+different directory). This runs the test in verbose mode.\r
+\r
+\r
+Installing\r
+----------\r
+\r
+To install the Python binary, library modules, shared library modules\r
+(see below), include files, configuration files, and the manual page,\r
+just type\r
+\r
+ make install\r
+\r
+This will install all platform-independent files in subdirectories of\r
+the directory given with the --prefix option to configure or to the\r
+`prefix' Make variable (default /usr/local). All binary and other\r
+platform-specific files will be installed in subdirectories if the\r
+directory given by --exec-prefix or the `exec_prefix' Make variable\r
+(defaults to the --prefix directory) is given.\r
+\r
+If DESTDIR is set, it will be taken as the root directory of the\r
+installation, and files will be installed into $(DESTDIR)$(prefix),\r
+$(DESTDIR)$(exec_prefix), etc.\r
+\r
+All subdirectories created will have Python's version number in their\r
+name, e.g. the library modules are installed in\r
+"/usr/local/lib/python<version>/" by default, where <version> is the\r
+<major>.<minor> release number (e.g. "2.1"). The Python binary is\r
+installed as "python<version>" and a hard link named "python" is\r
+created. The only file not installed with a version number in its\r
+name is the manual page, installed as "/usr/local/man/man1/python.1"\r
+by default.\r
+\r
+If you want to install multiple versions of Python see the section below\r
+entitled "Installing multiple versions".\r
+\r
+The only thing you may have to install manually is the Python mode for\r
+Emacs found in Misc/python-mode.el. (But then again, more recent\r
+versions of Emacs may already have it.) Follow the instructions that\r
+came with Emacs for installation of site-specific files.\r
+\r
+On Mac OS X, if you have configured Python with --enable-framework, you\r
+should use "make frameworkinstall" to do the installation. Note that this\r
+installs the Python executable in a place that is not normally on your\r
+PATH, you may want to set up a symlink in /usr/local/bin.\r
+\r
+\r
+Installing multiple versions\r
+----------------------------\r
+\r
+On Unix and Mac systems if you intend to install multiple versions of Python\r
+using the same installation prefix (--prefix argument to the configure\r
+script) you must take care that your primary python executable is not\r
+overwritten by the installation of a different version. All files and\r
+directories installed using "make altinstall" contain the major and minor\r
+version and can thus live side-by-side. "make install" also creates\r
+${prefix}/bin/python which refers to ${prefix}/bin/pythonX.Y. If you intend\r
+to install multiple versions using the same prefix you must decide which\r
+version (if any) is your "primary" version. Install that version using\r
+"make install". Install all other versions using "make altinstall".\r
+\r
+For example, if you want to install Python 2.5, 2.6 and 3.0 with 2.6 being\r
+the primary version, you would execute "make install" in your 2.6 build\r
+directory and "make altinstall" in the others.\r
+\r
+\r
+Configuration options and variables\r
+-----------------------------------\r
+\r
+Some special cases are handled by passing options to the configure\r
+script.\r
+\r
+WARNING: if you rerun the configure script with different options, you\r
+must run "make clean" before rebuilding. Exceptions to this rule:\r
+after changing --prefix or --exec-prefix, all you need to do is remove\r
+Modules/getpath.o.\r
+\r
+--with(out)-gcc: The configure script uses gcc (the GNU C compiler) if\r
+ it finds it. If you don't want this, or if this compiler is\r
+ installed but broken on your platform, pass the option\r
+ --without-gcc. You can also pass "CC=cc" (or whatever the\r
+ name of the proper C compiler is) in the environment, but the\r
+ advantage of using --without-gcc is that this option is\r
+ remembered by the config.status script for its --recheck\r
+ option.\r
+\r
+--prefix, --exec-prefix: If you want to install the binaries and the\r
+ Python library somewhere else than in /usr/local/{bin,lib},\r
+ you can pass the option --prefix=DIRECTORY; the interpreter\r
+ binary will be installed as DIRECTORY/bin/python and the\r
+ library files as DIRECTORY/lib/python/*. If you pass\r
+ --exec-prefix=DIRECTORY (as well) this overrides the\r
+ installation prefix for architecture-dependent files (like the\r
+ interpreter binary). Note that --prefix=DIRECTORY also\r
+ affects the default module search path (sys.path), when\r
+ Modules/config.c is compiled. Passing make the option\r
+ prefix=DIRECTORY (and/or exec_prefix=DIRECTORY) overrides the\r
+ prefix set at configuration time; this may be more convenient\r
+ than re-running the configure script if you change your mind\r
+ about the install prefix.\r
+\r
+--with-readline: This option is no longer supported. GNU\r
+ readline is automatically enabled by setup.py when present.\r
+\r
+--with-threads: On most Unix systems, you can now use multiple\r
+ threads, and support for this is enabled by default. To\r
+ disable this, pass --with-threads=no. If the library required\r
+ for threads lives in a peculiar place, you can use\r
+ --with-thread=DIRECTORY. IMPORTANT: run "make clean" after\r
+ changing (either enabling or disabling) this option, or you\r
+ will get link errors! Note: for DEC Unix use\r
+ --with-dec-threads instead.\r
+\r
+--with-sgi-dl: On SGI IRIX 4, dynamic loading of extension modules is\r
+ supported by the "dl" library by Jack Jansen, which is\r
+ ftp'able from ftp://ftp.cwi.nl/pub/dynload/dl-1.6.tar.Z.\r
+ This is enabled (after you've ftp'ed and compiled the dl\r
+ library) by passing --with-sgi-dl=DIRECTORY where DIRECTORY\r
+ is the absolute pathname of the dl library. (Don't bother on\r
+ IRIX 5, it already has dynamic linking using SunOS style\r
+ shared libraries.) THIS OPTION IS UNSUPPORTED.\r
+\r
+--with-dl-dld: Dynamic loading of modules is rumored to be supported\r
+ on some other systems: VAX (Ultrix), Sun3 (SunOS 3.4), Sequent\r
+ Symmetry (Dynix), and Atari ST. This is done using a\r
+ combination of the GNU dynamic loading package\r
+ (ftp://ftp.cwi.nl/pub/dynload/dl-dld-1.1.tar.Z) and an\r
+ emulation of the SGI dl library mentioned above (the emulation\r
+ can be found at\r
+ ftp://ftp.cwi.nl/pub/dynload/dld-3.2.3.tar.Z). To\r
+ enable this, ftp and compile both libraries, then call\r
+ configure, passing it the option\r
+ --with-dl-dld=DL_DIRECTORY,DLD_DIRECTORY where DL_DIRECTORY is\r
+ the absolute pathname of the dl emulation library and\r
+ DLD_DIRECTORY is the absolute pathname of the GNU dld library.\r
+ (Don't bother on SunOS 4 or 5, they already have dynamic\r
+ linking using shared libraries.) THIS OPTION IS UNSUPPORTED.\r
+\r
+--with-libm, --with-libc: It is possible to specify alternative\r
+ versions for the Math library (default -lm) and the C library\r
+ (default the empty string) using the options\r
+ --with-libm=STRING and --with-libc=STRING, respectively. For\r
+ example, if your system requires that you pass -lc_s to the C\r
+ compiler to use the shared C library, you can pass\r
+ --with-libc=-lc_s. These libraries are passed after all other\r
+ libraries, the C library last.\r
+\r
+--with-libs='libs': Add 'libs' to the LIBS that the python interpreter\r
+ is linked against.\r
+\r
+--with-cxx-main=<compiler>: If you plan to use C++ extension modules,\r
+ then -- on some platforms -- you need to compile python's main()\r
+ function with the C++ compiler. With this option, make will use\r
+ <compiler> to compile main() *and* to link the python executable.\r
+ It is likely that the resulting executable depends on the C++\r
+ runtime library of <compiler>. (The default is --without-cxx-main.)\r
+\r
+ There are platforms that do not require you to build Python\r
+ with a C++ compiler in order to use C++ extension modules.\r
+ E.g., x86 Linux with ELF shared binaries and GCC 3.x, 4.x is such\r
+ a platform. We recommend that you configure Python\r
+ --without-cxx-main on those platforms because a mismatch\r
+ between the C++ compiler version used to build Python and to\r
+ build a C++ extension module is likely to cause a crash at\r
+ runtime.\r
+\r
+ The Python installation also stores the variable CXX that\r
+ determines, e.g., the C++ compiler distutils calls by default\r
+ to build C++ extensions. If you set CXX on the configure command\r
+ line to any string of non-zero length, then configure won't\r
+ change CXX. If you do not preset CXX but pass\r
+ --with-cxx-main=<compiler>, then configure sets CXX=<compiler>.\r
+ In all other cases, configure looks for a C++ compiler by\r
+ some common names (c++, g++, gcc, CC, cxx, cc++, cl) and sets\r
+ CXX to the first compiler it finds. If it does not find any\r
+ C++ compiler, then it sets CXX="".\r
+\r
+ Similarly, if you want to change the command used to link the\r
+ python executable, then set LINKCC on the configure command line.\r
+\r
+\r
+--with-pydebug: Enable additional debugging code to help track down\r
+ memory management problems. This allows printing a list of all\r
+ live objects when the interpreter terminates.\r
+\r
+--with(out)-universal-newlines: enable reading of text files with\r
+ foreign newline convention (default: enabled). In other words,\r
+ any of \r, \n or \r\n is acceptable as end-of-line character.\r
+ If enabled import and execfile will automatically accept any newline\r
+ in files. Python code can open a file with open(file, 'U') to\r
+ read it in universal newline mode. THIS OPTION IS UNSUPPORTED.\r
+\r
+--with-tsc: Profile using the Pentium timestamping counter (TSC).\r
+\r
+--with-system-ffi: Build the _ctypes extension module using an ffi\r
+ library installed on the system.\r
+\r
+--with-dbmliborder=db1:db2:...: Specify the order that backends for the\r
+ dbm extension are checked. Valid value is a colon separated string\r
+ with the backend names `ndbm', `gdbm' and `bdb'.\r
+\r
+Building for multiple architectures (using the VPATH feature)\r
+-------------------------------------------------------------\r
+\r
+If your file system is shared between multiple architectures, it\r
+usually is not necessary to make copies of the sources for each\r
+architecture you want to support. If the make program supports the\r
+VPATH feature, you can create an empty build directory for each\r
+architecture, and in each directory run the configure script (on the\r
+appropriate machine with the appropriate options). This creates the\r
+necessary subdirectories and the Makefiles therein. The Makefiles\r
+contain a line VPATH=... which points to a directory containing the\r
+actual sources. (On SGI systems, use "smake -J1" instead of "make" if\r
+you use VPATH -- don't try gnumake.)\r
+\r
+For example, the following is all you need to build a minimal Python\r
+in /usr/tmp/python (assuming ~guido/src/python is the toplevel\r
+directory and you want to build in /usr/tmp/python):\r
+\r
+ $ mkdir /usr/tmp/python\r
+ $ cd /usr/tmp/python\r
+ $ ~guido/src/python/configure\r
+ [...]\r
+ $ make\r
+ [...]\r
+ $\r
+\r
+Note that configure copies the original Setup file to the build\r
+directory if it finds no Setup file there. This means that you can\r
+edit the Setup file for each architecture independently. For this\r
+reason, subsequent changes to the original Setup file are not tracked\r
+automatically, as they might overwrite local changes. To force a copy\r
+of a changed original Setup file, delete the target Setup file. (The\r
+makesetup script supports multiple input files, so if you want to be\r
+fancy you can change the rules to create an empty Setup.local if it\r
+doesn't exist and run it with arguments $(srcdir)/Setup Setup.local;\r
+however this assumes that you only need to add modules.)\r
+\r
+Also note that you can't use a workspace for VPATH and non VPATH builds. The\r
+object files left behind by one version confuses the other.\r
+\r
+\r
+Building on non-UNIX systems\r
+----------------------------\r
+\r
+For Windows (2000/NT/ME/98/95), assuming you have MS VC++ 7.1, the\r
+project files are in PCbuild, the workspace is pcbuild.dsw. See\r
+PCbuild\readme.txt for detailed instructions.\r
+\r
+For other non-Unix Windows compilers, in particular MS VC++ 6.0 and\r
+for OS/2, enter the directory "PC" and read the file "readme.txt".\r
+\r
+For the Mac, a separate source distribution will be made available,\r
+for use with the CodeWarrior compiler. If you are interested in Mac\r
+development, join the PythonMac Special Interest Group\r
+(http://www.python.org/sigs/pythonmac-sig/, or send email to\r
+pythonmac-sig-request@python.org).\r
+\r
+Of course, there are also binary distributions available for these\r
+platforms -- see http://www.python.org/.\r
+\r
+To port Python to a new non-UNIX system, you will have to fake the\r
+effect of running the configure script manually (for Mac and PC, this\r
+has already been done for you). A good start is to copy the file\r
+pyconfig.h.in to pyconfig.h and edit the latter to reflect the actual\r
+configuration of your system. Most symbols must simply be defined as\r
+1 only if the corresponding feature is present and can be left alone\r
+otherwise; however the *_t type symbols must be defined as some\r
+variant of int if they need to be defined at all.\r
+\r
+For all platforms, it's important that the build arrange to define the\r
+preprocessor symbol NDEBUG on the compiler command line in a release\r
+build of Python (else assert() calls remain in the code, hurting\r
+release-build performance). The Unix, Windows and Mac builds already\r
+do this.\r
+\r
+\r
+Miscellaneous issues\r
+====================\r
+\r
+Emacs mode\r
+----------\r
+\r
+There's an excellent Emacs editing mode for Python code; see the file\r
+Misc/python-mode.el. Originally written by the famous Tim Peters, it is now\r
+maintained by the equally famous Barry Warsaw. The latest version, along with\r
+various other contributed Python-related Emacs goodies, is online at\r
+http://launchpad.net/python-mode/.\r
+\r
+\r
+Tkinter\r
+-------\r
+\r
+The setup.py script automatically configures this when it detects a\r
+usable Tcl/Tk installation. This requires Tcl/Tk version 8.0 or\r
+higher.\r
+\r
+For more Tkinter information, see the Tkinter Resource page:\r
+http://www.python.org/topics/tkinter/\r
+\r
+There are demos in the Demo/tkinter directory.\r
+\r
+Note that there's a Python module called "Tkinter" (capital T) which\r
+lives in Lib/lib-tk/Tkinter.py, and a C module called "_tkinter"\r
+(lower case t and leading underscore) which lives in\r
+Modules/_tkinter.c. Demos and normal Tk applications import only the\r
+Python Tkinter module -- only the latter imports the C _tkinter\r
+module. In order to find the C _tkinter module, it must be compiled\r
+and linked into the Python interpreter -- the setup.py script does\r
+this. In order to find the Python Tkinter module, sys.path must be\r
+set correctly -- normal installation takes care of this.\r
+\r
+\r
+Distribution structure\r
+----------------------\r
+\r
+Most subdirectories have their own README files. Most files have\r
+comments.\r
+\r
+Demo/ Demonstration scripts, modules and programs\r
+Doc/ Documentation sources (reStructuredText)\r
+Grammar/ Input for the parser generator\r
+Include/ Public header files\r
+LICENSE Licensing information\r
+Lib/ Python library modules\r
+Mac/ Macintosh specific resources\r
+Makefile.pre.in Source from which config.status creates the Makefile.pre\r
+Misc/ Miscellaneous useful files\r
+Modules/ Implementation of most built-in modules\r
+Objects/ Implementation of most built-in object types\r
+PC/ Files specific to PC ports (DOS, Windows, OS/2)\r
+PCbuild/ Build directory for Microsoft Visual C++\r
+Parser/ The parser and tokenizer and their input handling\r
+Python/ The byte-compiler and interpreter\r
+README The file you're reading now\r
+RISCOS/ Files specific to RISC OS port\r
+Tools/ Some useful programs written in Python\r
+pyconfig.h.in Source from which pyconfig.h is created (GNU autoheader output)\r
+configure Configuration shell script (GNU autoconf output)\r
+configure.ac Configuration specification (input for GNU autoconf)\r
+install-sh Shell script used to install files\r
+setup.py Python script used to build extension modules\r
+\r
+The following files will (may) be created in the toplevel directory by\r
+the configuration and build processes:\r
+\r
+Makefile Build rules\r
+Makefile.pre Build rules before running Modules/makesetup\r
+buildno Keeps track of the build number\r
+config.cache Cache of configuration variables\r
+pyconfig.h Configuration header\r
+config.log Log from last configure run\r
+config.status Status from last run of the configure script\r
+getbuildinfo.o Object file from Modules/getbuildinfo.c\r
+libpython<version>.a The library archive\r
+python The executable interpreter\r
+reflog.txt Output from running the regression suite with the -R flag \r
+tags, TAGS Tags files for vi and Emacs\r
+\r
+\r
+That's all, folks!\r
+------------------\r
+\r
+\r
+--Guido van Rossum (home page: http://www.python.org/~guido/)\r