17db96d56Sopenharmony_ci#include "Python.h" 27db96d56Sopenharmony_ci#include "pycore_call.h" // _PyObject_CallNoArgs() 37db96d56Sopenharmony_ci#include "pycore_long.h" // _PyLong_GetZero() 47db96d56Sopenharmony_ci#include "structmember.h" // PyMemberDef 57db96d56Sopenharmony_ci#include <stddef.h> 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci/*[clinic input] 87db96d56Sopenharmony_cimodule _collections 97db96d56Sopenharmony_ciclass _tuplegetter "_tuplegetterobject *" "&tuplegetter_type" 107db96d56Sopenharmony_ci[clinic start generated code]*/ 117db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a8ece4ccad7e30ac]*/ 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_cistatic PyTypeObject tuplegetter_type; 147db96d56Sopenharmony_ci#include "clinic/_collectionsmodule.c.h" 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci/* collections module implementation of a deque() datatype 177db96d56Sopenharmony_ci Written and maintained by Raymond D. Hettinger <python@rcn.com> 187db96d56Sopenharmony_ci*/ 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci/* The block length may be set to any number over 1. Larger numbers 217db96d56Sopenharmony_ci * reduce the number of calls to the memory allocator, give faster 227db96d56Sopenharmony_ci * indexing and rotation, and reduce the link to data overhead ratio. 237db96d56Sopenharmony_ci * Making the block length a power of two speeds-up the modulo 247db96d56Sopenharmony_ci * and division calculations in deque_item() and deque_ass_item(). 257db96d56Sopenharmony_ci */ 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci#define BLOCKLEN 64 287db96d56Sopenharmony_ci#define CENTER ((BLOCKLEN - 1) / 2) 297db96d56Sopenharmony_ci#define MAXFREEBLOCKS 16 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci/* Data for deque objects is stored in a doubly-linked list of fixed 327db96d56Sopenharmony_ci * length blocks. This assures that appends or pops never move any 337db96d56Sopenharmony_ci * other data elements besides the one being appended or popped. 347db96d56Sopenharmony_ci * 357db96d56Sopenharmony_ci * Another advantage is that it completely avoids use of realloc(), 367db96d56Sopenharmony_ci * resulting in more predictable performance. 377db96d56Sopenharmony_ci * 387db96d56Sopenharmony_ci * Textbook implementations of doubly-linked lists store one datum 397db96d56Sopenharmony_ci * per link, but that gives them a 200% memory overhead (a prev and 407db96d56Sopenharmony_ci * next link for each datum) and it costs one malloc() call per data 417db96d56Sopenharmony_ci * element. By using fixed-length blocks, the link to data ratio is 427db96d56Sopenharmony_ci * significantly improved and there are proportionally fewer calls 437db96d56Sopenharmony_ci * to malloc() and free(). The data blocks of consecutive pointers 447db96d56Sopenharmony_ci * also improve cache locality. 457db96d56Sopenharmony_ci * 467db96d56Sopenharmony_ci * The list of blocks is never empty, so d.leftblock and d.rightblock 477db96d56Sopenharmony_ci * are never equal to NULL. The list is not circular. 487db96d56Sopenharmony_ci * 497db96d56Sopenharmony_ci * A deque d's first element is at d.leftblock[leftindex] 507db96d56Sopenharmony_ci * and its last element is at d.rightblock[rightindex]. 517db96d56Sopenharmony_ci * 527db96d56Sopenharmony_ci * Unlike Python slice indices, these indices are inclusive on both 537db96d56Sopenharmony_ci * ends. This makes the algorithms for left and right operations 547db96d56Sopenharmony_ci * more symmetrical and it simplifies the design. 557db96d56Sopenharmony_ci * 567db96d56Sopenharmony_ci * The indices, d.leftindex and d.rightindex are always in the range: 577db96d56Sopenharmony_ci * 0 <= index < BLOCKLEN 587db96d56Sopenharmony_ci * 597db96d56Sopenharmony_ci * And their exact relationship is: 607db96d56Sopenharmony_ci * (d.leftindex + d.len - 1) % BLOCKLEN == d.rightindex 617db96d56Sopenharmony_ci * 627db96d56Sopenharmony_ci * Whenever d.leftblock == d.rightblock, then: 637db96d56Sopenharmony_ci * d.leftindex + d.len - 1 == d.rightindex 647db96d56Sopenharmony_ci * 657db96d56Sopenharmony_ci * However, when d.leftblock != d.rightblock, the d.leftindex and 667db96d56Sopenharmony_ci * d.rightindex become indices into distinct blocks and either may 677db96d56Sopenharmony_ci * be larger than the other. 687db96d56Sopenharmony_ci * 697db96d56Sopenharmony_ci * Empty deques have: 707db96d56Sopenharmony_ci * d.len == 0 717db96d56Sopenharmony_ci * d.leftblock == d.rightblock 727db96d56Sopenharmony_ci * d.leftindex == CENTER + 1 737db96d56Sopenharmony_ci * d.rightindex == CENTER 747db96d56Sopenharmony_ci * 757db96d56Sopenharmony_ci * Checking for d.len == 0 is the intended way to see whether d is empty. 767db96d56Sopenharmony_ci */ 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_citypedef struct BLOCK { 797db96d56Sopenharmony_ci struct BLOCK *leftlink; 807db96d56Sopenharmony_ci PyObject *data[BLOCKLEN]; 817db96d56Sopenharmony_ci struct BLOCK *rightlink; 827db96d56Sopenharmony_ci} block; 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_citypedef struct { 857db96d56Sopenharmony_ci PyObject_VAR_HEAD 867db96d56Sopenharmony_ci block *leftblock; 877db96d56Sopenharmony_ci block *rightblock; 887db96d56Sopenharmony_ci Py_ssize_t leftindex; /* 0 <= leftindex < BLOCKLEN */ 897db96d56Sopenharmony_ci Py_ssize_t rightindex; /* 0 <= rightindex < BLOCKLEN */ 907db96d56Sopenharmony_ci size_t state; /* incremented whenever the indices move */ 917db96d56Sopenharmony_ci Py_ssize_t maxlen; /* maxlen is -1 for unbounded deques */ 927db96d56Sopenharmony_ci Py_ssize_t numfreeblocks; 937db96d56Sopenharmony_ci block *freeblocks[MAXFREEBLOCKS]; 947db96d56Sopenharmony_ci PyObject *weakreflist; 957db96d56Sopenharmony_ci} dequeobject; 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_cistatic PyTypeObject deque_type; 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci/* For debug builds, add error checking to track the endpoints 1007db96d56Sopenharmony_ci * in the chain of links. The goal is to make sure that link 1017db96d56Sopenharmony_ci * assignments only take place at endpoints so that links already 1027db96d56Sopenharmony_ci * in use do not get overwritten. 1037db96d56Sopenharmony_ci * 1047db96d56Sopenharmony_ci * CHECK_END should happen before each assignment to a block's link field. 1057db96d56Sopenharmony_ci * MARK_END should happen whenever a link field becomes a new endpoint. 1067db96d56Sopenharmony_ci * This happens when new blocks are added or whenever an existing 1077db96d56Sopenharmony_ci * block is freed leaving another existing block as the new endpoint. 1087db96d56Sopenharmony_ci */ 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci#ifndef NDEBUG 1117db96d56Sopenharmony_ci#define MARK_END(link) link = NULL; 1127db96d56Sopenharmony_ci#define CHECK_END(link) assert(link == NULL); 1137db96d56Sopenharmony_ci#define CHECK_NOT_END(link) assert(link != NULL); 1147db96d56Sopenharmony_ci#else 1157db96d56Sopenharmony_ci#define MARK_END(link) 1167db96d56Sopenharmony_ci#define CHECK_END(link) 1177db96d56Sopenharmony_ci#define CHECK_NOT_END(link) 1187db96d56Sopenharmony_ci#endif 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ci/* A simple freelisting scheme is used to minimize calls to the memory 1217db96d56Sopenharmony_ci allocator. It accommodates common use cases where new blocks are being 1227db96d56Sopenharmony_ci added at about the same rate as old blocks are being freed. 1237db96d56Sopenharmony_ci */ 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_cistatic inline block * 1267db96d56Sopenharmony_cinewblock(dequeobject *deque) { 1277db96d56Sopenharmony_ci block *b; 1287db96d56Sopenharmony_ci if (deque->numfreeblocks) { 1297db96d56Sopenharmony_ci deque->numfreeblocks--; 1307db96d56Sopenharmony_ci return deque->freeblocks[deque->numfreeblocks]; 1317db96d56Sopenharmony_ci } 1327db96d56Sopenharmony_ci b = PyMem_Malloc(sizeof(block)); 1337db96d56Sopenharmony_ci if (b != NULL) { 1347db96d56Sopenharmony_ci return b; 1357db96d56Sopenharmony_ci } 1367db96d56Sopenharmony_ci PyErr_NoMemory(); 1377db96d56Sopenharmony_ci return NULL; 1387db96d56Sopenharmony_ci} 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_cistatic inline void 1417db96d56Sopenharmony_cifreeblock(dequeobject *deque, block *b) 1427db96d56Sopenharmony_ci{ 1437db96d56Sopenharmony_ci if (deque->numfreeblocks < MAXFREEBLOCKS) { 1447db96d56Sopenharmony_ci deque->freeblocks[deque->numfreeblocks] = b; 1457db96d56Sopenharmony_ci deque->numfreeblocks++; 1467db96d56Sopenharmony_ci } else { 1477db96d56Sopenharmony_ci PyMem_Free(b); 1487db96d56Sopenharmony_ci } 1497db96d56Sopenharmony_ci} 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_cistatic PyObject * 1527db96d56Sopenharmony_cideque_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 1537db96d56Sopenharmony_ci{ 1547db96d56Sopenharmony_ci dequeobject *deque; 1557db96d56Sopenharmony_ci block *b; 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_ci /* create dequeobject structure */ 1587db96d56Sopenharmony_ci deque = (dequeobject *)type->tp_alloc(type, 0); 1597db96d56Sopenharmony_ci if (deque == NULL) 1607db96d56Sopenharmony_ci return NULL; 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci b = newblock(deque); 1637db96d56Sopenharmony_ci if (b == NULL) { 1647db96d56Sopenharmony_ci Py_DECREF(deque); 1657db96d56Sopenharmony_ci return NULL; 1667db96d56Sopenharmony_ci } 1677db96d56Sopenharmony_ci MARK_END(b->leftlink); 1687db96d56Sopenharmony_ci MARK_END(b->rightlink); 1697db96d56Sopenharmony_ci 1707db96d56Sopenharmony_ci assert(BLOCKLEN >= 2); 1717db96d56Sopenharmony_ci Py_SET_SIZE(deque, 0); 1727db96d56Sopenharmony_ci deque->leftblock = b; 1737db96d56Sopenharmony_ci deque->rightblock = b; 1747db96d56Sopenharmony_ci deque->leftindex = CENTER + 1; 1757db96d56Sopenharmony_ci deque->rightindex = CENTER; 1767db96d56Sopenharmony_ci deque->state = 0; 1777db96d56Sopenharmony_ci deque->maxlen = -1; 1787db96d56Sopenharmony_ci deque->numfreeblocks = 0; 1797db96d56Sopenharmony_ci deque->weakreflist = NULL; 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci return (PyObject *)deque; 1827db96d56Sopenharmony_ci} 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_cistatic PyObject * 1857db96d56Sopenharmony_cideque_pop(dequeobject *deque, PyObject *unused) 1867db96d56Sopenharmony_ci{ 1877db96d56Sopenharmony_ci PyObject *item; 1887db96d56Sopenharmony_ci block *prevblock; 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci if (Py_SIZE(deque) == 0) { 1917db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "pop from an empty deque"); 1927db96d56Sopenharmony_ci return NULL; 1937db96d56Sopenharmony_ci } 1947db96d56Sopenharmony_ci item = deque->rightblock->data[deque->rightindex]; 1957db96d56Sopenharmony_ci deque->rightindex--; 1967db96d56Sopenharmony_ci Py_SET_SIZE(deque, Py_SIZE(deque) - 1); 1977db96d56Sopenharmony_ci deque->state++; 1987db96d56Sopenharmony_ci 1997db96d56Sopenharmony_ci if (deque->rightindex < 0) { 2007db96d56Sopenharmony_ci if (Py_SIZE(deque)) { 2017db96d56Sopenharmony_ci prevblock = deque->rightblock->leftlink; 2027db96d56Sopenharmony_ci assert(deque->leftblock != deque->rightblock); 2037db96d56Sopenharmony_ci freeblock(deque, deque->rightblock); 2047db96d56Sopenharmony_ci CHECK_NOT_END(prevblock); 2057db96d56Sopenharmony_ci MARK_END(prevblock->rightlink); 2067db96d56Sopenharmony_ci deque->rightblock = prevblock; 2077db96d56Sopenharmony_ci deque->rightindex = BLOCKLEN - 1; 2087db96d56Sopenharmony_ci } else { 2097db96d56Sopenharmony_ci assert(deque->leftblock == deque->rightblock); 2107db96d56Sopenharmony_ci assert(deque->leftindex == deque->rightindex+1); 2117db96d56Sopenharmony_ci /* re-center instead of freeing a block */ 2127db96d56Sopenharmony_ci deque->leftindex = CENTER + 1; 2137db96d56Sopenharmony_ci deque->rightindex = CENTER; 2147db96d56Sopenharmony_ci } 2157db96d56Sopenharmony_ci } 2167db96d56Sopenharmony_ci return item; 2177db96d56Sopenharmony_ci} 2187db96d56Sopenharmony_ci 2197db96d56Sopenharmony_ciPyDoc_STRVAR(pop_doc, "Remove and return the rightmost element."); 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_cistatic PyObject * 2227db96d56Sopenharmony_cideque_popleft(dequeobject *deque, PyObject *unused) 2237db96d56Sopenharmony_ci{ 2247db96d56Sopenharmony_ci PyObject *item; 2257db96d56Sopenharmony_ci block *prevblock; 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci if (Py_SIZE(deque) == 0) { 2287db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "pop from an empty deque"); 2297db96d56Sopenharmony_ci return NULL; 2307db96d56Sopenharmony_ci } 2317db96d56Sopenharmony_ci assert(deque->leftblock != NULL); 2327db96d56Sopenharmony_ci item = deque->leftblock->data[deque->leftindex]; 2337db96d56Sopenharmony_ci deque->leftindex++; 2347db96d56Sopenharmony_ci Py_SET_SIZE(deque, Py_SIZE(deque) - 1); 2357db96d56Sopenharmony_ci deque->state++; 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_ci if (deque->leftindex == BLOCKLEN) { 2387db96d56Sopenharmony_ci if (Py_SIZE(deque)) { 2397db96d56Sopenharmony_ci assert(deque->leftblock != deque->rightblock); 2407db96d56Sopenharmony_ci prevblock = deque->leftblock->rightlink; 2417db96d56Sopenharmony_ci freeblock(deque, deque->leftblock); 2427db96d56Sopenharmony_ci CHECK_NOT_END(prevblock); 2437db96d56Sopenharmony_ci MARK_END(prevblock->leftlink); 2447db96d56Sopenharmony_ci deque->leftblock = prevblock; 2457db96d56Sopenharmony_ci deque->leftindex = 0; 2467db96d56Sopenharmony_ci } else { 2477db96d56Sopenharmony_ci assert(deque->leftblock == deque->rightblock); 2487db96d56Sopenharmony_ci assert(deque->leftindex == deque->rightindex+1); 2497db96d56Sopenharmony_ci /* re-center instead of freeing a block */ 2507db96d56Sopenharmony_ci deque->leftindex = CENTER + 1; 2517db96d56Sopenharmony_ci deque->rightindex = CENTER; 2527db96d56Sopenharmony_ci } 2537db96d56Sopenharmony_ci } 2547db96d56Sopenharmony_ci return item; 2557db96d56Sopenharmony_ci} 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ciPyDoc_STRVAR(popleft_doc, "Remove and return the leftmost element."); 2587db96d56Sopenharmony_ci 2597db96d56Sopenharmony_ci/* The deque's size limit is d.maxlen. The limit can be zero or positive. 2607db96d56Sopenharmony_ci * If there is no limit, then d.maxlen == -1. 2617db96d56Sopenharmony_ci * 2627db96d56Sopenharmony_ci * After an item is added to a deque, we check to see if the size has 2637db96d56Sopenharmony_ci * grown past the limit. If it has, we get the size back down to the limit 2647db96d56Sopenharmony_ci * by popping an item off of the opposite end. The methods that can 2657db96d56Sopenharmony_ci * trigger this are append(), appendleft(), extend(), and extendleft(). 2667db96d56Sopenharmony_ci * 2677db96d56Sopenharmony_ci * The macro to check whether a deque needs to be trimmed uses a single 2687db96d56Sopenharmony_ci * unsigned test that returns true whenever 0 <= maxlen < Py_SIZE(deque). 2697db96d56Sopenharmony_ci */ 2707db96d56Sopenharmony_ci 2717db96d56Sopenharmony_ci#define NEEDS_TRIM(deque, maxlen) ((size_t)(maxlen) < (size_t)(Py_SIZE(deque))) 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_cistatic inline int 2747db96d56Sopenharmony_cideque_append_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen) 2757db96d56Sopenharmony_ci{ 2767db96d56Sopenharmony_ci if (deque->rightindex == BLOCKLEN - 1) { 2777db96d56Sopenharmony_ci block *b = newblock(deque); 2787db96d56Sopenharmony_ci if (b == NULL) 2797db96d56Sopenharmony_ci return -1; 2807db96d56Sopenharmony_ci b->leftlink = deque->rightblock; 2817db96d56Sopenharmony_ci CHECK_END(deque->rightblock->rightlink); 2827db96d56Sopenharmony_ci deque->rightblock->rightlink = b; 2837db96d56Sopenharmony_ci deque->rightblock = b; 2847db96d56Sopenharmony_ci MARK_END(b->rightlink); 2857db96d56Sopenharmony_ci deque->rightindex = -1; 2867db96d56Sopenharmony_ci } 2877db96d56Sopenharmony_ci Py_SET_SIZE(deque, Py_SIZE(deque) + 1); 2887db96d56Sopenharmony_ci deque->rightindex++; 2897db96d56Sopenharmony_ci deque->rightblock->data[deque->rightindex] = item; 2907db96d56Sopenharmony_ci if (NEEDS_TRIM(deque, maxlen)) { 2917db96d56Sopenharmony_ci PyObject *olditem = deque_popleft(deque, NULL); 2927db96d56Sopenharmony_ci Py_DECREF(olditem); 2937db96d56Sopenharmony_ci } else { 2947db96d56Sopenharmony_ci deque->state++; 2957db96d56Sopenharmony_ci } 2967db96d56Sopenharmony_ci return 0; 2977db96d56Sopenharmony_ci} 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_cistatic PyObject * 3007db96d56Sopenharmony_cideque_append(dequeobject *deque, PyObject *item) 3017db96d56Sopenharmony_ci{ 3027db96d56Sopenharmony_ci Py_INCREF(item); 3037db96d56Sopenharmony_ci if (deque_append_internal(deque, item, deque->maxlen) < 0) 3047db96d56Sopenharmony_ci return NULL; 3057db96d56Sopenharmony_ci Py_RETURN_NONE; 3067db96d56Sopenharmony_ci} 3077db96d56Sopenharmony_ci 3087db96d56Sopenharmony_ciPyDoc_STRVAR(append_doc, "Add an element to the right side of the deque."); 3097db96d56Sopenharmony_ci 3107db96d56Sopenharmony_cistatic inline int 3117db96d56Sopenharmony_cideque_appendleft_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen) 3127db96d56Sopenharmony_ci{ 3137db96d56Sopenharmony_ci if (deque->leftindex == 0) { 3147db96d56Sopenharmony_ci block *b = newblock(deque); 3157db96d56Sopenharmony_ci if (b == NULL) 3167db96d56Sopenharmony_ci return -1; 3177db96d56Sopenharmony_ci b->rightlink = deque->leftblock; 3187db96d56Sopenharmony_ci CHECK_END(deque->leftblock->leftlink); 3197db96d56Sopenharmony_ci deque->leftblock->leftlink = b; 3207db96d56Sopenharmony_ci deque->leftblock = b; 3217db96d56Sopenharmony_ci MARK_END(b->leftlink); 3227db96d56Sopenharmony_ci deque->leftindex = BLOCKLEN; 3237db96d56Sopenharmony_ci } 3247db96d56Sopenharmony_ci Py_SET_SIZE(deque, Py_SIZE(deque) + 1); 3257db96d56Sopenharmony_ci deque->leftindex--; 3267db96d56Sopenharmony_ci deque->leftblock->data[deque->leftindex] = item; 3277db96d56Sopenharmony_ci if (NEEDS_TRIM(deque, deque->maxlen)) { 3287db96d56Sopenharmony_ci PyObject *olditem = deque_pop(deque, NULL); 3297db96d56Sopenharmony_ci Py_DECREF(olditem); 3307db96d56Sopenharmony_ci } else { 3317db96d56Sopenharmony_ci deque->state++; 3327db96d56Sopenharmony_ci } 3337db96d56Sopenharmony_ci return 0; 3347db96d56Sopenharmony_ci} 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_cistatic PyObject * 3377db96d56Sopenharmony_cideque_appendleft(dequeobject *deque, PyObject *item) 3387db96d56Sopenharmony_ci{ 3397db96d56Sopenharmony_ci Py_INCREF(item); 3407db96d56Sopenharmony_ci if (deque_appendleft_internal(deque, item, deque->maxlen) < 0) 3417db96d56Sopenharmony_ci return NULL; 3427db96d56Sopenharmony_ci Py_RETURN_NONE; 3437db96d56Sopenharmony_ci} 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ciPyDoc_STRVAR(appendleft_doc, "Add an element to the left side of the deque."); 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_cistatic PyObject* 3487db96d56Sopenharmony_cifinalize_iterator(PyObject *it) 3497db96d56Sopenharmony_ci{ 3507db96d56Sopenharmony_ci if (PyErr_Occurred()) { 3517db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_StopIteration)) 3527db96d56Sopenharmony_ci PyErr_Clear(); 3537db96d56Sopenharmony_ci else { 3547db96d56Sopenharmony_ci Py_DECREF(it); 3557db96d56Sopenharmony_ci return NULL; 3567db96d56Sopenharmony_ci } 3577db96d56Sopenharmony_ci } 3587db96d56Sopenharmony_ci Py_DECREF(it); 3597db96d56Sopenharmony_ci Py_RETURN_NONE; 3607db96d56Sopenharmony_ci} 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ci/* Run an iterator to exhaustion. Shortcut for 3637db96d56Sopenharmony_ci the extend/extendleft methods when maxlen == 0. */ 3647db96d56Sopenharmony_cistatic PyObject* 3657db96d56Sopenharmony_ciconsume_iterator(PyObject *it) 3667db96d56Sopenharmony_ci{ 3677db96d56Sopenharmony_ci PyObject *(*iternext)(PyObject *); 3687db96d56Sopenharmony_ci PyObject *item; 3697db96d56Sopenharmony_ci 3707db96d56Sopenharmony_ci iternext = *Py_TYPE(it)->tp_iternext; 3717db96d56Sopenharmony_ci while ((item = iternext(it)) != NULL) { 3727db96d56Sopenharmony_ci Py_DECREF(item); 3737db96d56Sopenharmony_ci } 3747db96d56Sopenharmony_ci return finalize_iterator(it); 3757db96d56Sopenharmony_ci} 3767db96d56Sopenharmony_ci 3777db96d56Sopenharmony_cistatic PyObject * 3787db96d56Sopenharmony_cideque_extend(dequeobject *deque, PyObject *iterable) 3797db96d56Sopenharmony_ci{ 3807db96d56Sopenharmony_ci PyObject *it, *item; 3817db96d56Sopenharmony_ci PyObject *(*iternext)(PyObject *); 3827db96d56Sopenharmony_ci Py_ssize_t maxlen = deque->maxlen; 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci /* Handle case where id(deque) == id(iterable) */ 3857db96d56Sopenharmony_ci if ((PyObject *)deque == iterable) { 3867db96d56Sopenharmony_ci PyObject *result; 3877db96d56Sopenharmony_ci PyObject *s = PySequence_List(iterable); 3887db96d56Sopenharmony_ci if (s == NULL) 3897db96d56Sopenharmony_ci return NULL; 3907db96d56Sopenharmony_ci result = deque_extend(deque, s); 3917db96d56Sopenharmony_ci Py_DECREF(s); 3927db96d56Sopenharmony_ci return result; 3937db96d56Sopenharmony_ci } 3947db96d56Sopenharmony_ci 3957db96d56Sopenharmony_ci it = PyObject_GetIter(iterable); 3967db96d56Sopenharmony_ci if (it == NULL) 3977db96d56Sopenharmony_ci return NULL; 3987db96d56Sopenharmony_ci 3997db96d56Sopenharmony_ci if (maxlen == 0) 4007db96d56Sopenharmony_ci return consume_iterator(it); 4017db96d56Sopenharmony_ci 4027db96d56Sopenharmony_ci /* Space saving heuristic. Start filling from the left */ 4037db96d56Sopenharmony_ci if (Py_SIZE(deque) == 0) { 4047db96d56Sopenharmony_ci assert(deque->leftblock == deque->rightblock); 4057db96d56Sopenharmony_ci assert(deque->leftindex == deque->rightindex+1); 4067db96d56Sopenharmony_ci deque->leftindex = 1; 4077db96d56Sopenharmony_ci deque->rightindex = 0; 4087db96d56Sopenharmony_ci } 4097db96d56Sopenharmony_ci 4107db96d56Sopenharmony_ci iternext = *Py_TYPE(it)->tp_iternext; 4117db96d56Sopenharmony_ci while ((item = iternext(it)) != NULL) { 4127db96d56Sopenharmony_ci if (deque_append_internal(deque, item, maxlen) == -1) { 4137db96d56Sopenharmony_ci Py_DECREF(item); 4147db96d56Sopenharmony_ci Py_DECREF(it); 4157db96d56Sopenharmony_ci return NULL; 4167db96d56Sopenharmony_ci } 4177db96d56Sopenharmony_ci } 4187db96d56Sopenharmony_ci return finalize_iterator(it); 4197db96d56Sopenharmony_ci} 4207db96d56Sopenharmony_ci 4217db96d56Sopenharmony_ciPyDoc_STRVAR(extend_doc, 4227db96d56Sopenharmony_ci"Extend the right side of the deque with elements from the iterable"); 4237db96d56Sopenharmony_ci 4247db96d56Sopenharmony_cistatic PyObject * 4257db96d56Sopenharmony_cideque_extendleft(dequeobject *deque, PyObject *iterable) 4267db96d56Sopenharmony_ci{ 4277db96d56Sopenharmony_ci PyObject *it, *item; 4287db96d56Sopenharmony_ci PyObject *(*iternext)(PyObject *); 4297db96d56Sopenharmony_ci Py_ssize_t maxlen = deque->maxlen; 4307db96d56Sopenharmony_ci 4317db96d56Sopenharmony_ci /* Handle case where id(deque) == id(iterable) */ 4327db96d56Sopenharmony_ci if ((PyObject *)deque == iterable) { 4337db96d56Sopenharmony_ci PyObject *result; 4347db96d56Sopenharmony_ci PyObject *s = PySequence_List(iterable); 4357db96d56Sopenharmony_ci if (s == NULL) 4367db96d56Sopenharmony_ci return NULL; 4377db96d56Sopenharmony_ci result = deque_extendleft(deque, s); 4387db96d56Sopenharmony_ci Py_DECREF(s); 4397db96d56Sopenharmony_ci return result; 4407db96d56Sopenharmony_ci } 4417db96d56Sopenharmony_ci 4427db96d56Sopenharmony_ci it = PyObject_GetIter(iterable); 4437db96d56Sopenharmony_ci if (it == NULL) 4447db96d56Sopenharmony_ci return NULL; 4457db96d56Sopenharmony_ci 4467db96d56Sopenharmony_ci if (maxlen == 0) 4477db96d56Sopenharmony_ci return consume_iterator(it); 4487db96d56Sopenharmony_ci 4497db96d56Sopenharmony_ci /* Space saving heuristic. Start filling from the right */ 4507db96d56Sopenharmony_ci if (Py_SIZE(deque) == 0) { 4517db96d56Sopenharmony_ci assert(deque->leftblock == deque->rightblock); 4527db96d56Sopenharmony_ci assert(deque->leftindex == deque->rightindex+1); 4537db96d56Sopenharmony_ci deque->leftindex = BLOCKLEN - 1; 4547db96d56Sopenharmony_ci deque->rightindex = BLOCKLEN - 2; 4557db96d56Sopenharmony_ci } 4567db96d56Sopenharmony_ci 4577db96d56Sopenharmony_ci iternext = *Py_TYPE(it)->tp_iternext; 4587db96d56Sopenharmony_ci while ((item = iternext(it)) != NULL) { 4597db96d56Sopenharmony_ci if (deque_appendleft_internal(deque, item, maxlen) == -1) { 4607db96d56Sopenharmony_ci Py_DECREF(item); 4617db96d56Sopenharmony_ci Py_DECREF(it); 4627db96d56Sopenharmony_ci return NULL; 4637db96d56Sopenharmony_ci } 4647db96d56Sopenharmony_ci } 4657db96d56Sopenharmony_ci return finalize_iterator(it); 4667db96d56Sopenharmony_ci} 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ciPyDoc_STRVAR(extendleft_doc, 4697db96d56Sopenharmony_ci"Extend the left side of the deque with elements from the iterable"); 4707db96d56Sopenharmony_ci 4717db96d56Sopenharmony_cistatic PyObject * 4727db96d56Sopenharmony_cideque_inplace_concat(dequeobject *deque, PyObject *other) 4737db96d56Sopenharmony_ci{ 4747db96d56Sopenharmony_ci PyObject *result; 4757db96d56Sopenharmony_ci 4767db96d56Sopenharmony_ci result = deque_extend(deque, other); 4777db96d56Sopenharmony_ci if (result == NULL) 4787db96d56Sopenharmony_ci return result; 4797db96d56Sopenharmony_ci Py_INCREF(deque); 4807db96d56Sopenharmony_ci Py_DECREF(result); 4817db96d56Sopenharmony_ci return (PyObject *)deque; 4827db96d56Sopenharmony_ci} 4837db96d56Sopenharmony_ci 4847db96d56Sopenharmony_cistatic PyObject * 4857db96d56Sopenharmony_cideque_copy(PyObject *deque, PyObject *Py_UNUSED(ignored)) 4867db96d56Sopenharmony_ci{ 4877db96d56Sopenharmony_ci PyObject *result; 4887db96d56Sopenharmony_ci dequeobject *old_deque = (dequeobject *)deque; 4897db96d56Sopenharmony_ci if (Py_IS_TYPE(deque, &deque_type)) { 4907db96d56Sopenharmony_ci dequeobject *new_deque; 4917db96d56Sopenharmony_ci PyObject *rv; 4927db96d56Sopenharmony_ci 4937db96d56Sopenharmony_ci new_deque = (dequeobject *)deque_new(&deque_type, (PyObject *)NULL, (PyObject *)NULL); 4947db96d56Sopenharmony_ci if (new_deque == NULL) 4957db96d56Sopenharmony_ci return NULL; 4967db96d56Sopenharmony_ci new_deque->maxlen = old_deque->maxlen; 4977db96d56Sopenharmony_ci /* Fast path for the deque_repeat() common case where len(deque) == 1 */ 4987db96d56Sopenharmony_ci if (Py_SIZE(deque) == 1) { 4997db96d56Sopenharmony_ci PyObject *item = old_deque->leftblock->data[old_deque->leftindex]; 5007db96d56Sopenharmony_ci rv = deque_append(new_deque, item); 5017db96d56Sopenharmony_ci } else { 5027db96d56Sopenharmony_ci rv = deque_extend(new_deque, deque); 5037db96d56Sopenharmony_ci } 5047db96d56Sopenharmony_ci if (rv != NULL) { 5057db96d56Sopenharmony_ci Py_DECREF(rv); 5067db96d56Sopenharmony_ci return (PyObject *)new_deque; 5077db96d56Sopenharmony_ci } 5087db96d56Sopenharmony_ci Py_DECREF(new_deque); 5097db96d56Sopenharmony_ci return NULL; 5107db96d56Sopenharmony_ci } 5117db96d56Sopenharmony_ci if (old_deque->maxlen < 0) 5127db96d56Sopenharmony_ci result = PyObject_CallOneArg((PyObject *)(Py_TYPE(deque)), deque); 5137db96d56Sopenharmony_ci else 5147db96d56Sopenharmony_ci result = PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "Oi", 5157db96d56Sopenharmony_ci deque, old_deque->maxlen, NULL); 5167db96d56Sopenharmony_ci if (result != NULL && !PyObject_TypeCheck(result, &deque_type)) { 5177db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 5187db96d56Sopenharmony_ci "%.200s() must return a deque, not %.200s", 5197db96d56Sopenharmony_ci Py_TYPE(deque)->tp_name, Py_TYPE(result)->tp_name); 5207db96d56Sopenharmony_ci Py_DECREF(result); 5217db96d56Sopenharmony_ci return NULL; 5227db96d56Sopenharmony_ci } 5237db96d56Sopenharmony_ci return result; 5247db96d56Sopenharmony_ci} 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_ciPyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque."); 5277db96d56Sopenharmony_ci 5287db96d56Sopenharmony_cistatic PyObject * 5297db96d56Sopenharmony_cideque_concat(dequeobject *deque, PyObject *other) 5307db96d56Sopenharmony_ci{ 5317db96d56Sopenharmony_ci PyObject *new_deque, *result; 5327db96d56Sopenharmony_ci int rv; 5337db96d56Sopenharmony_ci 5347db96d56Sopenharmony_ci rv = PyObject_IsInstance(other, (PyObject *)&deque_type); 5357db96d56Sopenharmony_ci if (rv <= 0) { 5367db96d56Sopenharmony_ci if (rv == 0) { 5377db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 5387db96d56Sopenharmony_ci "can only concatenate deque (not \"%.200s\") to deque", 5397db96d56Sopenharmony_ci Py_TYPE(other)->tp_name); 5407db96d56Sopenharmony_ci } 5417db96d56Sopenharmony_ci return NULL; 5427db96d56Sopenharmony_ci } 5437db96d56Sopenharmony_ci 5447db96d56Sopenharmony_ci new_deque = deque_copy((PyObject *)deque, NULL); 5457db96d56Sopenharmony_ci if (new_deque == NULL) 5467db96d56Sopenharmony_ci return NULL; 5477db96d56Sopenharmony_ci result = deque_extend((dequeobject *)new_deque, other); 5487db96d56Sopenharmony_ci if (result == NULL) { 5497db96d56Sopenharmony_ci Py_DECREF(new_deque); 5507db96d56Sopenharmony_ci return NULL; 5517db96d56Sopenharmony_ci } 5527db96d56Sopenharmony_ci Py_DECREF(result); 5537db96d56Sopenharmony_ci return new_deque; 5547db96d56Sopenharmony_ci} 5557db96d56Sopenharmony_ci 5567db96d56Sopenharmony_cistatic int 5577db96d56Sopenharmony_cideque_clear(dequeobject *deque) 5587db96d56Sopenharmony_ci{ 5597db96d56Sopenharmony_ci block *b; 5607db96d56Sopenharmony_ci block *prevblock; 5617db96d56Sopenharmony_ci block *leftblock; 5627db96d56Sopenharmony_ci Py_ssize_t leftindex; 5637db96d56Sopenharmony_ci Py_ssize_t n, m; 5647db96d56Sopenharmony_ci PyObject *item; 5657db96d56Sopenharmony_ci PyObject **itemptr, **limit; 5667db96d56Sopenharmony_ci 5677db96d56Sopenharmony_ci if (Py_SIZE(deque) == 0) 5687db96d56Sopenharmony_ci return 0; 5697db96d56Sopenharmony_ci 5707db96d56Sopenharmony_ci /* During the process of clearing a deque, decrefs can cause the 5717db96d56Sopenharmony_ci deque to mutate. To avoid fatal confusion, we have to make the 5727db96d56Sopenharmony_ci deque empty before clearing the blocks and never refer to 5737db96d56Sopenharmony_ci anything via deque->ref while clearing. (This is the same 5747db96d56Sopenharmony_ci technique used for clearing lists, sets, and dicts.) 5757db96d56Sopenharmony_ci 5767db96d56Sopenharmony_ci Making the deque empty requires allocating a new empty block. In 5777db96d56Sopenharmony_ci the unlikely event that memory is full, we fall back to an 5787db96d56Sopenharmony_ci alternate method that doesn't require a new block. Repeating 5797db96d56Sopenharmony_ci pops in a while-loop is slower, possibly re-entrant (and a clever 5807db96d56Sopenharmony_ci adversary could cause it to never terminate). 5817db96d56Sopenharmony_ci */ 5827db96d56Sopenharmony_ci 5837db96d56Sopenharmony_ci b = newblock(deque); 5847db96d56Sopenharmony_ci if (b == NULL) { 5857db96d56Sopenharmony_ci PyErr_Clear(); 5867db96d56Sopenharmony_ci goto alternate_method; 5877db96d56Sopenharmony_ci } 5887db96d56Sopenharmony_ci 5897db96d56Sopenharmony_ci /* Remember the old size, leftblock, and leftindex */ 5907db96d56Sopenharmony_ci n = Py_SIZE(deque); 5917db96d56Sopenharmony_ci leftblock = deque->leftblock; 5927db96d56Sopenharmony_ci leftindex = deque->leftindex; 5937db96d56Sopenharmony_ci 5947db96d56Sopenharmony_ci /* Set the deque to be empty using the newly allocated block */ 5957db96d56Sopenharmony_ci MARK_END(b->leftlink); 5967db96d56Sopenharmony_ci MARK_END(b->rightlink); 5977db96d56Sopenharmony_ci Py_SET_SIZE(deque, 0); 5987db96d56Sopenharmony_ci deque->leftblock = b; 5997db96d56Sopenharmony_ci deque->rightblock = b; 6007db96d56Sopenharmony_ci deque->leftindex = CENTER + 1; 6017db96d56Sopenharmony_ci deque->rightindex = CENTER; 6027db96d56Sopenharmony_ci deque->state++; 6037db96d56Sopenharmony_ci 6047db96d56Sopenharmony_ci /* Now the old size, leftblock, and leftindex are disconnected from 6057db96d56Sopenharmony_ci the empty deque and we can use them to decref the pointers. 6067db96d56Sopenharmony_ci */ 6077db96d56Sopenharmony_ci m = (BLOCKLEN - leftindex > n) ? n : BLOCKLEN - leftindex; 6087db96d56Sopenharmony_ci itemptr = &leftblock->data[leftindex]; 6097db96d56Sopenharmony_ci limit = itemptr + m; 6107db96d56Sopenharmony_ci n -= m; 6117db96d56Sopenharmony_ci while (1) { 6127db96d56Sopenharmony_ci if (itemptr == limit) { 6137db96d56Sopenharmony_ci if (n == 0) 6147db96d56Sopenharmony_ci break; 6157db96d56Sopenharmony_ci CHECK_NOT_END(leftblock->rightlink); 6167db96d56Sopenharmony_ci prevblock = leftblock; 6177db96d56Sopenharmony_ci leftblock = leftblock->rightlink; 6187db96d56Sopenharmony_ci m = (n > BLOCKLEN) ? BLOCKLEN : n; 6197db96d56Sopenharmony_ci itemptr = leftblock->data; 6207db96d56Sopenharmony_ci limit = itemptr + m; 6217db96d56Sopenharmony_ci n -= m; 6227db96d56Sopenharmony_ci freeblock(deque, prevblock); 6237db96d56Sopenharmony_ci } 6247db96d56Sopenharmony_ci item = *(itemptr++); 6257db96d56Sopenharmony_ci Py_DECREF(item); 6267db96d56Sopenharmony_ci } 6277db96d56Sopenharmony_ci CHECK_END(leftblock->rightlink); 6287db96d56Sopenharmony_ci freeblock(deque, leftblock); 6297db96d56Sopenharmony_ci return 0; 6307db96d56Sopenharmony_ci 6317db96d56Sopenharmony_ci alternate_method: 6327db96d56Sopenharmony_ci while (Py_SIZE(deque)) { 6337db96d56Sopenharmony_ci item = deque_pop(deque, NULL); 6347db96d56Sopenharmony_ci assert (item != NULL); 6357db96d56Sopenharmony_ci Py_DECREF(item); 6367db96d56Sopenharmony_ci } 6377db96d56Sopenharmony_ci return 0; 6387db96d56Sopenharmony_ci} 6397db96d56Sopenharmony_ci 6407db96d56Sopenharmony_cistatic PyObject * 6417db96d56Sopenharmony_cideque_clearmethod(dequeobject *deque, PyObject *Py_UNUSED(ignored)) 6427db96d56Sopenharmony_ci{ 6437db96d56Sopenharmony_ci deque_clear(deque); 6447db96d56Sopenharmony_ci Py_RETURN_NONE; 6457db96d56Sopenharmony_ci} 6467db96d56Sopenharmony_ci 6477db96d56Sopenharmony_ciPyDoc_STRVAR(clear_doc, "Remove all elements from the deque."); 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_cistatic PyObject * 6507db96d56Sopenharmony_cideque_inplace_repeat(dequeobject *deque, Py_ssize_t n) 6517db96d56Sopenharmony_ci{ 6527db96d56Sopenharmony_ci Py_ssize_t i, m, size; 6537db96d56Sopenharmony_ci PyObject *seq; 6547db96d56Sopenharmony_ci PyObject *rv; 6557db96d56Sopenharmony_ci 6567db96d56Sopenharmony_ci size = Py_SIZE(deque); 6577db96d56Sopenharmony_ci if (size == 0 || n == 1) { 6587db96d56Sopenharmony_ci Py_INCREF(deque); 6597db96d56Sopenharmony_ci return (PyObject *)deque; 6607db96d56Sopenharmony_ci } 6617db96d56Sopenharmony_ci 6627db96d56Sopenharmony_ci if (n <= 0) { 6637db96d56Sopenharmony_ci deque_clear(deque); 6647db96d56Sopenharmony_ci Py_INCREF(deque); 6657db96d56Sopenharmony_ci return (PyObject *)deque; 6667db96d56Sopenharmony_ci } 6677db96d56Sopenharmony_ci 6687db96d56Sopenharmony_ci if (size == 1) { 6697db96d56Sopenharmony_ci /* common case, repeating a single element */ 6707db96d56Sopenharmony_ci PyObject *item = deque->leftblock->data[deque->leftindex]; 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci if (deque->maxlen >= 0 && n > deque->maxlen) 6737db96d56Sopenharmony_ci n = deque->maxlen; 6747db96d56Sopenharmony_ci 6757db96d56Sopenharmony_ci deque->state++; 6767db96d56Sopenharmony_ci for (i = 0 ; i < n-1 ; ) { 6777db96d56Sopenharmony_ci if (deque->rightindex == BLOCKLEN - 1) { 6787db96d56Sopenharmony_ci block *b = newblock(deque); 6797db96d56Sopenharmony_ci if (b == NULL) { 6807db96d56Sopenharmony_ci Py_SET_SIZE(deque, Py_SIZE(deque) + i); 6817db96d56Sopenharmony_ci return NULL; 6827db96d56Sopenharmony_ci } 6837db96d56Sopenharmony_ci b->leftlink = deque->rightblock; 6847db96d56Sopenharmony_ci CHECK_END(deque->rightblock->rightlink); 6857db96d56Sopenharmony_ci deque->rightblock->rightlink = b; 6867db96d56Sopenharmony_ci deque->rightblock = b; 6877db96d56Sopenharmony_ci MARK_END(b->rightlink); 6887db96d56Sopenharmony_ci deque->rightindex = -1; 6897db96d56Sopenharmony_ci } 6907db96d56Sopenharmony_ci m = n - 1 - i; 6917db96d56Sopenharmony_ci if (m > BLOCKLEN - 1 - deque->rightindex) 6927db96d56Sopenharmony_ci m = BLOCKLEN - 1 - deque->rightindex; 6937db96d56Sopenharmony_ci i += m; 6947db96d56Sopenharmony_ci while (m--) { 6957db96d56Sopenharmony_ci deque->rightindex++; 6967db96d56Sopenharmony_ci Py_INCREF(item); 6977db96d56Sopenharmony_ci deque->rightblock->data[deque->rightindex] = item; 6987db96d56Sopenharmony_ci } 6997db96d56Sopenharmony_ci } 7007db96d56Sopenharmony_ci Py_SET_SIZE(deque, Py_SIZE(deque) + i); 7017db96d56Sopenharmony_ci Py_INCREF(deque); 7027db96d56Sopenharmony_ci return (PyObject *)deque; 7037db96d56Sopenharmony_ci } 7047db96d56Sopenharmony_ci 7057db96d56Sopenharmony_ci if ((size_t)size > PY_SSIZE_T_MAX / (size_t)n) { 7067db96d56Sopenharmony_ci return PyErr_NoMemory(); 7077db96d56Sopenharmony_ci } 7087db96d56Sopenharmony_ci 7097db96d56Sopenharmony_ci seq = PySequence_List((PyObject *)deque); 7107db96d56Sopenharmony_ci if (seq == NULL) 7117db96d56Sopenharmony_ci return seq; 7127db96d56Sopenharmony_ci 7137db96d56Sopenharmony_ci /* Reduce the number of repetitions when maxlen would be exceeded */ 7147db96d56Sopenharmony_ci if (deque->maxlen >= 0 && n * size > deque->maxlen) 7157db96d56Sopenharmony_ci n = (deque->maxlen + size - 1) / size; 7167db96d56Sopenharmony_ci 7177db96d56Sopenharmony_ci for (i = 0 ; i < n-1 ; i++) { 7187db96d56Sopenharmony_ci rv = deque_extend(deque, seq); 7197db96d56Sopenharmony_ci if (rv == NULL) { 7207db96d56Sopenharmony_ci Py_DECREF(seq); 7217db96d56Sopenharmony_ci return NULL; 7227db96d56Sopenharmony_ci } 7237db96d56Sopenharmony_ci Py_DECREF(rv); 7247db96d56Sopenharmony_ci } 7257db96d56Sopenharmony_ci Py_INCREF(deque); 7267db96d56Sopenharmony_ci Py_DECREF(seq); 7277db96d56Sopenharmony_ci return (PyObject *)deque; 7287db96d56Sopenharmony_ci} 7297db96d56Sopenharmony_ci 7307db96d56Sopenharmony_cistatic PyObject * 7317db96d56Sopenharmony_cideque_repeat(dequeobject *deque, Py_ssize_t n) 7327db96d56Sopenharmony_ci{ 7337db96d56Sopenharmony_ci dequeobject *new_deque; 7347db96d56Sopenharmony_ci PyObject *rv; 7357db96d56Sopenharmony_ci 7367db96d56Sopenharmony_ci new_deque = (dequeobject *)deque_copy((PyObject *) deque, NULL); 7377db96d56Sopenharmony_ci if (new_deque == NULL) 7387db96d56Sopenharmony_ci return NULL; 7397db96d56Sopenharmony_ci rv = deque_inplace_repeat(new_deque, n); 7407db96d56Sopenharmony_ci Py_DECREF(new_deque); 7417db96d56Sopenharmony_ci return rv; 7427db96d56Sopenharmony_ci} 7437db96d56Sopenharmony_ci 7447db96d56Sopenharmony_ci/* The rotate() method is part of the public API and is used internally 7457db96d56Sopenharmony_cias a primitive for other methods. 7467db96d56Sopenharmony_ci 7477db96d56Sopenharmony_ciRotation by 1 or -1 is a common case, so any optimizations for high 7487db96d56Sopenharmony_civolume rotations should take care not to penalize the common case. 7497db96d56Sopenharmony_ci 7507db96d56Sopenharmony_ciConceptually, a rotate by one is equivalent to a pop on one side and an 7517db96d56Sopenharmony_ciappend on the other. However, a pop/append pair is unnecessarily slow 7527db96d56Sopenharmony_cibecause it requires an incref/decref pair for an object located randomly 7537db96d56Sopenharmony_ciin memory. It is better to just move the object pointer from one block 7547db96d56Sopenharmony_cito the next without changing the reference count. 7557db96d56Sopenharmony_ci 7567db96d56Sopenharmony_ciWhen moving batches of pointers, it is tempting to use memcpy() but that 7577db96d56Sopenharmony_ciproved to be slower than a simple loop for a variety of reasons. 7587db96d56Sopenharmony_ciMemcpy() cannot know in advance that we're copying pointers instead of 7597db96d56Sopenharmony_cibytes, that the source and destination are pointer aligned and 7607db96d56Sopenharmony_cinon-overlapping, that moving just one pointer is a common case, that we 7617db96d56Sopenharmony_cinever need to move more than BLOCKLEN pointers, and that at least one 7627db96d56Sopenharmony_cipointer is always moved. 7637db96d56Sopenharmony_ci 7647db96d56Sopenharmony_ciFor high volume rotations, newblock() and freeblock() are never called 7657db96d56Sopenharmony_cimore than once. Previously emptied blocks are immediately reused as a 7667db96d56Sopenharmony_cidestination block. If a block is left-over at the end, it is freed. 7677db96d56Sopenharmony_ci*/ 7687db96d56Sopenharmony_ci 7697db96d56Sopenharmony_cistatic int 7707db96d56Sopenharmony_ci_deque_rotate(dequeobject *deque, Py_ssize_t n) 7717db96d56Sopenharmony_ci{ 7727db96d56Sopenharmony_ci block *b = NULL; 7737db96d56Sopenharmony_ci block *leftblock = deque->leftblock; 7747db96d56Sopenharmony_ci block *rightblock = deque->rightblock; 7757db96d56Sopenharmony_ci Py_ssize_t leftindex = deque->leftindex; 7767db96d56Sopenharmony_ci Py_ssize_t rightindex = deque->rightindex; 7777db96d56Sopenharmony_ci Py_ssize_t len=Py_SIZE(deque), halflen=len>>1; 7787db96d56Sopenharmony_ci int rv = -1; 7797db96d56Sopenharmony_ci 7807db96d56Sopenharmony_ci if (len <= 1) 7817db96d56Sopenharmony_ci return 0; 7827db96d56Sopenharmony_ci if (n > halflen || n < -halflen) { 7837db96d56Sopenharmony_ci n %= len; 7847db96d56Sopenharmony_ci if (n > halflen) 7857db96d56Sopenharmony_ci n -= len; 7867db96d56Sopenharmony_ci else if (n < -halflen) 7877db96d56Sopenharmony_ci n += len; 7887db96d56Sopenharmony_ci } 7897db96d56Sopenharmony_ci assert(len > 1); 7907db96d56Sopenharmony_ci assert(-halflen <= n && n <= halflen); 7917db96d56Sopenharmony_ci 7927db96d56Sopenharmony_ci deque->state++; 7937db96d56Sopenharmony_ci while (n > 0) { 7947db96d56Sopenharmony_ci if (leftindex == 0) { 7957db96d56Sopenharmony_ci if (b == NULL) { 7967db96d56Sopenharmony_ci b = newblock(deque); 7977db96d56Sopenharmony_ci if (b == NULL) 7987db96d56Sopenharmony_ci goto done; 7997db96d56Sopenharmony_ci } 8007db96d56Sopenharmony_ci b->rightlink = leftblock; 8017db96d56Sopenharmony_ci CHECK_END(leftblock->leftlink); 8027db96d56Sopenharmony_ci leftblock->leftlink = b; 8037db96d56Sopenharmony_ci leftblock = b; 8047db96d56Sopenharmony_ci MARK_END(b->leftlink); 8057db96d56Sopenharmony_ci leftindex = BLOCKLEN; 8067db96d56Sopenharmony_ci b = NULL; 8077db96d56Sopenharmony_ci } 8087db96d56Sopenharmony_ci assert(leftindex > 0); 8097db96d56Sopenharmony_ci { 8107db96d56Sopenharmony_ci PyObject **src, **dest; 8117db96d56Sopenharmony_ci Py_ssize_t m = n; 8127db96d56Sopenharmony_ci 8137db96d56Sopenharmony_ci if (m > rightindex + 1) 8147db96d56Sopenharmony_ci m = rightindex + 1; 8157db96d56Sopenharmony_ci if (m > leftindex) 8167db96d56Sopenharmony_ci m = leftindex; 8177db96d56Sopenharmony_ci assert (m > 0 && m <= len); 8187db96d56Sopenharmony_ci rightindex -= m; 8197db96d56Sopenharmony_ci leftindex -= m; 8207db96d56Sopenharmony_ci src = &rightblock->data[rightindex + 1]; 8217db96d56Sopenharmony_ci dest = &leftblock->data[leftindex]; 8227db96d56Sopenharmony_ci n -= m; 8237db96d56Sopenharmony_ci do { 8247db96d56Sopenharmony_ci *(dest++) = *(src++); 8257db96d56Sopenharmony_ci } while (--m); 8267db96d56Sopenharmony_ci } 8277db96d56Sopenharmony_ci if (rightindex < 0) { 8287db96d56Sopenharmony_ci assert(leftblock != rightblock); 8297db96d56Sopenharmony_ci assert(b == NULL); 8307db96d56Sopenharmony_ci b = rightblock; 8317db96d56Sopenharmony_ci CHECK_NOT_END(rightblock->leftlink); 8327db96d56Sopenharmony_ci rightblock = rightblock->leftlink; 8337db96d56Sopenharmony_ci MARK_END(rightblock->rightlink); 8347db96d56Sopenharmony_ci rightindex = BLOCKLEN - 1; 8357db96d56Sopenharmony_ci } 8367db96d56Sopenharmony_ci } 8377db96d56Sopenharmony_ci while (n < 0) { 8387db96d56Sopenharmony_ci if (rightindex == BLOCKLEN - 1) { 8397db96d56Sopenharmony_ci if (b == NULL) { 8407db96d56Sopenharmony_ci b = newblock(deque); 8417db96d56Sopenharmony_ci if (b == NULL) 8427db96d56Sopenharmony_ci goto done; 8437db96d56Sopenharmony_ci } 8447db96d56Sopenharmony_ci b->leftlink = rightblock; 8457db96d56Sopenharmony_ci CHECK_END(rightblock->rightlink); 8467db96d56Sopenharmony_ci rightblock->rightlink = b; 8477db96d56Sopenharmony_ci rightblock = b; 8487db96d56Sopenharmony_ci MARK_END(b->rightlink); 8497db96d56Sopenharmony_ci rightindex = -1; 8507db96d56Sopenharmony_ci b = NULL; 8517db96d56Sopenharmony_ci } 8527db96d56Sopenharmony_ci assert (rightindex < BLOCKLEN - 1); 8537db96d56Sopenharmony_ci { 8547db96d56Sopenharmony_ci PyObject **src, **dest; 8557db96d56Sopenharmony_ci Py_ssize_t m = -n; 8567db96d56Sopenharmony_ci 8577db96d56Sopenharmony_ci if (m > BLOCKLEN - leftindex) 8587db96d56Sopenharmony_ci m = BLOCKLEN - leftindex; 8597db96d56Sopenharmony_ci if (m > BLOCKLEN - 1 - rightindex) 8607db96d56Sopenharmony_ci m = BLOCKLEN - 1 - rightindex; 8617db96d56Sopenharmony_ci assert (m > 0 && m <= len); 8627db96d56Sopenharmony_ci src = &leftblock->data[leftindex]; 8637db96d56Sopenharmony_ci dest = &rightblock->data[rightindex + 1]; 8647db96d56Sopenharmony_ci leftindex += m; 8657db96d56Sopenharmony_ci rightindex += m; 8667db96d56Sopenharmony_ci n += m; 8677db96d56Sopenharmony_ci do { 8687db96d56Sopenharmony_ci *(dest++) = *(src++); 8697db96d56Sopenharmony_ci } while (--m); 8707db96d56Sopenharmony_ci } 8717db96d56Sopenharmony_ci if (leftindex == BLOCKLEN) { 8727db96d56Sopenharmony_ci assert(leftblock != rightblock); 8737db96d56Sopenharmony_ci assert(b == NULL); 8747db96d56Sopenharmony_ci b = leftblock; 8757db96d56Sopenharmony_ci CHECK_NOT_END(leftblock->rightlink); 8767db96d56Sopenharmony_ci leftblock = leftblock->rightlink; 8777db96d56Sopenharmony_ci MARK_END(leftblock->leftlink); 8787db96d56Sopenharmony_ci leftindex = 0; 8797db96d56Sopenharmony_ci } 8807db96d56Sopenharmony_ci } 8817db96d56Sopenharmony_ci rv = 0; 8827db96d56Sopenharmony_cidone: 8837db96d56Sopenharmony_ci if (b != NULL) 8847db96d56Sopenharmony_ci freeblock(deque, b); 8857db96d56Sopenharmony_ci deque->leftblock = leftblock; 8867db96d56Sopenharmony_ci deque->rightblock = rightblock; 8877db96d56Sopenharmony_ci deque->leftindex = leftindex; 8887db96d56Sopenharmony_ci deque->rightindex = rightindex; 8897db96d56Sopenharmony_ci 8907db96d56Sopenharmony_ci return rv; 8917db96d56Sopenharmony_ci} 8927db96d56Sopenharmony_ci 8937db96d56Sopenharmony_cistatic PyObject * 8947db96d56Sopenharmony_cideque_rotate(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) 8957db96d56Sopenharmony_ci{ 8967db96d56Sopenharmony_ci Py_ssize_t n=1; 8977db96d56Sopenharmony_ci 8987db96d56Sopenharmony_ci if (!_PyArg_CheckPositional("deque.rotate", nargs, 0, 1)) { 8997db96d56Sopenharmony_ci return NULL; 9007db96d56Sopenharmony_ci } 9017db96d56Sopenharmony_ci if (nargs) { 9027db96d56Sopenharmony_ci PyObject *index = _PyNumber_Index(args[0]); 9037db96d56Sopenharmony_ci if (index == NULL) { 9047db96d56Sopenharmony_ci return NULL; 9057db96d56Sopenharmony_ci } 9067db96d56Sopenharmony_ci n = PyLong_AsSsize_t(index); 9077db96d56Sopenharmony_ci Py_DECREF(index); 9087db96d56Sopenharmony_ci if (n == -1 && PyErr_Occurred()) { 9097db96d56Sopenharmony_ci return NULL; 9107db96d56Sopenharmony_ci } 9117db96d56Sopenharmony_ci } 9127db96d56Sopenharmony_ci 9137db96d56Sopenharmony_ci if (!_deque_rotate(deque, n)) 9147db96d56Sopenharmony_ci Py_RETURN_NONE; 9157db96d56Sopenharmony_ci return NULL; 9167db96d56Sopenharmony_ci} 9177db96d56Sopenharmony_ci 9187db96d56Sopenharmony_ciPyDoc_STRVAR(rotate_doc, 9197db96d56Sopenharmony_ci"Rotate the deque n steps to the right (default n=1). If n is negative, rotates left."); 9207db96d56Sopenharmony_ci 9217db96d56Sopenharmony_cistatic PyObject * 9227db96d56Sopenharmony_cideque_reverse(dequeobject *deque, PyObject *unused) 9237db96d56Sopenharmony_ci{ 9247db96d56Sopenharmony_ci block *leftblock = deque->leftblock; 9257db96d56Sopenharmony_ci block *rightblock = deque->rightblock; 9267db96d56Sopenharmony_ci Py_ssize_t leftindex = deque->leftindex; 9277db96d56Sopenharmony_ci Py_ssize_t rightindex = deque->rightindex; 9287db96d56Sopenharmony_ci Py_ssize_t n = Py_SIZE(deque) >> 1; 9297db96d56Sopenharmony_ci PyObject *tmp; 9307db96d56Sopenharmony_ci 9317db96d56Sopenharmony_ci while (--n >= 0) { 9327db96d56Sopenharmony_ci /* Validate that pointers haven't met in the middle */ 9337db96d56Sopenharmony_ci assert(leftblock != rightblock || leftindex < rightindex); 9347db96d56Sopenharmony_ci CHECK_NOT_END(leftblock); 9357db96d56Sopenharmony_ci CHECK_NOT_END(rightblock); 9367db96d56Sopenharmony_ci 9377db96d56Sopenharmony_ci /* Swap */ 9387db96d56Sopenharmony_ci tmp = leftblock->data[leftindex]; 9397db96d56Sopenharmony_ci leftblock->data[leftindex] = rightblock->data[rightindex]; 9407db96d56Sopenharmony_ci rightblock->data[rightindex] = tmp; 9417db96d56Sopenharmony_ci 9427db96d56Sopenharmony_ci /* Advance left block/index pair */ 9437db96d56Sopenharmony_ci leftindex++; 9447db96d56Sopenharmony_ci if (leftindex == BLOCKLEN) { 9457db96d56Sopenharmony_ci leftblock = leftblock->rightlink; 9467db96d56Sopenharmony_ci leftindex = 0; 9477db96d56Sopenharmony_ci } 9487db96d56Sopenharmony_ci 9497db96d56Sopenharmony_ci /* Step backwards with the right block/index pair */ 9507db96d56Sopenharmony_ci rightindex--; 9517db96d56Sopenharmony_ci if (rightindex < 0) { 9527db96d56Sopenharmony_ci rightblock = rightblock->leftlink; 9537db96d56Sopenharmony_ci rightindex = BLOCKLEN - 1; 9547db96d56Sopenharmony_ci } 9557db96d56Sopenharmony_ci } 9567db96d56Sopenharmony_ci Py_RETURN_NONE; 9577db96d56Sopenharmony_ci} 9587db96d56Sopenharmony_ci 9597db96d56Sopenharmony_ciPyDoc_STRVAR(reverse_doc, 9607db96d56Sopenharmony_ci"D.reverse() -- reverse *IN PLACE*"); 9617db96d56Sopenharmony_ci 9627db96d56Sopenharmony_cistatic PyObject * 9637db96d56Sopenharmony_cideque_count(dequeobject *deque, PyObject *v) 9647db96d56Sopenharmony_ci{ 9657db96d56Sopenharmony_ci block *b = deque->leftblock; 9667db96d56Sopenharmony_ci Py_ssize_t index = deque->leftindex; 9677db96d56Sopenharmony_ci Py_ssize_t n = Py_SIZE(deque); 9687db96d56Sopenharmony_ci Py_ssize_t count = 0; 9697db96d56Sopenharmony_ci size_t start_state = deque->state; 9707db96d56Sopenharmony_ci PyObject *item; 9717db96d56Sopenharmony_ci int cmp; 9727db96d56Sopenharmony_ci 9737db96d56Sopenharmony_ci while (--n >= 0) { 9747db96d56Sopenharmony_ci CHECK_NOT_END(b); 9757db96d56Sopenharmony_ci item = b->data[index]; 9767db96d56Sopenharmony_ci Py_INCREF(item); 9777db96d56Sopenharmony_ci cmp = PyObject_RichCompareBool(item, v, Py_EQ); 9787db96d56Sopenharmony_ci Py_DECREF(item); 9797db96d56Sopenharmony_ci if (cmp < 0) 9807db96d56Sopenharmony_ci return NULL; 9817db96d56Sopenharmony_ci count += cmp; 9827db96d56Sopenharmony_ci 9837db96d56Sopenharmony_ci if (start_state != deque->state) { 9847db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 9857db96d56Sopenharmony_ci "deque mutated during iteration"); 9867db96d56Sopenharmony_ci return NULL; 9877db96d56Sopenharmony_ci } 9887db96d56Sopenharmony_ci 9897db96d56Sopenharmony_ci /* Advance left block/index pair */ 9907db96d56Sopenharmony_ci index++; 9917db96d56Sopenharmony_ci if (index == BLOCKLEN) { 9927db96d56Sopenharmony_ci b = b->rightlink; 9937db96d56Sopenharmony_ci index = 0; 9947db96d56Sopenharmony_ci } 9957db96d56Sopenharmony_ci } 9967db96d56Sopenharmony_ci return PyLong_FromSsize_t(count); 9977db96d56Sopenharmony_ci} 9987db96d56Sopenharmony_ci 9997db96d56Sopenharmony_ciPyDoc_STRVAR(count_doc, 10007db96d56Sopenharmony_ci"D.count(value) -- return number of occurrences of value"); 10017db96d56Sopenharmony_ci 10027db96d56Sopenharmony_cistatic int 10037db96d56Sopenharmony_cideque_contains(dequeobject *deque, PyObject *v) 10047db96d56Sopenharmony_ci{ 10057db96d56Sopenharmony_ci block *b = deque->leftblock; 10067db96d56Sopenharmony_ci Py_ssize_t index = deque->leftindex; 10077db96d56Sopenharmony_ci Py_ssize_t n = Py_SIZE(deque); 10087db96d56Sopenharmony_ci size_t start_state = deque->state; 10097db96d56Sopenharmony_ci PyObject *item; 10107db96d56Sopenharmony_ci int cmp; 10117db96d56Sopenharmony_ci 10127db96d56Sopenharmony_ci while (--n >= 0) { 10137db96d56Sopenharmony_ci CHECK_NOT_END(b); 10147db96d56Sopenharmony_ci item = b->data[index]; 10157db96d56Sopenharmony_ci Py_INCREF(item); 10167db96d56Sopenharmony_ci cmp = PyObject_RichCompareBool(item, v, Py_EQ); 10177db96d56Sopenharmony_ci Py_DECREF(item); 10187db96d56Sopenharmony_ci if (cmp) { 10197db96d56Sopenharmony_ci return cmp; 10207db96d56Sopenharmony_ci } 10217db96d56Sopenharmony_ci if (start_state != deque->state) { 10227db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 10237db96d56Sopenharmony_ci "deque mutated during iteration"); 10247db96d56Sopenharmony_ci return -1; 10257db96d56Sopenharmony_ci } 10267db96d56Sopenharmony_ci index++; 10277db96d56Sopenharmony_ci if (index == BLOCKLEN) { 10287db96d56Sopenharmony_ci b = b->rightlink; 10297db96d56Sopenharmony_ci index = 0; 10307db96d56Sopenharmony_ci } 10317db96d56Sopenharmony_ci } 10327db96d56Sopenharmony_ci return 0; 10337db96d56Sopenharmony_ci} 10347db96d56Sopenharmony_ci 10357db96d56Sopenharmony_cistatic Py_ssize_t 10367db96d56Sopenharmony_cideque_len(dequeobject *deque) 10377db96d56Sopenharmony_ci{ 10387db96d56Sopenharmony_ci return Py_SIZE(deque); 10397db96d56Sopenharmony_ci} 10407db96d56Sopenharmony_ci 10417db96d56Sopenharmony_cistatic PyObject * 10427db96d56Sopenharmony_cideque_index(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) 10437db96d56Sopenharmony_ci{ 10447db96d56Sopenharmony_ci Py_ssize_t i, n, start=0, stop=Py_SIZE(deque); 10457db96d56Sopenharmony_ci PyObject *v, *item; 10467db96d56Sopenharmony_ci block *b = deque->leftblock; 10477db96d56Sopenharmony_ci Py_ssize_t index = deque->leftindex; 10487db96d56Sopenharmony_ci size_t start_state = deque->state; 10497db96d56Sopenharmony_ci int cmp; 10507db96d56Sopenharmony_ci 10517db96d56Sopenharmony_ci if (!_PyArg_ParseStack(args, nargs, "O|O&O&:index", &v, 10527db96d56Sopenharmony_ci _PyEval_SliceIndexNotNone, &start, 10537db96d56Sopenharmony_ci _PyEval_SliceIndexNotNone, &stop)) { 10547db96d56Sopenharmony_ci return NULL; 10557db96d56Sopenharmony_ci } 10567db96d56Sopenharmony_ci 10577db96d56Sopenharmony_ci if (start < 0) { 10587db96d56Sopenharmony_ci start += Py_SIZE(deque); 10597db96d56Sopenharmony_ci if (start < 0) 10607db96d56Sopenharmony_ci start = 0; 10617db96d56Sopenharmony_ci } 10627db96d56Sopenharmony_ci if (stop < 0) { 10637db96d56Sopenharmony_ci stop += Py_SIZE(deque); 10647db96d56Sopenharmony_ci if (stop < 0) 10657db96d56Sopenharmony_ci stop = 0; 10667db96d56Sopenharmony_ci } 10677db96d56Sopenharmony_ci if (stop > Py_SIZE(deque)) 10687db96d56Sopenharmony_ci stop = Py_SIZE(deque); 10697db96d56Sopenharmony_ci if (start > stop) 10707db96d56Sopenharmony_ci start = stop; 10717db96d56Sopenharmony_ci assert(0 <= start && start <= stop && stop <= Py_SIZE(deque)); 10727db96d56Sopenharmony_ci 10737db96d56Sopenharmony_ci for (i=0 ; i < start - BLOCKLEN ; i += BLOCKLEN) { 10747db96d56Sopenharmony_ci b = b->rightlink; 10757db96d56Sopenharmony_ci } 10767db96d56Sopenharmony_ci for ( ; i < start ; i++) { 10777db96d56Sopenharmony_ci index++; 10787db96d56Sopenharmony_ci if (index == BLOCKLEN) { 10797db96d56Sopenharmony_ci b = b->rightlink; 10807db96d56Sopenharmony_ci index = 0; 10817db96d56Sopenharmony_ci } 10827db96d56Sopenharmony_ci } 10837db96d56Sopenharmony_ci 10847db96d56Sopenharmony_ci n = stop - i; 10857db96d56Sopenharmony_ci while (--n >= 0) { 10867db96d56Sopenharmony_ci CHECK_NOT_END(b); 10877db96d56Sopenharmony_ci item = b->data[index]; 10887db96d56Sopenharmony_ci cmp = PyObject_RichCompareBool(item, v, Py_EQ); 10897db96d56Sopenharmony_ci if (cmp > 0) 10907db96d56Sopenharmony_ci return PyLong_FromSsize_t(stop - n - 1); 10917db96d56Sopenharmony_ci if (cmp < 0) 10927db96d56Sopenharmony_ci return NULL; 10937db96d56Sopenharmony_ci if (start_state != deque->state) { 10947db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 10957db96d56Sopenharmony_ci "deque mutated during iteration"); 10967db96d56Sopenharmony_ci return NULL; 10977db96d56Sopenharmony_ci } 10987db96d56Sopenharmony_ci index++; 10997db96d56Sopenharmony_ci if (index == BLOCKLEN) { 11007db96d56Sopenharmony_ci b = b->rightlink; 11017db96d56Sopenharmony_ci index = 0; 11027db96d56Sopenharmony_ci } 11037db96d56Sopenharmony_ci } 11047db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "%R is not in deque", v); 11057db96d56Sopenharmony_ci return NULL; 11067db96d56Sopenharmony_ci} 11077db96d56Sopenharmony_ci 11087db96d56Sopenharmony_ciPyDoc_STRVAR(index_doc, 11097db96d56Sopenharmony_ci"D.index(value, [start, [stop]]) -- return first index of value.\n" 11107db96d56Sopenharmony_ci"Raises ValueError if the value is not present."); 11117db96d56Sopenharmony_ci 11127db96d56Sopenharmony_ci/* insert(), remove(), and delitem() are implemented in terms of 11137db96d56Sopenharmony_ci rotate() for simplicity and reasonable performance near the end 11147db96d56Sopenharmony_ci points. If for some reason these methods become popular, it is not 11157db96d56Sopenharmony_ci hard to re-implement this using direct data movement (similar to 11167db96d56Sopenharmony_ci the code used in list slice assignments) and achieve a performance 11177db96d56Sopenharmony_ci boost (by moving each pointer only once instead of twice). 11187db96d56Sopenharmony_ci*/ 11197db96d56Sopenharmony_ci 11207db96d56Sopenharmony_cistatic PyObject * 11217db96d56Sopenharmony_cideque_insert(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) 11227db96d56Sopenharmony_ci{ 11237db96d56Sopenharmony_ci Py_ssize_t index; 11247db96d56Sopenharmony_ci Py_ssize_t n = Py_SIZE(deque); 11257db96d56Sopenharmony_ci PyObject *value; 11267db96d56Sopenharmony_ci PyObject *rv; 11277db96d56Sopenharmony_ci 11287db96d56Sopenharmony_ci if (!_PyArg_ParseStack(args, nargs, "nO:insert", &index, &value)) { 11297db96d56Sopenharmony_ci return NULL; 11307db96d56Sopenharmony_ci } 11317db96d56Sopenharmony_ci 11327db96d56Sopenharmony_ci if (deque->maxlen == Py_SIZE(deque)) { 11337db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "deque already at its maximum size"); 11347db96d56Sopenharmony_ci return NULL; 11357db96d56Sopenharmony_ci } 11367db96d56Sopenharmony_ci if (index >= n) 11377db96d56Sopenharmony_ci return deque_append(deque, value); 11387db96d56Sopenharmony_ci if (index <= -n || index == 0) 11397db96d56Sopenharmony_ci return deque_appendleft(deque, value); 11407db96d56Sopenharmony_ci if (_deque_rotate(deque, -index)) 11417db96d56Sopenharmony_ci return NULL; 11427db96d56Sopenharmony_ci if (index < 0) 11437db96d56Sopenharmony_ci rv = deque_append(deque, value); 11447db96d56Sopenharmony_ci else 11457db96d56Sopenharmony_ci rv = deque_appendleft(deque, value); 11467db96d56Sopenharmony_ci if (rv == NULL) 11477db96d56Sopenharmony_ci return NULL; 11487db96d56Sopenharmony_ci Py_DECREF(rv); 11497db96d56Sopenharmony_ci if (_deque_rotate(deque, index)) 11507db96d56Sopenharmony_ci return NULL; 11517db96d56Sopenharmony_ci Py_RETURN_NONE; 11527db96d56Sopenharmony_ci} 11537db96d56Sopenharmony_ci 11547db96d56Sopenharmony_ciPyDoc_STRVAR(insert_doc, 11557db96d56Sopenharmony_ci"D.insert(index, object) -- insert object before index"); 11567db96d56Sopenharmony_ci 11577db96d56Sopenharmony_ciPyDoc_STRVAR(remove_doc, 11587db96d56Sopenharmony_ci"D.remove(value) -- remove first occurrence of value."); 11597db96d56Sopenharmony_ci 11607db96d56Sopenharmony_cistatic int 11617db96d56Sopenharmony_civalid_index(Py_ssize_t i, Py_ssize_t limit) 11627db96d56Sopenharmony_ci{ 11637db96d56Sopenharmony_ci /* The cast to size_t lets us use just a single comparison 11647db96d56Sopenharmony_ci to check whether i is in the range: 0 <= i < limit */ 11657db96d56Sopenharmony_ci return (size_t) i < (size_t) limit; 11667db96d56Sopenharmony_ci} 11677db96d56Sopenharmony_ci 11687db96d56Sopenharmony_cistatic PyObject * 11697db96d56Sopenharmony_cideque_item(dequeobject *deque, Py_ssize_t i) 11707db96d56Sopenharmony_ci{ 11717db96d56Sopenharmony_ci block *b; 11727db96d56Sopenharmony_ci PyObject *item; 11737db96d56Sopenharmony_ci Py_ssize_t n, index=i; 11747db96d56Sopenharmony_ci 11757db96d56Sopenharmony_ci if (!valid_index(i, Py_SIZE(deque))) { 11767db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "deque index out of range"); 11777db96d56Sopenharmony_ci return NULL; 11787db96d56Sopenharmony_ci } 11797db96d56Sopenharmony_ci 11807db96d56Sopenharmony_ci if (i == 0) { 11817db96d56Sopenharmony_ci i = deque->leftindex; 11827db96d56Sopenharmony_ci b = deque->leftblock; 11837db96d56Sopenharmony_ci } else if (i == Py_SIZE(deque) - 1) { 11847db96d56Sopenharmony_ci i = deque->rightindex; 11857db96d56Sopenharmony_ci b = deque->rightblock; 11867db96d56Sopenharmony_ci } else { 11877db96d56Sopenharmony_ci i += deque->leftindex; 11887db96d56Sopenharmony_ci n = (Py_ssize_t)((size_t) i / BLOCKLEN); 11897db96d56Sopenharmony_ci i = (Py_ssize_t)((size_t) i % BLOCKLEN); 11907db96d56Sopenharmony_ci if (index < (Py_SIZE(deque) >> 1)) { 11917db96d56Sopenharmony_ci b = deque->leftblock; 11927db96d56Sopenharmony_ci while (--n >= 0) 11937db96d56Sopenharmony_ci b = b->rightlink; 11947db96d56Sopenharmony_ci } else { 11957db96d56Sopenharmony_ci n = (Py_ssize_t)( 11967db96d56Sopenharmony_ci ((size_t)(deque->leftindex + Py_SIZE(deque) - 1)) 11977db96d56Sopenharmony_ci / BLOCKLEN - n); 11987db96d56Sopenharmony_ci b = deque->rightblock; 11997db96d56Sopenharmony_ci while (--n >= 0) 12007db96d56Sopenharmony_ci b = b->leftlink; 12017db96d56Sopenharmony_ci } 12027db96d56Sopenharmony_ci } 12037db96d56Sopenharmony_ci item = b->data[i]; 12047db96d56Sopenharmony_ci Py_INCREF(item); 12057db96d56Sopenharmony_ci return item; 12067db96d56Sopenharmony_ci} 12077db96d56Sopenharmony_ci 12087db96d56Sopenharmony_cistatic int 12097db96d56Sopenharmony_cideque_del_item(dequeobject *deque, Py_ssize_t i) 12107db96d56Sopenharmony_ci{ 12117db96d56Sopenharmony_ci PyObject *item; 12127db96d56Sopenharmony_ci int rv; 12137db96d56Sopenharmony_ci 12147db96d56Sopenharmony_ci assert (i >= 0 && i < Py_SIZE(deque)); 12157db96d56Sopenharmony_ci if (_deque_rotate(deque, -i)) 12167db96d56Sopenharmony_ci return -1; 12177db96d56Sopenharmony_ci item = deque_popleft(deque, NULL); 12187db96d56Sopenharmony_ci rv = _deque_rotate(deque, i); 12197db96d56Sopenharmony_ci assert (item != NULL); 12207db96d56Sopenharmony_ci Py_DECREF(item); 12217db96d56Sopenharmony_ci return rv; 12227db96d56Sopenharmony_ci} 12237db96d56Sopenharmony_ci 12247db96d56Sopenharmony_cistatic PyObject * 12257db96d56Sopenharmony_cideque_remove(dequeobject *deque, PyObject *value) 12267db96d56Sopenharmony_ci{ 12277db96d56Sopenharmony_ci PyObject *item; 12287db96d56Sopenharmony_ci block *b = deque->leftblock; 12297db96d56Sopenharmony_ci Py_ssize_t i, n = Py_SIZE(deque), index = deque->leftindex; 12307db96d56Sopenharmony_ci size_t start_state = deque->state; 12317db96d56Sopenharmony_ci int cmp, rv; 12327db96d56Sopenharmony_ci 12337db96d56Sopenharmony_ci for (i = 0 ; i < n; i++) { 12347db96d56Sopenharmony_ci item = b->data[index]; 12357db96d56Sopenharmony_ci Py_INCREF(item); 12367db96d56Sopenharmony_ci cmp = PyObject_RichCompareBool(item, value, Py_EQ); 12377db96d56Sopenharmony_ci Py_DECREF(item); 12387db96d56Sopenharmony_ci if (cmp < 0) { 12397db96d56Sopenharmony_ci return NULL; 12407db96d56Sopenharmony_ci } 12417db96d56Sopenharmony_ci if (start_state != deque->state) { 12427db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, 12437db96d56Sopenharmony_ci "deque mutated during iteration"); 12447db96d56Sopenharmony_ci return NULL; 12457db96d56Sopenharmony_ci } 12467db96d56Sopenharmony_ci if (cmp > 0) { 12477db96d56Sopenharmony_ci break; 12487db96d56Sopenharmony_ci } 12497db96d56Sopenharmony_ci index++; 12507db96d56Sopenharmony_ci if (index == BLOCKLEN) { 12517db96d56Sopenharmony_ci b = b->rightlink; 12527db96d56Sopenharmony_ci index = 0; 12537db96d56Sopenharmony_ci } 12547db96d56Sopenharmony_ci } 12557db96d56Sopenharmony_ci if (i == n) { 12567db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "%R is not in deque", value); 12577db96d56Sopenharmony_ci return NULL; 12587db96d56Sopenharmony_ci } 12597db96d56Sopenharmony_ci rv = deque_del_item(deque, i); 12607db96d56Sopenharmony_ci if (rv == -1) { 12617db96d56Sopenharmony_ci return NULL; 12627db96d56Sopenharmony_ci } 12637db96d56Sopenharmony_ci Py_RETURN_NONE; 12647db96d56Sopenharmony_ci} 12657db96d56Sopenharmony_ci 12667db96d56Sopenharmony_cistatic int 12677db96d56Sopenharmony_cideque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v) 12687db96d56Sopenharmony_ci{ 12697db96d56Sopenharmony_ci PyObject *old_value; 12707db96d56Sopenharmony_ci block *b; 12717db96d56Sopenharmony_ci Py_ssize_t n, len=Py_SIZE(deque), halflen=(len+1)>>1, index=i; 12727db96d56Sopenharmony_ci 12737db96d56Sopenharmony_ci if (!valid_index(i, len)) { 12747db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "deque index out of range"); 12757db96d56Sopenharmony_ci return -1; 12767db96d56Sopenharmony_ci } 12777db96d56Sopenharmony_ci if (v == NULL) 12787db96d56Sopenharmony_ci return deque_del_item(deque, i); 12797db96d56Sopenharmony_ci 12807db96d56Sopenharmony_ci i += deque->leftindex; 12817db96d56Sopenharmony_ci n = (Py_ssize_t)((size_t) i / BLOCKLEN); 12827db96d56Sopenharmony_ci i = (Py_ssize_t)((size_t) i % BLOCKLEN); 12837db96d56Sopenharmony_ci if (index <= halflen) { 12847db96d56Sopenharmony_ci b = deque->leftblock; 12857db96d56Sopenharmony_ci while (--n >= 0) 12867db96d56Sopenharmony_ci b = b->rightlink; 12877db96d56Sopenharmony_ci } else { 12887db96d56Sopenharmony_ci n = (Py_ssize_t)( 12897db96d56Sopenharmony_ci ((size_t)(deque->leftindex + Py_SIZE(deque) - 1)) 12907db96d56Sopenharmony_ci / BLOCKLEN - n); 12917db96d56Sopenharmony_ci b = deque->rightblock; 12927db96d56Sopenharmony_ci while (--n >= 0) 12937db96d56Sopenharmony_ci b = b->leftlink; 12947db96d56Sopenharmony_ci } 12957db96d56Sopenharmony_ci Py_INCREF(v); 12967db96d56Sopenharmony_ci old_value = b->data[i]; 12977db96d56Sopenharmony_ci b->data[i] = v; 12987db96d56Sopenharmony_ci Py_DECREF(old_value); 12997db96d56Sopenharmony_ci return 0; 13007db96d56Sopenharmony_ci} 13017db96d56Sopenharmony_ci 13027db96d56Sopenharmony_cistatic void 13037db96d56Sopenharmony_cideque_dealloc(dequeobject *deque) 13047db96d56Sopenharmony_ci{ 13057db96d56Sopenharmony_ci Py_ssize_t i; 13067db96d56Sopenharmony_ci 13077db96d56Sopenharmony_ci PyObject_GC_UnTrack(deque); 13087db96d56Sopenharmony_ci if (deque->weakreflist != NULL) 13097db96d56Sopenharmony_ci PyObject_ClearWeakRefs((PyObject *) deque); 13107db96d56Sopenharmony_ci if (deque->leftblock != NULL) { 13117db96d56Sopenharmony_ci deque_clear(deque); 13127db96d56Sopenharmony_ci assert(deque->leftblock != NULL); 13137db96d56Sopenharmony_ci freeblock(deque, deque->leftblock); 13147db96d56Sopenharmony_ci } 13157db96d56Sopenharmony_ci deque->leftblock = NULL; 13167db96d56Sopenharmony_ci deque->rightblock = NULL; 13177db96d56Sopenharmony_ci for (i=0 ; i < deque->numfreeblocks ; i++) { 13187db96d56Sopenharmony_ci PyMem_Free(deque->freeblocks[i]); 13197db96d56Sopenharmony_ci } 13207db96d56Sopenharmony_ci Py_TYPE(deque)->tp_free(deque); 13217db96d56Sopenharmony_ci} 13227db96d56Sopenharmony_ci 13237db96d56Sopenharmony_cistatic int 13247db96d56Sopenharmony_cideque_traverse(dequeobject *deque, visitproc visit, void *arg) 13257db96d56Sopenharmony_ci{ 13267db96d56Sopenharmony_ci block *b; 13277db96d56Sopenharmony_ci PyObject *item; 13287db96d56Sopenharmony_ci Py_ssize_t index; 13297db96d56Sopenharmony_ci Py_ssize_t indexlo = deque->leftindex; 13307db96d56Sopenharmony_ci Py_ssize_t indexhigh; 13317db96d56Sopenharmony_ci 13327db96d56Sopenharmony_ci for (b = deque->leftblock; b != deque->rightblock; b = b->rightlink) { 13337db96d56Sopenharmony_ci for (index = indexlo; index < BLOCKLEN ; index++) { 13347db96d56Sopenharmony_ci item = b->data[index]; 13357db96d56Sopenharmony_ci Py_VISIT(item); 13367db96d56Sopenharmony_ci } 13377db96d56Sopenharmony_ci indexlo = 0; 13387db96d56Sopenharmony_ci } 13397db96d56Sopenharmony_ci indexhigh = deque->rightindex; 13407db96d56Sopenharmony_ci for (index = indexlo; index <= indexhigh; index++) { 13417db96d56Sopenharmony_ci item = b->data[index]; 13427db96d56Sopenharmony_ci Py_VISIT(item); 13437db96d56Sopenharmony_ci } 13447db96d56Sopenharmony_ci return 0; 13457db96d56Sopenharmony_ci} 13467db96d56Sopenharmony_ci 13477db96d56Sopenharmony_cistatic PyObject * 13487db96d56Sopenharmony_cideque_reduce(dequeobject *deque, PyObject *Py_UNUSED(ignored)) 13497db96d56Sopenharmony_ci{ 13507db96d56Sopenharmony_ci PyObject *state, *it; 13517db96d56Sopenharmony_ci 13527db96d56Sopenharmony_ci state = _PyObject_GetState((PyObject *)deque); 13537db96d56Sopenharmony_ci if (state == NULL) { 13547db96d56Sopenharmony_ci return NULL; 13557db96d56Sopenharmony_ci } 13567db96d56Sopenharmony_ci 13577db96d56Sopenharmony_ci it = PyObject_GetIter((PyObject *)deque); 13587db96d56Sopenharmony_ci if (it == NULL) { 13597db96d56Sopenharmony_ci Py_DECREF(state); 13607db96d56Sopenharmony_ci return NULL; 13617db96d56Sopenharmony_ci } 13627db96d56Sopenharmony_ci 13637db96d56Sopenharmony_ci if (deque->maxlen < 0) { 13647db96d56Sopenharmony_ci return Py_BuildValue("O()NN", Py_TYPE(deque), state, it); 13657db96d56Sopenharmony_ci } 13667db96d56Sopenharmony_ci else { 13677db96d56Sopenharmony_ci return Py_BuildValue("O(()n)NN", Py_TYPE(deque), deque->maxlen, state, it); 13687db96d56Sopenharmony_ci } 13697db96d56Sopenharmony_ci} 13707db96d56Sopenharmony_ci 13717db96d56Sopenharmony_ciPyDoc_STRVAR(reduce_doc, "Return state information for pickling."); 13727db96d56Sopenharmony_ci 13737db96d56Sopenharmony_cistatic PyObject * 13747db96d56Sopenharmony_cideque_repr(PyObject *deque) 13757db96d56Sopenharmony_ci{ 13767db96d56Sopenharmony_ci PyObject *aslist, *result; 13777db96d56Sopenharmony_ci int i; 13787db96d56Sopenharmony_ci 13797db96d56Sopenharmony_ci i = Py_ReprEnter(deque); 13807db96d56Sopenharmony_ci if (i != 0) { 13817db96d56Sopenharmony_ci if (i < 0) 13827db96d56Sopenharmony_ci return NULL; 13837db96d56Sopenharmony_ci return PyUnicode_FromString("[...]"); 13847db96d56Sopenharmony_ci } 13857db96d56Sopenharmony_ci 13867db96d56Sopenharmony_ci aslist = PySequence_List(deque); 13877db96d56Sopenharmony_ci if (aslist == NULL) { 13887db96d56Sopenharmony_ci Py_ReprLeave(deque); 13897db96d56Sopenharmony_ci return NULL; 13907db96d56Sopenharmony_ci } 13917db96d56Sopenharmony_ci if (((dequeobject *)deque)->maxlen >= 0) 13927db96d56Sopenharmony_ci result = PyUnicode_FromFormat("%s(%R, maxlen=%zd)", 13937db96d56Sopenharmony_ci _PyType_Name(Py_TYPE(deque)), aslist, 13947db96d56Sopenharmony_ci ((dequeobject *)deque)->maxlen); 13957db96d56Sopenharmony_ci else 13967db96d56Sopenharmony_ci result = PyUnicode_FromFormat("%s(%R)", 13977db96d56Sopenharmony_ci _PyType_Name(Py_TYPE(deque)), aslist); 13987db96d56Sopenharmony_ci Py_ReprLeave(deque); 13997db96d56Sopenharmony_ci Py_DECREF(aslist); 14007db96d56Sopenharmony_ci return result; 14017db96d56Sopenharmony_ci} 14027db96d56Sopenharmony_ci 14037db96d56Sopenharmony_cistatic PyObject * 14047db96d56Sopenharmony_cideque_richcompare(PyObject *v, PyObject *w, int op) 14057db96d56Sopenharmony_ci{ 14067db96d56Sopenharmony_ci PyObject *it1=NULL, *it2=NULL, *x, *y; 14077db96d56Sopenharmony_ci Py_ssize_t vs, ws; 14087db96d56Sopenharmony_ci int b, cmp=-1; 14097db96d56Sopenharmony_ci 14107db96d56Sopenharmony_ci if (!PyObject_TypeCheck(v, &deque_type) || 14117db96d56Sopenharmony_ci !PyObject_TypeCheck(w, &deque_type)) { 14127db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 14137db96d56Sopenharmony_ci } 14147db96d56Sopenharmony_ci 14157db96d56Sopenharmony_ci /* Shortcuts */ 14167db96d56Sopenharmony_ci vs = Py_SIZE((dequeobject *)v); 14177db96d56Sopenharmony_ci ws = Py_SIZE((dequeobject *)w); 14187db96d56Sopenharmony_ci if (op == Py_EQ) { 14197db96d56Sopenharmony_ci if (v == w) 14207db96d56Sopenharmony_ci Py_RETURN_TRUE; 14217db96d56Sopenharmony_ci if (vs != ws) 14227db96d56Sopenharmony_ci Py_RETURN_FALSE; 14237db96d56Sopenharmony_ci } 14247db96d56Sopenharmony_ci if (op == Py_NE) { 14257db96d56Sopenharmony_ci if (v == w) 14267db96d56Sopenharmony_ci Py_RETURN_FALSE; 14277db96d56Sopenharmony_ci if (vs != ws) 14287db96d56Sopenharmony_ci Py_RETURN_TRUE; 14297db96d56Sopenharmony_ci } 14307db96d56Sopenharmony_ci 14317db96d56Sopenharmony_ci /* Search for the first index where items are different */ 14327db96d56Sopenharmony_ci it1 = PyObject_GetIter(v); 14337db96d56Sopenharmony_ci if (it1 == NULL) 14347db96d56Sopenharmony_ci goto done; 14357db96d56Sopenharmony_ci it2 = PyObject_GetIter(w); 14367db96d56Sopenharmony_ci if (it2 == NULL) 14377db96d56Sopenharmony_ci goto done; 14387db96d56Sopenharmony_ci for (;;) { 14397db96d56Sopenharmony_ci x = PyIter_Next(it1); 14407db96d56Sopenharmony_ci if (x == NULL && PyErr_Occurred()) 14417db96d56Sopenharmony_ci goto done; 14427db96d56Sopenharmony_ci y = PyIter_Next(it2); 14437db96d56Sopenharmony_ci if (x == NULL || y == NULL) 14447db96d56Sopenharmony_ci break; 14457db96d56Sopenharmony_ci b = PyObject_RichCompareBool(x, y, Py_EQ); 14467db96d56Sopenharmony_ci if (b == 0) { 14477db96d56Sopenharmony_ci cmp = PyObject_RichCompareBool(x, y, op); 14487db96d56Sopenharmony_ci Py_DECREF(x); 14497db96d56Sopenharmony_ci Py_DECREF(y); 14507db96d56Sopenharmony_ci goto done; 14517db96d56Sopenharmony_ci } 14527db96d56Sopenharmony_ci Py_DECREF(x); 14537db96d56Sopenharmony_ci Py_DECREF(y); 14547db96d56Sopenharmony_ci if (b < 0) 14557db96d56Sopenharmony_ci goto done; 14567db96d56Sopenharmony_ci } 14577db96d56Sopenharmony_ci /* We reached the end of one deque or both */ 14587db96d56Sopenharmony_ci Py_XDECREF(x); 14597db96d56Sopenharmony_ci Py_XDECREF(y); 14607db96d56Sopenharmony_ci if (PyErr_Occurred()) 14617db96d56Sopenharmony_ci goto done; 14627db96d56Sopenharmony_ci switch (op) { 14637db96d56Sopenharmony_ci case Py_LT: cmp = y != NULL; break; /* if w was longer */ 14647db96d56Sopenharmony_ci case Py_LE: cmp = x == NULL; break; /* if v was not longer */ 14657db96d56Sopenharmony_ci case Py_EQ: cmp = x == y; break; /* if we reached the end of both */ 14667db96d56Sopenharmony_ci case Py_NE: cmp = x != y; break; /* if one deque continues */ 14677db96d56Sopenharmony_ci case Py_GT: cmp = x != NULL; break; /* if v was longer */ 14687db96d56Sopenharmony_ci case Py_GE: cmp = y == NULL; break; /* if w was not longer */ 14697db96d56Sopenharmony_ci } 14707db96d56Sopenharmony_ci 14717db96d56Sopenharmony_cidone: 14727db96d56Sopenharmony_ci Py_XDECREF(it1); 14737db96d56Sopenharmony_ci Py_XDECREF(it2); 14747db96d56Sopenharmony_ci if (cmp == 1) 14757db96d56Sopenharmony_ci Py_RETURN_TRUE; 14767db96d56Sopenharmony_ci if (cmp == 0) 14777db96d56Sopenharmony_ci Py_RETURN_FALSE; 14787db96d56Sopenharmony_ci return NULL; 14797db96d56Sopenharmony_ci} 14807db96d56Sopenharmony_ci 14817db96d56Sopenharmony_cistatic int 14827db96d56Sopenharmony_cideque_init(dequeobject *deque, PyObject *args, PyObject *kwdargs) 14837db96d56Sopenharmony_ci{ 14847db96d56Sopenharmony_ci PyObject *iterable = NULL; 14857db96d56Sopenharmony_ci PyObject *maxlenobj = NULL; 14867db96d56Sopenharmony_ci Py_ssize_t maxlen = -1; 14877db96d56Sopenharmony_ci char *kwlist[] = {"iterable", "maxlen", 0}; 14887db96d56Sopenharmony_ci 14897db96d56Sopenharmony_ci if (kwdargs == NULL && PyTuple_GET_SIZE(args) <= 2) { 14907db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(args) > 0) { 14917db96d56Sopenharmony_ci iterable = PyTuple_GET_ITEM(args, 0); 14927db96d56Sopenharmony_ci } 14937db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(args) > 1) { 14947db96d56Sopenharmony_ci maxlenobj = PyTuple_GET_ITEM(args, 1); 14957db96d56Sopenharmony_ci } 14967db96d56Sopenharmony_ci } else { 14977db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwdargs, "|OO:deque", kwlist, 14987db96d56Sopenharmony_ci &iterable, &maxlenobj)) 14997db96d56Sopenharmony_ci return -1; 15007db96d56Sopenharmony_ci } 15017db96d56Sopenharmony_ci if (maxlenobj != NULL && maxlenobj != Py_None) { 15027db96d56Sopenharmony_ci maxlen = PyLong_AsSsize_t(maxlenobj); 15037db96d56Sopenharmony_ci if (maxlen == -1 && PyErr_Occurred()) 15047db96d56Sopenharmony_ci return -1; 15057db96d56Sopenharmony_ci if (maxlen < 0) { 15067db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "maxlen must be non-negative"); 15077db96d56Sopenharmony_ci return -1; 15087db96d56Sopenharmony_ci } 15097db96d56Sopenharmony_ci } 15107db96d56Sopenharmony_ci deque->maxlen = maxlen; 15117db96d56Sopenharmony_ci if (Py_SIZE(deque) > 0) 15127db96d56Sopenharmony_ci deque_clear(deque); 15137db96d56Sopenharmony_ci if (iterable != NULL) { 15147db96d56Sopenharmony_ci PyObject *rv = deque_extend(deque, iterable); 15157db96d56Sopenharmony_ci if (rv == NULL) 15167db96d56Sopenharmony_ci return -1; 15177db96d56Sopenharmony_ci Py_DECREF(rv); 15187db96d56Sopenharmony_ci } 15197db96d56Sopenharmony_ci return 0; 15207db96d56Sopenharmony_ci} 15217db96d56Sopenharmony_ci 15227db96d56Sopenharmony_cistatic PyObject * 15237db96d56Sopenharmony_cideque_sizeof(dequeobject *deque, void *unused) 15247db96d56Sopenharmony_ci{ 15257db96d56Sopenharmony_ci Py_ssize_t res; 15267db96d56Sopenharmony_ci Py_ssize_t blocks; 15277db96d56Sopenharmony_ci 15287db96d56Sopenharmony_ci res = _PyObject_SIZE(Py_TYPE(deque)); 15297db96d56Sopenharmony_ci blocks = (size_t)(deque->leftindex + Py_SIZE(deque) + BLOCKLEN - 1) / BLOCKLEN; 15307db96d56Sopenharmony_ci assert(deque->leftindex + Py_SIZE(deque) - 1 == 15317db96d56Sopenharmony_ci (blocks - 1) * BLOCKLEN + deque->rightindex); 15327db96d56Sopenharmony_ci res += blocks * sizeof(block); 15337db96d56Sopenharmony_ci return PyLong_FromSsize_t(res); 15347db96d56Sopenharmony_ci} 15357db96d56Sopenharmony_ci 15367db96d56Sopenharmony_ciPyDoc_STRVAR(sizeof_doc, 15377db96d56Sopenharmony_ci"D.__sizeof__() -- size of D in memory, in bytes"); 15387db96d56Sopenharmony_ci 15397db96d56Sopenharmony_cistatic PyObject * 15407db96d56Sopenharmony_cideque_get_maxlen(dequeobject *deque, void *Py_UNUSED(ignored)) 15417db96d56Sopenharmony_ci{ 15427db96d56Sopenharmony_ci if (deque->maxlen < 0) 15437db96d56Sopenharmony_ci Py_RETURN_NONE; 15447db96d56Sopenharmony_ci return PyLong_FromSsize_t(deque->maxlen); 15457db96d56Sopenharmony_ci} 15467db96d56Sopenharmony_ci 15477db96d56Sopenharmony_ci 15487db96d56Sopenharmony_ci/* deque object ********************************************************/ 15497db96d56Sopenharmony_ci 15507db96d56Sopenharmony_cistatic PyGetSetDef deque_getset[] = { 15517db96d56Sopenharmony_ci {"maxlen", (getter)deque_get_maxlen, (setter)NULL, 15527db96d56Sopenharmony_ci "maximum size of a deque or None if unbounded"}, 15537db96d56Sopenharmony_ci {0} 15547db96d56Sopenharmony_ci}; 15557db96d56Sopenharmony_ci 15567db96d56Sopenharmony_cistatic PySequenceMethods deque_as_sequence = { 15577db96d56Sopenharmony_ci (lenfunc)deque_len, /* sq_length */ 15587db96d56Sopenharmony_ci (binaryfunc)deque_concat, /* sq_concat */ 15597db96d56Sopenharmony_ci (ssizeargfunc)deque_repeat, /* sq_repeat */ 15607db96d56Sopenharmony_ci (ssizeargfunc)deque_item, /* sq_item */ 15617db96d56Sopenharmony_ci 0, /* sq_slice */ 15627db96d56Sopenharmony_ci (ssizeobjargproc)deque_ass_item, /* sq_ass_item */ 15637db96d56Sopenharmony_ci 0, /* sq_ass_slice */ 15647db96d56Sopenharmony_ci (objobjproc)deque_contains, /* sq_contains */ 15657db96d56Sopenharmony_ci (binaryfunc)deque_inplace_concat, /* sq_inplace_concat */ 15667db96d56Sopenharmony_ci (ssizeargfunc)deque_inplace_repeat, /* sq_inplace_repeat */ 15677db96d56Sopenharmony_ci}; 15687db96d56Sopenharmony_ci 15697db96d56Sopenharmony_cistatic PyObject *deque_iter(dequeobject *deque); 15707db96d56Sopenharmony_cistatic PyObject *deque_reviter(dequeobject *deque, PyObject *Py_UNUSED(ignored)); 15717db96d56Sopenharmony_ciPyDoc_STRVAR(reversed_doc, 15727db96d56Sopenharmony_ci "D.__reversed__() -- return a reverse iterator over the deque"); 15737db96d56Sopenharmony_ci 15747db96d56Sopenharmony_cistatic PyMethodDef deque_methods[] = { 15757db96d56Sopenharmony_ci {"append", (PyCFunction)deque_append, 15767db96d56Sopenharmony_ci METH_O, append_doc}, 15777db96d56Sopenharmony_ci {"appendleft", (PyCFunction)deque_appendleft, 15787db96d56Sopenharmony_ci METH_O, appendleft_doc}, 15797db96d56Sopenharmony_ci {"clear", (PyCFunction)deque_clearmethod, 15807db96d56Sopenharmony_ci METH_NOARGS, clear_doc}, 15817db96d56Sopenharmony_ci {"__copy__", deque_copy, 15827db96d56Sopenharmony_ci METH_NOARGS, copy_doc}, 15837db96d56Sopenharmony_ci {"copy", deque_copy, 15847db96d56Sopenharmony_ci METH_NOARGS, copy_doc}, 15857db96d56Sopenharmony_ci {"count", (PyCFunction)deque_count, 15867db96d56Sopenharmony_ci METH_O, count_doc}, 15877db96d56Sopenharmony_ci {"extend", (PyCFunction)deque_extend, 15887db96d56Sopenharmony_ci METH_O, extend_doc}, 15897db96d56Sopenharmony_ci {"extendleft", (PyCFunction)deque_extendleft, 15907db96d56Sopenharmony_ci METH_O, extendleft_doc}, 15917db96d56Sopenharmony_ci {"index", _PyCFunction_CAST(deque_index), 15927db96d56Sopenharmony_ci METH_FASTCALL, index_doc}, 15937db96d56Sopenharmony_ci {"insert", _PyCFunction_CAST(deque_insert), 15947db96d56Sopenharmony_ci METH_FASTCALL, insert_doc}, 15957db96d56Sopenharmony_ci {"pop", (PyCFunction)deque_pop, 15967db96d56Sopenharmony_ci METH_NOARGS, pop_doc}, 15977db96d56Sopenharmony_ci {"popleft", (PyCFunction)deque_popleft, 15987db96d56Sopenharmony_ci METH_NOARGS, popleft_doc}, 15997db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)deque_reduce, 16007db96d56Sopenharmony_ci METH_NOARGS, reduce_doc}, 16017db96d56Sopenharmony_ci {"remove", (PyCFunction)deque_remove, 16027db96d56Sopenharmony_ci METH_O, remove_doc}, 16037db96d56Sopenharmony_ci {"__reversed__", (PyCFunction)deque_reviter, 16047db96d56Sopenharmony_ci METH_NOARGS, reversed_doc}, 16057db96d56Sopenharmony_ci {"reverse", (PyCFunction)deque_reverse, 16067db96d56Sopenharmony_ci METH_NOARGS, reverse_doc}, 16077db96d56Sopenharmony_ci {"rotate", _PyCFunction_CAST(deque_rotate), 16087db96d56Sopenharmony_ci METH_FASTCALL, rotate_doc}, 16097db96d56Sopenharmony_ci {"__sizeof__", (PyCFunction)deque_sizeof, 16107db96d56Sopenharmony_ci METH_NOARGS, sizeof_doc}, 16117db96d56Sopenharmony_ci {"__class_getitem__", Py_GenericAlias, 16127db96d56Sopenharmony_ci METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, 16137db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 16147db96d56Sopenharmony_ci}; 16157db96d56Sopenharmony_ci 16167db96d56Sopenharmony_ciPyDoc_STRVAR(deque_doc, 16177db96d56Sopenharmony_ci"deque([iterable[, maxlen]]) --> deque object\n\ 16187db96d56Sopenharmony_ci\n\ 16197db96d56Sopenharmony_ciA list-like sequence optimized for data accesses near its endpoints."); 16207db96d56Sopenharmony_ci 16217db96d56Sopenharmony_cistatic PyTypeObject deque_type = { 16227db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 16237db96d56Sopenharmony_ci "collections.deque", /* tp_name */ 16247db96d56Sopenharmony_ci sizeof(dequeobject), /* tp_basicsize */ 16257db96d56Sopenharmony_ci 0, /* tp_itemsize */ 16267db96d56Sopenharmony_ci /* methods */ 16277db96d56Sopenharmony_ci (destructor)deque_dealloc, /* tp_dealloc */ 16287db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 16297db96d56Sopenharmony_ci 0, /* tp_getattr */ 16307db96d56Sopenharmony_ci 0, /* tp_setattr */ 16317db96d56Sopenharmony_ci 0, /* tp_as_async */ 16327db96d56Sopenharmony_ci deque_repr, /* tp_repr */ 16337db96d56Sopenharmony_ci 0, /* tp_as_number */ 16347db96d56Sopenharmony_ci &deque_as_sequence, /* tp_as_sequence */ 16357db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 16367db96d56Sopenharmony_ci PyObject_HashNotImplemented, /* tp_hash */ 16377db96d56Sopenharmony_ci 0, /* tp_call */ 16387db96d56Sopenharmony_ci 0, /* tp_str */ 16397db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 16407db96d56Sopenharmony_ci 0, /* tp_setattro */ 16417db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 16427db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 16437db96d56Sopenharmony_ci Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SEQUENCE, 16447db96d56Sopenharmony_ci /* tp_flags */ 16457db96d56Sopenharmony_ci deque_doc, /* tp_doc */ 16467db96d56Sopenharmony_ci (traverseproc)deque_traverse, /* tp_traverse */ 16477db96d56Sopenharmony_ci (inquiry)deque_clear, /* tp_clear */ 16487db96d56Sopenharmony_ci (richcmpfunc)deque_richcompare, /* tp_richcompare */ 16497db96d56Sopenharmony_ci offsetof(dequeobject, weakreflist), /* tp_weaklistoffset*/ 16507db96d56Sopenharmony_ci (getiterfunc)deque_iter, /* tp_iter */ 16517db96d56Sopenharmony_ci 0, /* tp_iternext */ 16527db96d56Sopenharmony_ci deque_methods, /* tp_methods */ 16537db96d56Sopenharmony_ci 0, /* tp_members */ 16547db96d56Sopenharmony_ci deque_getset, /* tp_getset */ 16557db96d56Sopenharmony_ci 0, /* tp_base */ 16567db96d56Sopenharmony_ci 0, /* tp_dict */ 16577db96d56Sopenharmony_ci 0, /* tp_descr_get */ 16587db96d56Sopenharmony_ci 0, /* tp_descr_set */ 16597db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 16607db96d56Sopenharmony_ci (initproc)deque_init, /* tp_init */ 16617db96d56Sopenharmony_ci PyType_GenericAlloc, /* tp_alloc */ 16627db96d56Sopenharmony_ci deque_new, /* tp_new */ 16637db96d56Sopenharmony_ci PyObject_GC_Del, /* tp_free */ 16647db96d56Sopenharmony_ci}; 16657db96d56Sopenharmony_ci 16667db96d56Sopenharmony_ci/*********************** Deque Iterator **************************/ 16677db96d56Sopenharmony_ci 16687db96d56Sopenharmony_citypedef struct { 16697db96d56Sopenharmony_ci PyObject_HEAD 16707db96d56Sopenharmony_ci block *b; 16717db96d56Sopenharmony_ci Py_ssize_t index; 16727db96d56Sopenharmony_ci dequeobject *deque; 16737db96d56Sopenharmony_ci size_t state; /* state when the iterator is created */ 16747db96d56Sopenharmony_ci Py_ssize_t counter; /* number of items remaining for iteration */ 16757db96d56Sopenharmony_ci} dequeiterobject; 16767db96d56Sopenharmony_ci 16777db96d56Sopenharmony_cistatic PyTypeObject dequeiter_type; 16787db96d56Sopenharmony_ci 16797db96d56Sopenharmony_cistatic PyObject * 16807db96d56Sopenharmony_cideque_iter(dequeobject *deque) 16817db96d56Sopenharmony_ci{ 16827db96d56Sopenharmony_ci dequeiterobject *it; 16837db96d56Sopenharmony_ci 16847db96d56Sopenharmony_ci it = PyObject_GC_New(dequeiterobject, &dequeiter_type); 16857db96d56Sopenharmony_ci if (it == NULL) 16867db96d56Sopenharmony_ci return NULL; 16877db96d56Sopenharmony_ci it->b = deque->leftblock; 16887db96d56Sopenharmony_ci it->index = deque->leftindex; 16897db96d56Sopenharmony_ci Py_INCREF(deque); 16907db96d56Sopenharmony_ci it->deque = deque; 16917db96d56Sopenharmony_ci it->state = deque->state; 16927db96d56Sopenharmony_ci it->counter = Py_SIZE(deque); 16937db96d56Sopenharmony_ci PyObject_GC_Track(it); 16947db96d56Sopenharmony_ci return (PyObject *)it; 16957db96d56Sopenharmony_ci} 16967db96d56Sopenharmony_ci 16977db96d56Sopenharmony_cistatic int 16987db96d56Sopenharmony_cidequeiter_traverse(dequeiterobject *dio, visitproc visit, void *arg) 16997db96d56Sopenharmony_ci{ 17007db96d56Sopenharmony_ci Py_VISIT(dio->deque); 17017db96d56Sopenharmony_ci return 0; 17027db96d56Sopenharmony_ci} 17037db96d56Sopenharmony_ci 17047db96d56Sopenharmony_cistatic void 17057db96d56Sopenharmony_cidequeiter_dealloc(dequeiterobject *dio) 17067db96d56Sopenharmony_ci{ 17077db96d56Sopenharmony_ci /* bpo-31095: UnTrack is needed before calling any callbacks */ 17087db96d56Sopenharmony_ci PyObject_GC_UnTrack(dio); 17097db96d56Sopenharmony_ci Py_XDECREF(dio->deque); 17107db96d56Sopenharmony_ci PyObject_GC_Del(dio); 17117db96d56Sopenharmony_ci} 17127db96d56Sopenharmony_ci 17137db96d56Sopenharmony_cistatic PyObject * 17147db96d56Sopenharmony_cidequeiter_next(dequeiterobject *it) 17157db96d56Sopenharmony_ci{ 17167db96d56Sopenharmony_ci PyObject *item; 17177db96d56Sopenharmony_ci 17187db96d56Sopenharmony_ci if (it->deque->state != it->state) { 17197db96d56Sopenharmony_ci it->counter = 0; 17207db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 17217db96d56Sopenharmony_ci "deque mutated during iteration"); 17227db96d56Sopenharmony_ci return NULL; 17237db96d56Sopenharmony_ci } 17247db96d56Sopenharmony_ci if (it->counter == 0) 17257db96d56Sopenharmony_ci return NULL; 17267db96d56Sopenharmony_ci assert (!(it->b == it->deque->rightblock && 17277db96d56Sopenharmony_ci it->index > it->deque->rightindex)); 17287db96d56Sopenharmony_ci 17297db96d56Sopenharmony_ci item = it->b->data[it->index]; 17307db96d56Sopenharmony_ci it->index++; 17317db96d56Sopenharmony_ci it->counter--; 17327db96d56Sopenharmony_ci if (it->index == BLOCKLEN && it->counter > 0) { 17337db96d56Sopenharmony_ci CHECK_NOT_END(it->b->rightlink); 17347db96d56Sopenharmony_ci it->b = it->b->rightlink; 17357db96d56Sopenharmony_ci it->index = 0; 17367db96d56Sopenharmony_ci } 17377db96d56Sopenharmony_ci Py_INCREF(item); 17387db96d56Sopenharmony_ci return item; 17397db96d56Sopenharmony_ci} 17407db96d56Sopenharmony_ci 17417db96d56Sopenharmony_cistatic PyObject * 17427db96d56Sopenharmony_cidequeiter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 17437db96d56Sopenharmony_ci{ 17447db96d56Sopenharmony_ci Py_ssize_t i, index=0; 17457db96d56Sopenharmony_ci PyObject *deque; 17467db96d56Sopenharmony_ci dequeiterobject *it; 17477db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "O!|n", &deque_type, &deque, &index)) 17487db96d56Sopenharmony_ci return NULL; 17497db96d56Sopenharmony_ci assert(type == &dequeiter_type); 17507db96d56Sopenharmony_ci 17517db96d56Sopenharmony_ci it = (dequeiterobject*)deque_iter((dequeobject *)deque); 17527db96d56Sopenharmony_ci if (!it) 17537db96d56Sopenharmony_ci return NULL; 17547db96d56Sopenharmony_ci /* consume items from the queue */ 17557db96d56Sopenharmony_ci for(i=0; i<index; i++) { 17567db96d56Sopenharmony_ci PyObject *item = dequeiter_next(it); 17577db96d56Sopenharmony_ci if (item) { 17587db96d56Sopenharmony_ci Py_DECREF(item); 17597db96d56Sopenharmony_ci } else { 17607db96d56Sopenharmony_ci if (it->counter) { 17617db96d56Sopenharmony_ci Py_DECREF(it); 17627db96d56Sopenharmony_ci return NULL; 17637db96d56Sopenharmony_ci } else 17647db96d56Sopenharmony_ci break; 17657db96d56Sopenharmony_ci } 17667db96d56Sopenharmony_ci } 17677db96d56Sopenharmony_ci return (PyObject*)it; 17687db96d56Sopenharmony_ci} 17697db96d56Sopenharmony_ci 17707db96d56Sopenharmony_cistatic PyObject * 17717db96d56Sopenharmony_cidequeiter_len(dequeiterobject *it, PyObject *Py_UNUSED(ignored)) 17727db96d56Sopenharmony_ci{ 17737db96d56Sopenharmony_ci return PyLong_FromSsize_t(it->counter); 17747db96d56Sopenharmony_ci} 17757db96d56Sopenharmony_ci 17767db96d56Sopenharmony_ciPyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); 17777db96d56Sopenharmony_ci 17787db96d56Sopenharmony_cistatic PyObject * 17797db96d56Sopenharmony_cidequeiter_reduce(dequeiterobject *it, PyObject *Py_UNUSED(ignored)) 17807db96d56Sopenharmony_ci{ 17817db96d56Sopenharmony_ci return Py_BuildValue("O(On)", Py_TYPE(it), it->deque, Py_SIZE(it->deque) - it->counter); 17827db96d56Sopenharmony_ci} 17837db96d56Sopenharmony_ci 17847db96d56Sopenharmony_cistatic PyMethodDef dequeiter_methods[] = { 17857db96d56Sopenharmony_ci {"__length_hint__", (PyCFunction)dequeiter_len, METH_NOARGS, length_hint_doc}, 17867db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)dequeiter_reduce, METH_NOARGS, reduce_doc}, 17877db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 17887db96d56Sopenharmony_ci}; 17897db96d56Sopenharmony_ci 17907db96d56Sopenharmony_cistatic PyTypeObject dequeiter_type = { 17917db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 17927db96d56Sopenharmony_ci "_collections._deque_iterator", /* tp_name */ 17937db96d56Sopenharmony_ci sizeof(dequeiterobject), /* tp_basicsize */ 17947db96d56Sopenharmony_ci 0, /* tp_itemsize */ 17957db96d56Sopenharmony_ci /* methods */ 17967db96d56Sopenharmony_ci (destructor)dequeiter_dealloc, /* tp_dealloc */ 17977db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 17987db96d56Sopenharmony_ci 0, /* tp_getattr */ 17997db96d56Sopenharmony_ci 0, /* tp_setattr */ 18007db96d56Sopenharmony_ci 0, /* tp_as_async */ 18017db96d56Sopenharmony_ci 0, /* tp_repr */ 18027db96d56Sopenharmony_ci 0, /* tp_as_number */ 18037db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 18047db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 18057db96d56Sopenharmony_ci 0, /* tp_hash */ 18067db96d56Sopenharmony_ci 0, /* tp_call */ 18077db96d56Sopenharmony_ci 0, /* tp_str */ 18087db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 18097db96d56Sopenharmony_ci 0, /* tp_setattro */ 18107db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 18117db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 18127db96d56Sopenharmony_ci 0, /* tp_doc */ 18137db96d56Sopenharmony_ci (traverseproc)dequeiter_traverse, /* tp_traverse */ 18147db96d56Sopenharmony_ci 0, /* tp_clear */ 18157db96d56Sopenharmony_ci 0, /* tp_richcompare */ 18167db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 18177db96d56Sopenharmony_ci PyObject_SelfIter, /* tp_iter */ 18187db96d56Sopenharmony_ci (iternextfunc)dequeiter_next, /* tp_iternext */ 18197db96d56Sopenharmony_ci dequeiter_methods, /* tp_methods */ 18207db96d56Sopenharmony_ci 0, /* tp_members */ 18217db96d56Sopenharmony_ci 0, /* tp_getset */ 18227db96d56Sopenharmony_ci 0, /* tp_base */ 18237db96d56Sopenharmony_ci 0, /* tp_dict */ 18247db96d56Sopenharmony_ci 0, /* tp_descr_get */ 18257db96d56Sopenharmony_ci 0, /* tp_descr_set */ 18267db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 18277db96d56Sopenharmony_ci 0, /* tp_init */ 18287db96d56Sopenharmony_ci 0, /* tp_alloc */ 18297db96d56Sopenharmony_ci dequeiter_new, /* tp_new */ 18307db96d56Sopenharmony_ci 0, 18317db96d56Sopenharmony_ci}; 18327db96d56Sopenharmony_ci 18337db96d56Sopenharmony_ci/*********************** Deque Reverse Iterator **************************/ 18347db96d56Sopenharmony_ci 18357db96d56Sopenharmony_cistatic PyTypeObject dequereviter_type; 18367db96d56Sopenharmony_ci 18377db96d56Sopenharmony_cistatic PyObject * 18387db96d56Sopenharmony_cideque_reviter(dequeobject *deque, PyObject *Py_UNUSED(ignored)) 18397db96d56Sopenharmony_ci{ 18407db96d56Sopenharmony_ci dequeiterobject *it; 18417db96d56Sopenharmony_ci 18427db96d56Sopenharmony_ci it = PyObject_GC_New(dequeiterobject, &dequereviter_type); 18437db96d56Sopenharmony_ci if (it == NULL) 18447db96d56Sopenharmony_ci return NULL; 18457db96d56Sopenharmony_ci it->b = deque->rightblock; 18467db96d56Sopenharmony_ci it->index = deque->rightindex; 18477db96d56Sopenharmony_ci Py_INCREF(deque); 18487db96d56Sopenharmony_ci it->deque = deque; 18497db96d56Sopenharmony_ci it->state = deque->state; 18507db96d56Sopenharmony_ci it->counter = Py_SIZE(deque); 18517db96d56Sopenharmony_ci PyObject_GC_Track(it); 18527db96d56Sopenharmony_ci return (PyObject *)it; 18537db96d56Sopenharmony_ci} 18547db96d56Sopenharmony_ci 18557db96d56Sopenharmony_cistatic PyObject * 18567db96d56Sopenharmony_cidequereviter_next(dequeiterobject *it) 18577db96d56Sopenharmony_ci{ 18587db96d56Sopenharmony_ci PyObject *item; 18597db96d56Sopenharmony_ci if (it->counter == 0) 18607db96d56Sopenharmony_ci return NULL; 18617db96d56Sopenharmony_ci 18627db96d56Sopenharmony_ci if (it->deque->state != it->state) { 18637db96d56Sopenharmony_ci it->counter = 0; 18647db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 18657db96d56Sopenharmony_ci "deque mutated during iteration"); 18667db96d56Sopenharmony_ci return NULL; 18677db96d56Sopenharmony_ci } 18687db96d56Sopenharmony_ci assert (!(it->b == it->deque->leftblock && 18697db96d56Sopenharmony_ci it->index < it->deque->leftindex)); 18707db96d56Sopenharmony_ci 18717db96d56Sopenharmony_ci item = it->b->data[it->index]; 18727db96d56Sopenharmony_ci it->index--; 18737db96d56Sopenharmony_ci it->counter--; 18747db96d56Sopenharmony_ci if (it->index < 0 && it->counter > 0) { 18757db96d56Sopenharmony_ci CHECK_NOT_END(it->b->leftlink); 18767db96d56Sopenharmony_ci it->b = it->b->leftlink; 18777db96d56Sopenharmony_ci it->index = BLOCKLEN - 1; 18787db96d56Sopenharmony_ci } 18797db96d56Sopenharmony_ci Py_INCREF(item); 18807db96d56Sopenharmony_ci return item; 18817db96d56Sopenharmony_ci} 18827db96d56Sopenharmony_ci 18837db96d56Sopenharmony_cistatic PyObject * 18847db96d56Sopenharmony_cidequereviter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 18857db96d56Sopenharmony_ci{ 18867db96d56Sopenharmony_ci Py_ssize_t i, index=0; 18877db96d56Sopenharmony_ci PyObject *deque; 18887db96d56Sopenharmony_ci dequeiterobject *it; 18897db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "O!|n", &deque_type, &deque, &index)) 18907db96d56Sopenharmony_ci return NULL; 18917db96d56Sopenharmony_ci assert(type == &dequereviter_type); 18927db96d56Sopenharmony_ci 18937db96d56Sopenharmony_ci it = (dequeiterobject*)deque_reviter((dequeobject *)deque, NULL); 18947db96d56Sopenharmony_ci if (!it) 18957db96d56Sopenharmony_ci return NULL; 18967db96d56Sopenharmony_ci /* consume items from the queue */ 18977db96d56Sopenharmony_ci for(i=0; i<index; i++) { 18987db96d56Sopenharmony_ci PyObject *item = dequereviter_next(it); 18997db96d56Sopenharmony_ci if (item) { 19007db96d56Sopenharmony_ci Py_DECREF(item); 19017db96d56Sopenharmony_ci } else { 19027db96d56Sopenharmony_ci if (it->counter) { 19037db96d56Sopenharmony_ci Py_DECREF(it); 19047db96d56Sopenharmony_ci return NULL; 19057db96d56Sopenharmony_ci } else 19067db96d56Sopenharmony_ci break; 19077db96d56Sopenharmony_ci } 19087db96d56Sopenharmony_ci } 19097db96d56Sopenharmony_ci return (PyObject*)it; 19107db96d56Sopenharmony_ci} 19117db96d56Sopenharmony_ci 19127db96d56Sopenharmony_cistatic PyTypeObject dequereviter_type = { 19137db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 19147db96d56Sopenharmony_ci "_collections._deque_reverse_iterator", /* tp_name */ 19157db96d56Sopenharmony_ci sizeof(dequeiterobject), /* tp_basicsize */ 19167db96d56Sopenharmony_ci 0, /* tp_itemsize */ 19177db96d56Sopenharmony_ci /* methods */ 19187db96d56Sopenharmony_ci (destructor)dequeiter_dealloc, /* tp_dealloc */ 19197db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 19207db96d56Sopenharmony_ci 0, /* tp_getattr */ 19217db96d56Sopenharmony_ci 0, /* tp_setattr */ 19227db96d56Sopenharmony_ci 0, /* tp_as_async */ 19237db96d56Sopenharmony_ci 0, /* tp_repr */ 19247db96d56Sopenharmony_ci 0, /* tp_as_number */ 19257db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 19267db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 19277db96d56Sopenharmony_ci 0, /* tp_hash */ 19287db96d56Sopenharmony_ci 0, /* tp_call */ 19297db96d56Sopenharmony_ci 0, /* tp_str */ 19307db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 19317db96d56Sopenharmony_ci 0, /* tp_setattro */ 19327db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 19337db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 19347db96d56Sopenharmony_ci 0, /* tp_doc */ 19357db96d56Sopenharmony_ci (traverseproc)dequeiter_traverse, /* tp_traverse */ 19367db96d56Sopenharmony_ci 0, /* tp_clear */ 19377db96d56Sopenharmony_ci 0, /* tp_richcompare */ 19387db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 19397db96d56Sopenharmony_ci PyObject_SelfIter, /* tp_iter */ 19407db96d56Sopenharmony_ci (iternextfunc)dequereviter_next, /* tp_iternext */ 19417db96d56Sopenharmony_ci dequeiter_methods, /* tp_methods */ 19427db96d56Sopenharmony_ci 0, /* tp_members */ 19437db96d56Sopenharmony_ci 0, /* tp_getset */ 19447db96d56Sopenharmony_ci 0, /* tp_base */ 19457db96d56Sopenharmony_ci 0, /* tp_dict */ 19467db96d56Sopenharmony_ci 0, /* tp_descr_get */ 19477db96d56Sopenharmony_ci 0, /* tp_descr_set */ 19487db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 19497db96d56Sopenharmony_ci 0, /* tp_init */ 19507db96d56Sopenharmony_ci 0, /* tp_alloc */ 19517db96d56Sopenharmony_ci dequereviter_new, /* tp_new */ 19527db96d56Sopenharmony_ci 0, 19537db96d56Sopenharmony_ci}; 19547db96d56Sopenharmony_ci 19557db96d56Sopenharmony_ci/* defaultdict type *********************************************************/ 19567db96d56Sopenharmony_ci 19577db96d56Sopenharmony_citypedef struct { 19587db96d56Sopenharmony_ci PyDictObject dict; 19597db96d56Sopenharmony_ci PyObject *default_factory; 19607db96d56Sopenharmony_ci} defdictobject; 19617db96d56Sopenharmony_ci 19627db96d56Sopenharmony_cistatic PyTypeObject defdict_type; /* Forward */ 19637db96d56Sopenharmony_ci 19647db96d56Sopenharmony_ciPyDoc_STRVAR(defdict_missing_doc, 19657db96d56Sopenharmony_ci"__missing__(key) # Called by __getitem__ for missing key; pseudo-code:\n\ 19667db96d56Sopenharmony_ci if self.default_factory is None: raise KeyError((key,))\n\ 19677db96d56Sopenharmony_ci self[key] = value = self.default_factory()\n\ 19687db96d56Sopenharmony_ci return value\n\ 19697db96d56Sopenharmony_ci"); 19707db96d56Sopenharmony_ci 19717db96d56Sopenharmony_cistatic PyObject * 19727db96d56Sopenharmony_cidefdict_missing(defdictobject *dd, PyObject *key) 19737db96d56Sopenharmony_ci{ 19747db96d56Sopenharmony_ci PyObject *factory = dd->default_factory; 19757db96d56Sopenharmony_ci PyObject *value; 19767db96d56Sopenharmony_ci if (factory == NULL || factory == Py_None) { 19777db96d56Sopenharmony_ci /* XXX Call dict.__missing__(key) */ 19787db96d56Sopenharmony_ci PyObject *tup; 19797db96d56Sopenharmony_ci tup = PyTuple_Pack(1, key); 19807db96d56Sopenharmony_ci if (!tup) return NULL; 19817db96d56Sopenharmony_ci PyErr_SetObject(PyExc_KeyError, tup); 19827db96d56Sopenharmony_ci Py_DECREF(tup); 19837db96d56Sopenharmony_ci return NULL; 19847db96d56Sopenharmony_ci } 19857db96d56Sopenharmony_ci value = _PyObject_CallNoArgs(factory); 19867db96d56Sopenharmony_ci if (value == NULL) 19877db96d56Sopenharmony_ci return value; 19887db96d56Sopenharmony_ci if (PyObject_SetItem((PyObject *)dd, key, value) < 0) { 19897db96d56Sopenharmony_ci Py_DECREF(value); 19907db96d56Sopenharmony_ci return NULL; 19917db96d56Sopenharmony_ci } 19927db96d56Sopenharmony_ci return value; 19937db96d56Sopenharmony_ci} 19947db96d56Sopenharmony_ci 19957db96d56Sopenharmony_cistatic inline PyObject* 19967db96d56Sopenharmony_cinew_defdict(defdictobject *dd, PyObject *arg) 19977db96d56Sopenharmony_ci{ 19987db96d56Sopenharmony_ci return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd), 19997db96d56Sopenharmony_ci dd->default_factory ? dd->default_factory : Py_None, arg, NULL); 20007db96d56Sopenharmony_ci} 20017db96d56Sopenharmony_ci 20027db96d56Sopenharmony_ciPyDoc_STRVAR(defdict_copy_doc, "D.copy() -> a shallow copy of D."); 20037db96d56Sopenharmony_ci 20047db96d56Sopenharmony_cistatic PyObject * 20057db96d56Sopenharmony_cidefdict_copy(defdictobject *dd, PyObject *Py_UNUSED(ignored)) 20067db96d56Sopenharmony_ci{ 20077db96d56Sopenharmony_ci /* This calls the object's class. That only works for subclasses 20087db96d56Sopenharmony_ci whose class constructor has the same signature. Subclasses that 20097db96d56Sopenharmony_ci define a different constructor signature must override copy(). 20107db96d56Sopenharmony_ci */ 20117db96d56Sopenharmony_ci return new_defdict(dd, (PyObject*)dd); 20127db96d56Sopenharmony_ci} 20137db96d56Sopenharmony_ci 20147db96d56Sopenharmony_cistatic PyObject * 20157db96d56Sopenharmony_cidefdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored)) 20167db96d56Sopenharmony_ci{ 20177db96d56Sopenharmony_ci /* __reduce__ must return a 5-tuple as follows: 20187db96d56Sopenharmony_ci 20197db96d56Sopenharmony_ci - factory function 20207db96d56Sopenharmony_ci - tuple of args for the factory function 20217db96d56Sopenharmony_ci - additional state (here None) 20227db96d56Sopenharmony_ci - sequence iterator (here None) 20237db96d56Sopenharmony_ci - dictionary iterator (yielding successive (key, value) pairs 20247db96d56Sopenharmony_ci 20257db96d56Sopenharmony_ci This API is used by pickle.py and copy.py. 20267db96d56Sopenharmony_ci 20277db96d56Sopenharmony_ci For this to be useful with pickle.py, the default_factory 20287db96d56Sopenharmony_ci must be picklable; e.g., None, a built-in, or a global 20297db96d56Sopenharmony_ci function in a module or package. 20307db96d56Sopenharmony_ci 20317db96d56Sopenharmony_ci Both shallow and deep copying are supported, but for deep 20327db96d56Sopenharmony_ci copying, the default_factory must be deep-copyable; e.g. None, 20337db96d56Sopenharmony_ci or a built-in (functions are not copyable at this time). 20347db96d56Sopenharmony_ci 20357db96d56Sopenharmony_ci This only works for subclasses as long as their constructor 20367db96d56Sopenharmony_ci signature is compatible; the first argument must be the 20377db96d56Sopenharmony_ci optional default_factory, defaulting to None. 20387db96d56Sopenharmony_ci */ 20397db96d56Sopenharmony_ci PyObject *args; 20407db96d56Sopenharmony_ci PyObject *items; 20417db96d56Sopenharmony_ci PyObject *iter; 20427db96d56Sopenharmony_ci PyObject *result; 20437db96d56Sopenharmony_ci 20447db96d56Sopenharmony_ci if (dd->default_factory == NULL || dd->default_factory == Py_None) 20457db96d56Sopenharmony_ci args = PyTuple_New(0); 20467db96d56Sopenharmony_ci else 20477db96d56Sopenharmony_ci args = PyTuple_Pack(1, dd->default_factory); 20487db96d56Sopenharmony_ci if (args == NULL) 20497db96d56Sopenharmony_ci return NULL; 20507db96d56Sopenharmony_ci items = PyObject_CallMethodNoArgs((PyObject *)dd, &_Py_ID(items)); 20517db96d56Sopenharmony_ci if (items == NULL) { 20527db96d56Sopenharmony_ci Py_DECREF(args); 20537db96d56Sopenharmony_ci return NULL; 20547db96d56Sopenharmony_ci } 20557db96d56Sopenharmony_ci iter = PyObject_GetIter(items); 20567db96d56Sopenharmony_ci if (iter == NULL) { 20577db96d56Sopenharmony_ci Py_DECREF(items); 20587db96d56Sopenharmony_ci Py_DECREF(args); 20597db96d56Sopenharmony_ci return NULL; 20607db96d56Sopenharmony_ci } 20617db96d56Sopenharmony_ci result = PyTuple_Pack(5, Py_TYPE(dd), args, 20627db96d56Sopenharmony_ci Py_None, Py_None, iter); 20637db96d56Sopenharmony_ci Py_DECREF(iter); 20647db96d56Sopenharmony_ci Py_DECREF(items); 20657db96d56Sopenharmony_ci Py_DECREF(args); 20667db96d56Sopenharmony_ci return result; 20677db96d56Sopenharmony_ci} 20687db96d56Sopenharmony_ci 20697db96d56Sopenharmony_cistatic PyMethodDef defdict_methods[] = { 20707db96d56Sopenharmony_ci {"__missing__", (PyCFunction)defdict_missing, METH_O, 20717db96d56Sopenharmony_ci defdict_missing_doc}, 20727db96d56Sopenharmony_ci {"copy", (PyCFunction)defdict_copy, METH_NOARGS, 20737db96d56Sopenharmony_ci defdict_copy_doc}, 20747db96d56Sopenharmony_ci {"__copy__", (PyCFunction)defdict_copy, METH_NOARGS, 20757db96d56Sopenharmony_ci defdict_copy_doc}, 20767db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)defdict_reduce, METH_NOARGS, 20777db96d56Sopenharmony_ci reduce_doc}, 20787db96d56Sopenharmony_ci {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, 20797db96d56Sopenharmony_ci PyDoc_STR("See PEP 585")}, 20807db96d56Sopenharmony_ci {NULL} 20817db96d56Sopenharmony_ci}; 20827db96d56Sopenharmony_ci 20837db96d56Sopenharmony_cistatic PyMemberDef defdict_members[] = { 20847db96d56Sopenharmony_ci {"default_factory", T_OBJECT, 20857db96d56Sopenharmony_ci offsetof(defdictobject, default_factory), 0, 20867db96d56Sopenharmony_ci PyDoc_STR("Factory for default value called by __missing__().")}, 20877db96d56Sopenharmony_ci {NULL} 20887db96d56Sopenharmony_ci}; 20897db96d56Sopenharmony_ci 20907db96d56Sopenharmony_cistatic void 20917db96d56Sopenharmony_cidefdict_dealloc(defdictobject *dd) 20927db96d56Sopenharmony_ci{ 20937db96d56Sopenharmony_ci /* bpo-31095: UnTrack is needed before calling any callbacks */ 20947db96d56Sopenharmony_ci PyObject_GC_UnTrack(dd); 20957db96d56Sopenharmony_ci Py_CLEAR(dd->default_factory); 20967db96d56Sopenharmony_ci PyDict_Type.tp_dealloc((PyObject *)dd); 20977db96d56Sopenharmony_ci} 20987db96d56Sopenharmony_ci 20997db96d56Sopenharmony_cistatic PyObject * 21007db96d56Sopenharmony_cidefdict_repr(defdictobject *dd) 21017db96d56Sopenharmony_ci{ 21027db96d56Sopenharmony_ci PyObject *baserepr; 21037db96d56Sopenharmony_ci PyObject *defrepr; 21047db96d56Sopenharmony_ci PyObject *result; 21057db96d56Sopenharmony_ci baserepr = PyDict_Type.tp_repr((PyObject *)dd); 21067db96d56Sopenharmony_ci if (baserepr == NULL) 21077db96d56Sopenharmony_ci return NULL; 21087db96d56Sopenharmony_ci if (dd->default_factory == NULL) 21097db96d56Sopenharmony_ci defrepr = PyUnicode_FromString("None"); 21107db96d56Sopenharmony_ci else 21117db96d56Sopenharmony_ci { 21127db96d56Sopenharmony_ci int status = Py_ReprEnter(dd->default_factory); 21137db96d56Sopenharmony_ci if (status != 0) { 21147db96d56Sopenharmony_ci if (status < 0) { 21157db96d56Sopenharmony_ci Py_DECREF(baserepr); 21167db96d56Sopenharmony_ci return NULL; 21177db96d56Sopenharmony_ci } 21187db96d56Sopenharmony_ci defrepr = PyUnicode_FromString("..."); 21197db96d56Sopenharmony_ci } 21207db96d56Sopenharmony_ci else 21217db96d56Sopenharmony_ci defrepr = PyObject_Repr(dd->default_factory); 21227db96d56Sopenharmony_ci Py_ReprLeave(dd->default_factory); 21237db96d56Sopenharmony_ci } 21247db96d56Sopenharmony_ci if (defrepr == NULL) { 21257db96d56Sopenharmony_ci Py_DECREF(baserepr); 21267db96d56Sopenharmony_ci return NULL; 21277db96d56Sopenharmony_ci } 21287db96d56Sopenharmony_ci result = PyUnicode_FromFormat("%s(%U, %U)", 21297db96d56Sopenharmony_ci _PyType_Name(Py_TYPE(dd)), 21307db96d56Sopenharmony_ci defrepr, baserepr); 21317db96d56Sopenharmony_ci Py_DECREF(defrepr); 21327db96d56Sopenharmony_ci Py_DECREF(baserepr); 21337db96d56Sopenharmony_ci return result; 21347db96d56Sopenharmony_ci} 21357db96d56Sopenharmony_ci 21367db96d56Sopenharmony_cistatic PyObject* 21377db96d56Sopenharmony_cidefdict_or(PyObject* left, PyObject* right) 21387db96d56Sopenharmony_ci{ 21397db96d56Sopenharmony_ci PyObject *self, *other; 21407db96d56Sopenharmony_ci if (PyObject_TypeCheck(left, &defdict_type)) { 21417db96d56Sopenharmony_ci self = left; 21427db96d56Sopenharmony_ci other = right; 21437db96d56Sopenharmony_ci } 21447db96d56Sopenharmony_ci else { 21457db96d56Sopenharmony_ci self = right; 21467db96d56Sopenharmony_ci other = left; 21477db96d56Sopenharmony_ci } 21487db96d56Sopenharmony_ci if (!PyDict_Check(other)) { 21497db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 21507db96d56Sopenharmony_ci } 21517db96d56Sopenharmony_ci // Like copy(), this calls the object's class. 21527db96d56Sopenharmony_ci // Override __or__/__ror__ for subclasses with different constructors. 21537db96d56Sopenharmony_ci PyObject *new = new_defdict((defdictobject*)self, left); 21547db96d56Sopenharmony_ci if (!new) { 21557db96d56Sopenharmony_ci return NULL; 21567db96d56Sopenharmony_ci } 21577db96d56Sopenharmony_ci if (PyDict_Update(new, right)) { 21587db96d56Sopenharmony_ci Py_DECREF(new); 21597db96d56Sopenharmony_ci return NULL; 21607db96d56Sopenharmony_ci } 21617db96d56Sopenharmony_ci return new; 21627db96d56Sopenharmony_ci} 21637db96d56Sopenharmony_ci 21647db96d56Sopenharmony_cistatic PyNumberMethods defdict_as_number = { 21657db96d56Sopenharmony_ci .nb_or = defdict_or, 21667db96d56Sopenharmony_ci}; 21677db96d56Sopenharmony_ci 21687db96d56Sopenharmony_cistatic int 21697db96d56Sopenharmony_cidefdict_traverse(PyObject *self, visitproc visit, void *arg) 21707db96d56Sopenharmony_ci{ 21717db96d56Sopenharmony_ci Py_VISIT(((defdictobject *)self)->default_factory); 21727db96d56Sopenharmony_ci return PyDict_Type.tp_traverse(self, visit, arg); 21737db96d56Sopenharmony_ci} 21747db96d56Sopenharmony_ci 21757db96d56Sopenharmony_cistatic int 21767db96d56Sopenharmony_cidefdict_tp_clear(defdictobject *dd) 21777db96d56Sopenharmony_ci{ 21787db96d56Sopenharmony_ci Py_CLEAR(dd->default_factory); 21797db96d56Sopenharmony_ci return PyDict_Type.tp_clear((PyObject *)dd); 21807db96d56Sopenharmony_ci} 21817db96d56Sopenharmony_ci 21827db96d56Sopenharmony_cistatic int 21837db96d56Sopenharmony_cidefdict_init(PyObject *self, PyObject *args, PyObject *kwds) 21847db96d56Sopenharmony_ci{ 21857db96d56Sopenharmony_ci defdictobject *dd = (defdictobject *)self; 21867db96d56Sopenharmony_ci PyObject *olddefault = dd->default_factory; 21877db96d56Sopenharmony_ci PyObject *newdefault = NULL; 21887db96d56Sopenharmony_ci PyObject *newargs; 21897db96d56Sopenharmony_ci int result; 21907db96d56Sopenharmony_ci if (args == NULL || !PyTuple_Check(args)) 21917db96d56Sopenharmony_ci newargs = PyTuple_New(0); 21927db96d56Sopenharmony_ci else { 21937db96d56Sopenharmony_ci Py_ssize_t n = PyTuple_GET_SIZE(args); 21947db96d56Sopenharmony_ci if (n > 0) { 21957db96d56Sopenharmony_ci newdefault = PyTuple_GET_ITEM(args, 0); 21967db96d56Sopenharmony_ci if (!PyCallable_Check(newdefault) && newdefault != Py_None) { 21977db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 21987db96d56Sopenharmony_ci "first argument must be callable or None"); 21997db96d56Sopenharmony_ci return -1; 22007db96d56Sopenharmony_ci } 22017db96d56Sopenharmony_ci } 22027db96d56Sopenharmony_ci newargs = PySequence_GetSlice(args, 1, n); 22037db96d56Sopenharmony_ci } 22047db96d56Sopenharmony_ci if (newargs == NULL) 22057db96d56Sopenharmony_ci return -1; 22067db96d56Sopenharmony_ci Py_XINCREF(newdefault); 22077db96d56Sopenharmony_ci dd->default_factory = newdefault; 22087db96d56Sopenharmony_ci result = PyDict_Type.tp_init(self, newargs, kwds); 22097db96d56Sopenharmony_ci Py_DECREF(newargs); 22107db96d56Sopenharmony_ci Py_XDECREF(olddefault); 22117db96d56Sopenharmony_ci return result; 22127db96d56Sopenharmony_ci} 22137db96d56Sopenharmony_ci 22147db96d56Sopenharmony_ciPyDoc_STRVAR(defdict_doc, 22157db96d56Sopenharmony_ci"defaultdict(default_factory=None, /, [...]) --> dict with default factory\n\ 22167db96d56Sopenharmony_ci\n\ 22177db96d56Sopenharmony_ciThe default factory is called without arguments to produce\n\ 22187db96d56Sopenharmony_cia new value when a key is not present, in __getitem__ only.\n\ 22197db96d56Sopenharmony_ciA defaultdict compares equal to a dict with the same items.\n\ 22207db96d56Sopenharmony_ciAll remaining arguments are treated the same as if they were\n\ 22217db96d56Sopenharmony_cipassed to the dict constructor, including keyword arguments.\n\ 22227db96d56Sopenharmony_ci"); 22237db96d56Sopenharmony_ci 22247db96d56Sopenharmony_ci/* See comment in xxsubtype.c */ 22257db96d56Sopenharmony_ci#define DEFERRED_ADDRESS(ADDR) 0 22267db96d56Sopenharmony_ci 22277db96d56Sopenharmony_cistatic PyTypeObject defdict_type = { 22287db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) 22297db96d56Sopenharmony_ci "collections.defaultdict", /* tp_name */ 22307db96d56Sopenharmony_ci sizeof(defdictobject), /* tp_basicsize */ 22317db96d56Sopenharmony_ci 0, /* tp_itemsize */ 22327db96d56Sopenharmony_ci /* methods */ 22337db96d56Sopenharmony_ci (destructor)defdict_dealloc, /* tp_dealloc */ 22347db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 22357db96d56Sopenharmony_ci 0, /* tp_getattr */ 22367db96d56Sopenharmony_ci 0, /* tp_setattr */ 22377db96d56Sopenharmony_ci 0, /* tp_as_async */ 22387db96d56Sopenharmony_ci (reprfunc)defdict_repr, /* tp_repr */ 22397db96d56Sopenharmony_ci &defdict_as_number, /* tp_as_number */ 22407db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 22417db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 22427db96d56Sopenharmony_ci 0, /* tp_hash */ 22437db96d56Sopenharmony_ci 0, /* tp_call */ 22447db96d56Sopenharmony_ci 0, /* tp_str */ 22457db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 22467db96d56Sopenharmony_ci 0, /* tp_setattro */ 22477db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 22487db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, 22497db96d56Sopenharmony_ci /* tp_flags */ 22507db96d56Sopenharmony_ci defdict_doc, /* tp_doc */ 22517db96d56Sopenharmony_ci defdict_traverse, /* tp_traverse */ 22527db96d56Sopenharmony_ci (inquiry)defdict_tp_clear, /* tp_clear */ 22537db96d56Sopenharmony_ci 0, /* tp_richcompare */ 22547db96d56Sopenharmony_ci 0, /* tp_weaklistoffset*/ 22557db96d56Sopenharmony_ci 0, /* tp_iter */ 22567db96d56Sopenharmony_ci 0, /* tp_iternext */ 22577db96d56Sopenharmony_ci defdict_methods, /* tp_methods */ 22587db96d56Sopenharmony_ci defdict_members, /* tp_members */ 22597db96d56Sopenharmony_ci 0, /* tp_getset */ 22607db96d56Sopenharmony_ci DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */ 22617db96d56Sopenharmony_ci 0, /* tp_dict */ 22627db96d56Sopenharmony_ci 0, /* tp_descr_get */ 22637db96d56Sopenharmony_ci 0, /* tp_descr_set */ 22647db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 22657db96d56Sopenharmony_ci defdict_init, /* tp_init */ 22667db96d56Sopenharmony_ci PyType_GenericAlloc, /* tp_alloc */ 22677db96d56Sopenharmony_ci 0, /* tp_new */ 22687db96d56Sopenharmony_ci PyObject_GC_Del, /* tp_free */ 22697db96d56Sopenharmony_ci}; 22707db96d56Sopenharmony_ci 22717db96d56Sopenharmony_ci/* helper function for Counter *********************************************/ 22727db96d56Sopenharmony_ci 22737db96d56Sopenharmony_ci/*[clinic input] 22747db96d56Sopenharmony_ci_collections._count_elements 22757db96d56Sopenharmony_ci 22767db96d56Sopenharmony_ci mapping: object 22777db96d56Sopenharmony_ci iterable: object 22787db96d56Sopenharmony_ci / 22797db96d56Sopenharmony_ci 22807db96d56Sopenharmony_ciCount elements in the iterable, updating the mapping 22817db96d56Sopenharmony_ci[clinic start generated code]*/ 22827db96d56Sopenharmony_ci 22837db96d56Sopenharmony_cistatic PyObject * 22847db96d56Sopenharmony_ci_collections__count_elements_impl(PyObject *module, PyObject *mapping, 22857db96d56Sopenharmony_ci PyObject *iterable) 22867db96d56Sopenharmony_ci/*[clinic end generated code: output=7e0c1789636b3d8f input=e79fad04534a0b45]*/ 22877db96d56Sopenharmony_ci{ 22887db96d56Sopenharmony_ci PyObject *it, *oldval; 22897db96d56Sopenharmony_ci PyObject *newval = NULL; 22907db96d56Sopenharmony_ci PyObject *key = NULL; 22917db96d56Sopenharmony_ci PyObject *bound_get = NULL; 22927db96d56Sopenharmony_ci PyObject *mapping_get; 22937db96d56Sopenharmony_ci PyObject *dict_get; 22947db96d56Sopenharmony_ci PyObject *mapping_setitem; 22957db96d56Sopenharmony_ci PyObject *dict_setitem; 22967db96d56Sopenharmony_ci PyObject *one = _PyLong_GetOne(); // borrowed reference 22977db96d56Sopenharmony_ci 22987db96d56Sopenharmony_ci it = PyObject_GetIter(iterable); 22997db96d56Sopenharmony_ci if (it == NULL) 23007db96d56Sopenharmony_ci return NULL; 23017db96d56Sopenharmony_ci 23027db96d56Sopenharmony_ci /* Only take the fast path when get() and __setitem__() 23037db96d56Sopenharmony_ci * have not been overridden. 23047db96d56Sopenharmony_ci */ 23057db96d56Sopenharmony_ci mapping_get = _PyType_Lookup(Py_TYPE(mapping), &_Py_ID(get)); 23067db96d56Sopenharmony_ci dict_get = _PyType_Lookup(&PyDict_Type, &_Py_ID(get)); 23077db96d56Sopenharmony_ci mapping_setitem = _PyType_Lookup(Py_TYPE(mapping), &_Py_ID(__setitem__)); 23087db96d56Sopenharmony_ci dict_setitem = _PyType_Lookup(&PyDict_Type, &_Py_ID(__setitem__)); 23097db96d56Sopenharmony_ci 23107db96d56Sopenharmony_ci if (mapping_get != NULL && mapping_get == dict_get && 23117db96d56Sopenharmony_ci mapping_setitem != NULL && mapping_setitem == dict_setitem && 23127db96d56Sopenharmony_ci PyDict_Check(mapping)) 23137db96d56Sopenharmony_ci { 23147db96d56Sopenharmony_ci while (1) { 23157db96d56Sopenharmony_ci /* Fast path advantages: 23167db96d56Sopenharmony_ci 1. Eliminate double hashing 23177db96d56Sopenharmony_ci (by re-using the same hash for both the get and set) 23187db96d56Sopenharmony_ci 2. Avoid argument overhead of PyObject_CallFunctionObjArgs 23197db96d56Sopenharmony_ci (argument tuple creation and parsing) 23207db96d56Sopenharmony_ci 3. Avoid indirection through a bound method object 23217db96d56Sopenharmony_ci (creates another argument tuple) 23227db96d56Sopenharmony_ci 4. Avoid initial increment from zero 23237db96d56Sopenharmony_ci (reuse an existing one-object instead) 23247db96d56Sopenharmony_ci */ 23257db96d56Sopenharmony_ci Py_hash_t hash; 23267db96d56Sopenharmony_ci 23277db96d56Sopenharmony_ci key = PyIter_Next(it); 23287db96d56Sopenharmony_ci if (key == NULL) 23297db96d56Sopenharmony_ci break; 23307db96d56Sopenharmony_ci 23317db96d56Sopenharmony_ci if (!PyUnicode_CheckExact(key) || 23327db96d56Sopenharmony_ci (hash = _PyASCIIObject_CAST(key)->hash) == -1) 23337db96d56Sopenharmony_ci { 23347db96d56Sopenharmony_ci hash = PyObject_Hash(key); 23357db96d56Sopenharmony_ci if (hash == -1) 23367db96d56Sopenharmony_ci goto done; 23377db96d56Sopenharmony_ci } 23387db96d56Sopenharmony_ci 23397db96d56Sopenharmony_ci oldval = _PyDict_GetItem_KnownHash(mapping, key, hash); 23407db96d56Sopenharmony_ci if (oldval == NULL) { 23417db96d56Sopenharmony_ci if (PyErr_Occurred()) 23427db96d56Sopenharmony_ci goto done; 23437db96d56Sopenharmony_ci if (_PyDict_SetItem_KnownHash(mapping, key, one, hash) < 0) 23447db96d56Sopenharmony_ci goto done; 23457db96d56Sopenharmony_ci } else { 23467db96d56Sopenharmony_ci newval = PyNumber_Add(oldval, one); 23477db96d56Sopenharmony_ci if (newval == NULL) 23487db96d56Sopenharmony_ci goto done; 23497db96d56Sopenharmony_ci if (_PyDict_SetItem_KnownHash(mapping, key, newval, hash) < 0) 23507db96d56Sopenharmony_ci goto done; 23517db96d56Sopenharmony_ci Py_CLEAR(newval); 23527db96d56Sopenharmony_ci } 23537db96d56Sopenharmony_ci Py_DECREF(key); 23547db96d56Sopenharmony_ci } 23557db96d56Sopenharmony_ci } 23567db96d56Sopenharmony_ci else { 23577db96d56Sopenharmony_ci bound_get = PyObject_GetAttr(mapping, &_Py_ID(get)); 23587db96d56Sopenharmony_ci if (bound_get == NULL) 23597db96d56Sopenharmony_ci goto done; 23607db96d56Sopenharmony_ci 23617db96d56Sopenharmony_ci PyObject *zero = _PyLong_GetZero(); // borrowed reference 23627db96d56Sopenharmony_ci while (1) { 23637db96d56Sopenharmony_ci key = PyIter_Next(it); 23647db96d56Sopenharmony_ci if (key == NULL) 23657db96d56Sopenharmony_ci break; 23667db96d56Sopenharmony_ci oldval = PyObject_CallFunctionObjArgs(bound_get, key, zero, NULL); 23677db96d56Sopenharmony_ci if (oldval == NULL) 23687db96d56Sopenharmony_ci break; 23697db96d56Sopenharmony_ci newval = PyNumber_Add(oldval, one); 23707db96d56Sopenharmony_ci Py_DECREF(oldval); 23717db96d56Sopenharmony_ci if (newval == NULL) 23727db96d56Sopenharmony_ci break; 23737db96d56Sopenharmony_ci if (PyObject_SetItem(mapping, key, newval) < 0) 23747db96d56Sopenharmony_ci break; 23757db96d56Sopenharmony_ci Py_CLEAR(newval); 23767db96d56Sopenharmony_ci Py_DECREF(key); 23777db96d56Sopenharmony_ci } 23787db96d56Sopenharmony_ci } 23797db96d56Sopenharmony_ci 23807db96d56Sopenharmony_cidone: 23817db96d56Sopenharmony_ci Py_DECREF(it); 23827db96d56Sopenharmony_ci Py_XDECREF(key); 23837db96d56Sopenharmony_ci Py_XDECREF(newval); 23847db96d56Sopenharmony_ci Py_XDECREF(bound_get); 23857db96d56Sopenharmony_ci if (PyErr_Occurred()) 23867db96d56Sopenharmony_ci return NULL; 23877db96d56Sopenharmony_ci Py_RETURN_NONE; 23887db96d56Sopenharmony_ci} 23897db96d56Sopenharmony_ci 23907db96d56Sopenharmony_ci/* Helper function for namedtuple() ************************************/ 23917db96d56Sopenharmony_ci 23927db96d56Sopenharmony_citypedef struct { 23937db96d56Sopenharmony_ci PyObject_HEAD 23947db96d56Sopenharmony_ci Py_ssize_t index; 23957db96d56Sopenharmony_ci PyObject* doc; 23967db96d56Sopenharmony_ci} _tuplegetterobject; 23977db96d56Sopenharmony_ci 23987db96d56Sopenharmony_ci/*[clinic input] 23997db96d56Sopenharmony_ci@classmethod 24007db96d56Sopenharmony_ci_tuplegetter.__new__ as tuplegetter_new 24017db96d56Sopenharmony_ci 24027db96d56Sopenharmony_ci index: Py_ssize_t 24037db96d56Sopenharmony_ci doc: object 24047db96d56Sopenharmony_ci / 24057db96d56Sopenharmony_ci[clinic start generated code]*/ 24067db96d56Sopenharmony_ci 24077db96d56Sopenharmony_cistatic PyObject * 24087db96d56Sopenharmony_cituplegetter_new_impl(PyTypeObject *type, Py_ssize_t index, PyObject *doc) 24097db96d56Sopenharmony_ci/*[clinic end generated code: output=014be444ad80263f input=87c576a5bdbc0bbb]*/ 24107db96d56Sopenharmony_ci{ 24117db96d56Sopenharmony_ci _tuplegetterobject* self; 24127db96d56Sopenharmony_ci self = (_tuplegetterobject *)type->tp_alloc(type, 0); 24137db96d56Sopenharmony_ci if (self == NULL) { 24147db96d56Sopenharmony_ci return NULL; 24157db96d56Sopenharmony_ci } 24167db96d56Sopenharmony_ci self->index = index; 24177db96d56Sopenharmony_ci Py_INCREF(doc); 24187db96d56Sopenharmony_ci self->doc = doc; 24197db96d56Sopenharmony_ci return (PyObject *)self; 24207db96d56Sopenharmony_ci} 24217db96d56Sopenharmony_ci 24227db96d56Sopenharmony_cistatic PyObject * 24237db96d56Sopenharmony_cituplegetter_descr_get(PyObject *self, PyObject *obj, PyObject *type) 24247db96d56Sopenharmony_ci{ 24257db96d56Sopenharmony_ci Py_ssize_t index = ((_tuplegetterobject*)self)->index; 24267db96d56Sopenharmony_ci PyObject *result; 24277db96d56Sopenharmony_ci 24287db96d56Sopenharmony_ci if (obj == NULL) { 24297db96d56Sopenharmony_ci Py_INCREF(self); 24307db96d56Sopenharmony_ci return self; 24317db96d56Sopenharmony_ci } 24327db96d56Sopenharmony_ci if (!PyTuple_Check(obj)) { 24337db96d56Sopenharmony_ci if (obj == Py_None) { 24347db96d56Sopenharmony_ci Py_INCREF(self); 24357db96d56Sopenharmony_ci return self; 24367db96d56Sopenharmony_ci } 24377db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 24387db96d56Sopenharmony_ci "descriptor for index '%zd' for tuple subclasses " 24397db96d56Sopenharmony_ci "doesn't apply to '%s' object", 24407db96d56Sopenharmony_ci index, 24417db96d56Sopenharmony_ci Py_TYPE(obj)->tp_name); 24427db96d56Sopenharmony_ci return NULL; 24437db96d56Sopenharmony_ci } 24447db96d56Sopenharmony_ci 24457db96d56Sopenharmony_ci if (!valid_index(index, PyTuple_GET_SIZE(obj))) { 24467db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "tuple index out of range"); 24477db96d56Sopenharmony_ci return NULL; 24487db96d56Sopenharmony_ci } 24497db96d56Sopenharmony_ci 24507db96d56Sopenharmony_ci result = PyTuple_GET_ITEM(obj, index); 24517db96d56Sopenharmony_ci Py_INCREF(result); 24527db96d56Sopenharmony_ci return result; 24537db96d56Sopenharmony_ci} 24547db96d56Sopenharmony_ci 24557db96d56Sopenharmony_cistatic int 24567db96d56Sopenharmony_cituplegetter_descr_set(PyObject *self, PyObject *obj, PyObject *value) 24577db96d56Sopenharmony_ci{ 24587db96d56Sopenharmony_ci if (value == NULL) { 24597db96d56Sopenharmony_ci PyErr_SetString(PyExc_AttributeError, "can't delete attribute"); 24607db96d56Sopenharmony_ci } else { 24617db96d56Sopenharmony_ci PyErr_SetString(PyExc_AttributeError, "can't set attribute"); 24627db96d56Sopenharmony_ci } 24637db96d56Sopenharmony_ci return -1; 24647db96d56Sopenharmony_ci} 24657db96d56Sopenharmony_ci 24667db96d56Sopenharmony_cistatic int 24677db96d56Sopenharmony_cituplegetter_traverse(PyObject *self, visitproc visit, void *arg) 24687db96d56Sopenharmony_ci{ 24697db96d56Sopenharmony_ci _tuplegetterobject *tuplegetter = (_tuplegetterobject *)self; 24707db96d56Sopenharmony_ci Py_VISIT(tuplegetter->doc); 24717db96d56Sopenharmony_ci return 0; 24727db96d56Sopenharmony_ci} 24737db96d56Sopenharmony_ci 24747db96d56Sopenharmony_cistatic int 24757db96d56Sopenharmony_cituplegetter_clear(PyObject *self) 24767db96d56Sopenharmony_ci{ 24777db96d56Sopenharmony_ci _tuplegetterobject *tuplegetter = (_tuplegetterobject *)self; 24787db96d56Sopenharmony_ci Py_CLEAR(tuplegetter->doc); 24797db96d56Sopenharmony_ci return 0; 24807db96d56Sopenharmony_ci} 24817db96d56Sopenharmony_ci 24827db96d56Sopenharmony_cistatic void 24837db96d56Sopenharmony_cituplegetter_dealloc(_tuplegetterobject *self) 24847db96d56Sopenharmony_ci{ 24857db96d56Sopenharmony_ci PyObject_GC_UnTrack(self); 24867db96d56Sopenharmony_ci tuplegetter_clear((PyObject*)self); 24877db96d56Sopenharmony_ci Py_TYPE(self)->tp_free((PyObject*)self); 24887db96d56Sopenharmony_ci} 24897db96d56Sopenharmony_ci 24907db96d56Sopenharmony_cistatic PyObject* 24917db96d56Sopenharmony_cituplegetter_reduce(_tuplegetterobject *self, PyObject *Py_UNUSED(ignored)) 24927db96d56Sopenharmony_ci{ 24937db96d56Sopenharmony_ci return Py_BuildValue("(O(nO))", (PyObject*) Py_TYPE(self), self->index, self->doc); 24947db96d56Sopenharmony_ci} 24957db96d56Sopenharmony_ci 24967db96d56Sopenharmony_cistatic PyObject* 24977db96d56Sopenharmony_cituplegetter_repr(_tuplegetterobject *self) 24987db96d56Sopenharmony_ci{ 24997db96d56Sopenharmony_ci return PyUnicode_FromFormat("%s(%zd, %R)", 25007db96d56Sopenharmony_ci _PyType_Name(Py_TYPE(self)), 25017db96d56Sopenharmony_ci self->index, self->doc); 25027db96d56Sopenharmony_ci} 25037db96d56Sopenharmony_ci 25047db96d56Sopenharmony_ci 25057db96d56Sopenharmony_cistatic PyMemberDef tuplegetter_members[] = { 25067db96d56Sopenharmony_ci {"__doc__", T_OBJECT, offsetof(_tuplegetterobject, doc), 0}, 25077db96d56Sopenharmony_ci {0} 25087db96d56Sopenharmony_ci}; 25097db96d56Sopenharmony_ci 25107db96d56Sopenharmony_cistatic PyMethodDef tuplegetter_methods[] = { 25117db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)tuplegetter_reduce, METH_NOARGS, NULL}, 25127db96d56Sopenharmony_ci {NULL}, 25137db96d56Sopenharmony_ci}; 25147db96d56Sopenharmony_ci 25157db96d56Sopenharmony_cistatic PyTypeObject tuplegetter_type = { 25167db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 25177db96d56Sopenharmony_ci "_collections._tuplegetter", /* tp_name */ 25187db96d56Sopenharmony_ci sizeof(_tuplegetterobject), /* tp_basicsize */ 25197db96d56Sopenharmony_ci 0, /* tp_itemsize */ 25207db96d56Sopenharmony_ci /* methods */ 25217db96d56Sopenharmony_ci (destructor)tuplegetter_dealloc, /* tp_dealloc */ 25227db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 25237db96d56Sopenharmony_ci 0, /* tp_getattr */ 25247db96d56Sopenharmony_ci 0, /* tp_setattr */ 25257db96d56Sopenharmony_ci 0, /* tp_as_async */ 25267db96d56Sopenharmony_ci (reprfunc)tuplegetter_repr, /* tp_repr */ 25277db96d56Sopenharmony_ci 0, /* tp_as_number */ 25287db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 25297db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 25307db96d56Sopenharmony_ci 0, /* tp_hash */ 25317db96d56Sopenharmony_ci 0, /* tp_call */ 25327db96d56Sopenharmony_ci 0, /* tp_str */ 25337db96d56Sopenharmony_ci 0, /* tp_getattro */ 25347db96d56Sopenharmony_ci 0, /* tp_setattro */ 25357db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 25367db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 25377db96d56Sopenharmony_ci 0, /* tp_doc */ 25387db96d56Sopenharmony_ci (traverseproc)tuplegetter_traverse, /* tp_traverse */ 25397db96d56Sopenharmony_ci (inquiry)tuplegetter_clear, /* tp_clear */ 25407db96d56Sopenharmony_ci 0, /* tp_richcompare */ 25417db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 25427db96d56Sopenharmony_ci 0, /* tp_iter */ 25437db96d56Sopenharmony_ci 0, /* tp_iternext */ 25447db96d56Sopenharmony_ci tuplegetter_methods, /* tp_methods */ 25457db96d56Sopenharmony_ci tuplegetter_members, /* tp_members */ 25467db96d56Sopenharmony_ci 0, /* tp_getset */ 25477db96d56Sopenharmony_ci 0, /* tp_base */ 25487db96d56Sopenharmony_ci 0, /* tp_dict */ 25497db96d56Sopenharmony_ci tuplegetter_descr_get, /* tp_descr_get */ 25507db96d56Sopenharmony_ci tuplegetter_descr_set, /* tp_descr_set */ 25517db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 25527db96d56Sopenharmony_ci 0, /* tp_init */ 25537db96d56Sopenharmony_ci 0, /* tp_alloc */ 25547db96d56Sopenharmony_ci tuplegetter_new, /* tp_new */ 25557db96d56Sopenharmony_ci 0, 25567db96d56Sopenharmony_ci}; 25577db96d56Sopenharmony_ci 25587db96d56Sopenharmony_ci 25597db96d56Sopenharmony_ci/* module level code ********************************************************/ 25607db96d56Sopenharmony_ci 25617db96d56Sopenharmony_ciPyDoc_STRVAR(collections_doc, 25627db96d56Sopenharmony_ci"High performance data structures.\n\ 25637db96d56Sopenharmony_ci- deque: ordered collection accessible from endpoints only\n\ 25647db96d56Sopenharmony_ci- defaultdict: dict subclass with a default value factory\n\ 25657db96d56Sopenharmony_ci"); 25667db96d56Sopenharmony_ci 25677db96d56Sopenharmony_cistatic struct PyMethodDef collections_methods[] = { 25687db96d56Sopenharmony_ci _COLLECTIONS__COUNT_ELEMENTS_METHODDEF 25697db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 25707db96d56Sopenharmony_ci}; 25717db96d56Sopenharmony_ci 25727db96d56Sopenharmony_cistatic int 25737db96d56Sopenharmony_cicollections_exec(PyObject *module) { 25747db96d56Sopenharmony_ci PyTypeObject *typelist[] = { 25757db96d56Sopenharmony_ci &deque_type, 25767db96d56Sopenharmony_ci &defdict_type, 25777db96d56Sopenharmony_ci &PyODict_Type, 25787db96d56Sopenharmony_ci &dequeiter_type, 25797db96d56Sopenharmony_ci &dequereviter_type, 25807db96d56Sopenharmony_ci &tuplegetter_type 25817db96d56Sopenharmony_ci }; 25827db96d56Sopenharmony_ci 25837db96d56Sopenharmony_ci defdict_type.tp_base = &PyDict_Type; 25847db96d56Sopenharmony_ci 25857db96d56Sopenharmony_ci for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) { 25867db96d56Sopenharmony_ci if (PyModule_AddType(module, typelist[i]) < 0) { 25877db96d56Sopenharmony_ci return -1; 25887db96d56Sopenharmony_ci } 25897db96d56Sopenharmony_ci } 25907db96d56Sopenharmony_ci 25917db96d56Sopenharmony_ci return 0; 25927db96d56Sopenharmony_ci} 25937db96d56Sopenharmony_ci 25947db96d56Sopenharmony_cistatic struct PyModuleDef_Slot collections_slots[] = { 25957db96d56Sopenharmony_ci {Py_mod_exec, collections_exec}, 25967db96d56Sopenharmony_ci {0, NULL} 25977db96d56Sopenharmony_ci}; 25987db96d56Sopenharmony_ci 25997db96d56Sopenharmony_cistatic struct PyModuleDef _collectionsmodule = { 26007db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 26017db96d56Sopenharmony_ci "_collections", 26027db96d56Sopenharmony_ci collections_doc, 26037db96d56Sopenharmony_ci 0, 26047db96d56Sopenharmony_ci collections_methods, 26057db96d56Sopenharmony_ci collections_slots, 26067db96d56Sopenharmony_ci NULL, 26077db96d56Sopenharmony_ci NULL, 26087db96d56Sopenharmony_ci NULL 26097db96d56Sopenharmony_ci}; 26107db96d56Sopenharmony_ci 26117db96d56Sopenharmony_ciPyMODINIT_FUNC 26127db96d56Sopenharmony_ciPyInit__collections(void) 26137db96d56Sopenharmony_ci{ 26147db96d56Sopenharmony_ci return PyModuleDef_Init(&_collectionsmodule); 26157db96d56Sopenharmony_ci} 2616