17db96d56Sopenharmony_ci/* pickle accelerator C extensor: _pickle module.
27db96d56Sopenharmony_ci *
37db96d56Sopenharmony_ci * It is built as a built-in module (Py_BUILD_CORE_BUILTIN define) on Windows
47db96d56Sopenharmony_ci * and as an extension module (Py_BUILD_CORE_MODULE define) on other
57db96d56Sopenharmony_ci * platforms. */
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN
87db96d56Sopenharmony_ci#  define Py_BUILD_CORE_MODULE 1
97db96d56Sopenharmony_ci#endif
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ci#include "Python.h"
127db96d56Sopenharmony_ci#include "pycore_ceval.h"         // _Py_EnterRecursiveCall()
137db96d56Sopenharmony_ci#include "pycore_moduleobject.h"  // _PyModule_GetState()
147db96d56Sopenharmony_ci#include "pycore_runtime.h"       // _Py_ID()
157db96d56Sopenharmony_ci#include "pycore_pystate.h"       // _PyThreadState_GET()
167db96d56Sopenharmony_ci#include "structmember.h"         // PyMemberDef
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ci#include <stdlib.h>               // strtol()
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ciPyDoc_STRVAR(pickle_module_doc,
217db96d56Sopenharmony_ci"Optimized C implementation for the Python pickle module.");
227db96d56Sopenharmony_ci
237db96d56Sopenharmony_ci/*[clinic input]
247db96d56Sopenharmony_cimodule _pickle
257db96d56Sopenharmony_ciclass _pickle.Pickler "PicklerObject *" "&Pickler_Type"
267db96d56Sopenharmony_ciclass _pickle.PicklerMemoProxy "PicklerMemoProxyObject *" "&PicklerMemoProxyType"
277db96d56Sopenharmony_ciclass _pickle.Unpickler "UnpicklerObject *" "&Unpickler_Type"
287db96d56Sopenharmony_ciclass _pickle.UnpicklerMemoProxy "UnpicklerMemoProxyObject *" "&UnpicklerMemoProxyType"
297db96d56Sopenharmony_ci[clinic start generated code]*/
307db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b3e113468a58e6c]*/
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_ci/* Bump HIGHEST_PROTOCOL when new opcodes are added to the pickle protocol.
337db96d56Sopenharmony_ci   Bump DEFAULT_PROTOCOL only when the oldest still supported version of Python
347db96d56Sopenharmony_ci   already includes it. */
357db96d56Sopenharmony_cienum {
367db96d56Sopenharmony_ci    HIGHEST_PROTOCOL = 5,
377db96d56Sopenharmony_ci    DEFAULT_PROTOCOL = 4
387db96d56Sopenharmony_ci};
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ci#ifdef MS_WINDOWS
417db96d56Sopenharmony_ci// These are already typedefs from windows.h, pulled in via pycore_runtime.h.
427db96d56Sopenharmony_ci#define FLOAT FLOAT_
437db96d56Sopenharmony_ci#define INT INT_
447db96d56Sopenharmony_ci#define LONG LONG_
457db96d56Sopenharmony_ci#endif
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci/* Pickle opcodes. These must be kept updated with pickle.py.
487db96d56Sopenharmony_ci   Extensive docs are in pickletools.py. */
497db96d56Sopenharmony_cienum opcode {
507db96d56Sopenharmony_ci    MARK            = '(',
517db96d56Sopenharmony_ci    STOP            = '.',
527db96d56Sopenharmony_ci    POP             = '0',
537db96d56Sopenharmony_ci    POP_MARK        = '1',
547db96d56Sopenharmony_ci    DUP             = '2',
557db96d56Sopenharmony_ci    FLOAT           = 'F',
567db96d56Sopenharmony_ci    INT             = 'I',
577db96d56Sopenharmony_ci    BININT          = 'J',
587db96d56Sopenharmony_ci    BININT1         = 'K',
597db96d56Sopenharmony_ci    LONG            = 'L',
607db96d56Sopenharmony_ci    BININT2         = 'M',
617db96d56Sopenharmony_ci    NONE            = 'N',
627db96d56Sopenharmony_ci    PERSID          = 'P',
637db96d56Sopenharmony_ci    BINPERSID       = 'Q',
647db96d56Sopenharmony_ci    REDUCE          = 'R',
657db96d56Sopenharmony_ci    STRING          = 'S',
667db96d56Sopenharmony_ci    BINSTRING       = 'T',
677db96d56Sopenharmony_ci    SHORT_BINSTRING = 'U',
687db96d56Sopenharmony_ci    UNICODE         = 'V',
697db96d56Sopenharmony_ci    BINUNICODE      = 'X',
707db96d56Sopenharmony_ci    APPEND          = 'a',
717db96d56Sopenharmony_ci    BUILD           = 'b',
727db96d56Sopenharmony_ci    GLOBAL          = 'c',
737db96d56Sopenharmony_ci    DICT            = 'd',
747db96d56Sopenharmony_ci    EMPTY_DICT      = '}',
757db96d56Sopenharmony_ci    APPENDS         = 'e',
767db96d56Sopenharmony_ci    GET             = 'g',
777db96d56Sopenharmony_ci    BINGET          = 'h',
787db96d56Sopenharmony_ci    INST            = 'i',
797db96d56Sopenharmony_ci    LONG_BINGET     = 'j',
807db96d56Sopenharmony_ci    LIST            = 'l',
817db96d56Sopenharmony_ci    EMPTY_LIST      = ']',
827db96d56Sopenharmony_ci    OBJ             = 'o',
837db96d56Sopenharmony_ci    PUT             = 'p',
847db96d56Sopenharmony_ci    BINPUT          = 'q',
857db96d56Sopenharmony_ci    LONG_BINPUT     = 'r',
867db96d56Sopenharmony_ci    SETITEM         = 's',
877db96d56Sopenharmony_ci    TUPLE           = 't',
887db96d56Sopenharmony_ci    EMPTY_TUPLE     = ')',
897db96d56Sopenharmony_ci    SETITEMS        = 'u',
907db96d56Sopenharmony_ci    BINFLOAT        = 'G',
917db96d56Sopenharmony_ci
927db96d56Sopenharmony_ci    /* Protocol 2. */
937db96d56Sopenharmony_ci    PROTO       = '\x80',
947db96d56Sopenharmony_ci    NEWOBJ      = '\x81',
957db96d56Sopenharmony_ci    EXT1        = '\x82',
967db96d56Sopenharmony_ci    EXT2        = '\x83',
977db96d56Sopenharmony_ci    EXT4        = '\x84',
987db96d56Sopenharmony_ci    TUPLE1      = '\x85',
997db96d56Sopenharmony_ci    TUPLE2      = '\x86',
1007db96d56Sopenharmony_ci    TUPLE3      = '\x87',
1017db96d56Sopenharmony_ci    NEWTRUE     = '\x88',
1027db96d56Sopenharmony_ci    NEWFALSE    = '\x89',
1037db96d56Sopenharmony_ci    LONG1       = '\x8a',
1047db96d56Sopenharmony_ci    LONG4       = '\x8b',
1057db96d56Sopenharmony_ci
1067db96d56Sopenharmony_ci    /* Protocol 3 (Python 3.x) */
1077db96d56Sopenharmony_ci    BINBYTES       = 'B',
1087db96d56Sopenharmony_ci    SHORT_BINBYTES = 'C',
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci    /* Protocol 4 */
1117db96d56Sopenharmony_ci    SHORT_BINUNICODE = '\x8c',
1127db96d56Sopenharmony_ci    BINUNICODE8      = '\x8d',
1137db96d56Sopenharmony_ci    BINBYTES8        = '\x8e',
1147db96d56Sopenharmony_ci    EMPTY_SET        = '\x8f',
1157db96d56Sopenharmony_ci    ADDITEMS         = '\x90',
1167db96d56Sopenharmony_ci    FROZENSET        = '\x91',
1177db96d56Sopenharmony_ci    NEWOBJ_EX        = '\x92',
1187db96d56Sopenharmony_ci    STACK_GLOBAL     = '\x93',
1197db96d56Sopenharmony_ci    MEMOIZE          = '\x94',
1207db96d56Sopenharmony_ci    FRAME            = '\x95',
1217db96d56Sopenharmony_ci
1227db96d56Sopenharmony_ci    /* Protocol 5 */
1237db96d56Sopenharmony_ci    BYTEARRAY8       = '\x96',
1247db96d56Sopenharmony_ci    NEXT_BUFFER      = '\x97',
1257db96d56Sopenharmony_ci    READONLY_BUFFER  = '\x98'
1267db96d56Sopenharmony_ci};
1277db96d56Sopenharmony_ci
1287db96d56Sopenharmony_cienum {
1297db96d56Sopenharmony_ci   /* Keep in synch with pickle.Pickler._BATCHSIZE.  This is how many elements
1307db96d56Sopenharmony_ci      batch_list/dict() pumps out before doing APPENDS/SETITEMS.  Nothing will
1317db96d56Sopenharmony_ci      break if this gets out of synch with pickle.py, but it's unclear that would
1327db96d56Sopenharmony_ci      help anything either. */
1337db96d56Sopenharmony_ci    BATCHSIZE = 1000,
1347db96d56Sopenharmony_ci
1357db96d56Sopenharmony_ci    /* Nesting limit until Pickler, when running in "fast mode", starts
1367db96d56Sopenharmony_ci       checking for self-referential data-structures. */
1377db96d56Sopenharmony_ci    FAST_NESTING_LIMIT = 50,
1387db96d56Sopenharmony_ci
1397db96d56Sopenharmony_ci    /* Initial size of the write buffer of Pickler. */
1407db96d56Sopenharmony_ci    WRITE_BUF_SIZE = 4096,
1417db96d56Sopenharmony_ci
1427db96d56Sopenharmony_ci    /* Prefetch size when unpickling (disabled on unpeekable streams) */
1437db96d56Sopenharmony_ci    PREFETCH = 8192 * 16,
1447db96d56Sopenharmony_ci
1457db96d56Sopenharmony_ci    FRAME_SIZE_MIN = 4,
1467db96d56Sopenharmony_ci    FRAME_SIZE_TARGET = 64 * 1024,
1477db96d56Sopenharmony_ci    FRAME_HEADER_SIZE = 9
1487db96d56Sopenharmony_ci};
1497db96d56Sopenharmony_ci
1507db96d56Sopenharmony_ci/*************************************************************************/
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_ci/* State of the pickle module, per PEP 3121. */
1537db96d56Sopenharmony_citypedef struct {
1547db96d56Sopenharmony_ci    /* Exception classes for pickle. */
1557db96d56Sopenharmony_ci    PyObject *PickleError;
1567db96d56Sopenharmony_ci    PyObject *PicklingError;
1577db96d56Sopenharmony_ci    PyObject *UnpicklingError;
1587db96d56Sopenharmony_ci
1597db96d56Sopenharmony_ci    /* copyreg.dispatch_table, {type_object: pickling_function} */
1607db96d56Sopenharmony_ci    PyObject *dispatch_table;
1617db96d56Sopenharmony_ci
1627db96d56Sopenharmony_ci    /* For the extension opcodes EXT1, EXT2 and EXT4. */
1637db96d56Sopenharmony_ci
1647db96d56Sopenharmony_ci    /* copyreg._extension_registry, {(module_name, function_name): code} */
1657db96d56Sopenharmony_ci    PyObject *extension_registry;
1667db96d56Sopenharmony_ci    /* copyreg._extension_cache, {code: object} */
1677db96d56Sopenharmony_ci    PyObject *extension_cache;
1687db96d56Sopenharmony_ci    /* copyreg._inverted_registry, {code: (module_name, function_name)} */
1697db96d56Sopenharmony_ci    PyObject *inverted_registry;
1707db96d56Sopenharmony_ci
1717db96d56Sopenharmony_ci    /* Import mappings for compatibility with Python 2.x */
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci    /* _compat_pickle.NAME_MAPPING,
1747db96d56Sopenharmony_ci       {(oldmodule, oldname): (newmodule, newname)} */
1757db96d56Sopenharmony_ci    PyObject *name_mapping_2to3;
1767db96d56Sopenharmony_ci    /* _compat_pickle.IMPORT_MAPPING, {oldmodule: newmodule} */
1777db96d56Sopenharmony_ci    PyObject *import_mapping_2to3;
1787db96d56Sopenharmony_ci    /* Same, but with REVERSE_NAME_MAPPING / REVERSE_IMPORT_MAPPING */
1797db96d56Sopenharmony_ci    PyObject *name_mapping_3to2;
1807db96d56Sopenharmony_ci    PyObject *import_mapping_3to2;
1817db96d56Sopenharmony_ci
1827db96d56Sopenharmony_ci    /* codecs.encode, used for saving bytes in older protocols */
1837db96d56Sopenharmony_ci    PyObject *codecs_encode;
1847db96d56Sopenharmony_ci    /* builtins.getattr, used for saving nested names with protocol < 4 */
1857db96d56Sopenharmony_ci    PyObject *getattr;
1867db96d56Sopenharmony_ci    /* functools.partial, used for implementing __newobj_ex__ with protocols
1877db96d56Sopenharmony_ci       2 and 3 */
1887db96d56Sopenharmony_ci    PyObject *partial;
1897db96d56Sopenharmony_ci} PickleState;
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci/* Forward declaration of the _pickle module definition. */
1927db96d56Sopenharmony_cistatic struct PyModuleDef _picklemodule;
1937db96d56Sopenharmony_ci
1947db96d56Sopenharmony_ci/* Given a module object, get its per-module state. */
1957db96d56Sopenharmony_cistatic PickleState *
1967db96d56Sopenharmony_ci_Pickle_GetState(PyObject *module)
1977db96d56Sopenharmony_ci{
1987db96d56Sopenharmony_ci    return (PickleState *)_PyModule_GetState(module);
1997db96d56Sopenharmony_ci}
2007db96d56Sopenharmony_ci
2017db96d56Sopenharmony_ci/* Find the module instance imported in the currently running sub-interpreter
2027db96d56Sopenharmony_ci   and get its state. */
2037db96d56Sopenharmony_cistatic PickleState *
2047db96d56Sopenharmony_ci_Pickle_GetGlobalState(void)
2057db96d56Sopenharmony_ci{
2067db96d56Sopenharmony_ci    return _Pickle_GetState(PyState_FindModule(&_picklemodule));
2077db96d56Sopenharmony_ci}
2087db96d56Sopenharmony_ci
2097db96d56Sopenharmony_ci/* Clear the given pickle module state. */
2107db96d56Sopenharmony_cistatic void
2117db96d56Sopenharmony_ci_Pickle_ClearState(PickleState *st)
2127db96d56Sopenharmony_ci{
2137db96d56Sopenharmony_ci    Py_CLEAR(st->PickleError);
2147db96d56Sopenharmony_ci    Py_CLEAR(st->PicklingError);
2157db96d56Sopenharmony_ci    Py_CLEAR(st->UnpicklingError);
2167db96d56Sopenharmony_ci    Py_CLEAR(st->dispatch_table);
2177db96d56Sopenharmony_ci    Py_CLEAR(st->extension_registry);
2187db96d56Sopenharmony_ci    Py_CLEAR(st->extension_cache);
2197db96d56Sopenharmony_ci    Py_CLEAR(st->inverted_registry);
2207db96d56Sopenharmony_ci    Py_CLEAR(st->name_mapping_2to3);
2217db96d56Sopenharmony_ci    Py_CLEAR(st->import_mapping_2to3);
2227db96d56Sopenharmony_ci    Py_CLEAR(st->name_mapping_3to2);
2237db96d56Sopenharmony_ci    Py_CLEAR(st->import_mapping_3to2);
2247db96d56Sopenharmony_ci    Py_CLEAR(st->codecs_encode);
2257db96d56Sopenharmony_ci    Py_CLEAR(st->getattr);
2267db96d56Sopenharmony_ci    Py_CLEAR(st->partial);
2277db96d56Sopenharmony_ci}
2287db96d56Sopenharmony_ci
2297db96d56Sopenharmony_ci/* Initialize the given pickle module state. */
2307db96d56Sopenharmony_cistatic int
2317db96d56Sopenharmony_ci_Pickle_InitState(PickleState *st)
2327db96d56Sopenharmony_ci{
2337db96d56Sopenharmony_ci    PyObject *copyreg = NULL;
2347db96d56Sopenharmony_ci    PyObject *compat_pickle = NULL;
2357db96d56Sopenharmony_ci    PyObject *codecs = NULL;
2367db96d56Sopenharmony_ci    PyObject *functools = NULL;
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci    st->getattr = _PyEval_GetBuiltin(&_Py_ID(getattr));
2397db96d56Sopenharmony_ci    if (st->getattr == NULL)
2407db96d56Sopenharmony_ci        goto error;
2417db96d56Sopenharmony_ci
2427db96d56Sopenharmony_ci    copyreg = PyImport_ImportModule("copyreg");
2437db96d56Sopenharmony_ci    if (!copyreg)
2447db96d56Sopenharmony_ci        goto error;
2457db96d56Sopenharmony_ci    st->dispatch_table = PyObject_GetAttrString(copyreg, "dispatch_table");
2467db96d56Sopenharmony_ci    if (!st->dispatch_table)
2477db96d56Sopenharmony_ci        goto error;
2487db96d56Sopenharmony_ci    if (!PyDict_CheckExact(st->dispatch_table)) {
2497db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
2507db96d56Sopenharmony_ci                     "copyreg.dispatch_table should be a dict, not %.200s",
2517db96d56Sopenharmony_ci                     Py_TYPE(st->dispatch_table)->tp_name);
2527db96d56Sopenharmony_ci        goto error;
2537db96d56Sopenharmony_ci    }
2547db96d56Sopenharmony_ci    st->extension_registry = \
2557db96d56Sopenharmony_ci        PyObject_GetAttrString(copyreg, "_extension_registry");
2567db96d56Sopenharmony_ci    if (!st->extension_registry)
2577db96d56Sopenharmony_ci        goto error;
2587db96d56Sopenharmony_ci    if (!PyDict_CheckExact(st->extension_registry)) {
2597db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
2607db96d56Sopenharmony_ci                     "copyreg._extension_registry should be a dict, "
2617db96d56Sopenharmony_ci                     "not %.200s", Py_TYPE(st->extension_registry)->tp_name);
2627db96d56Sopenharmony_ci        goto error;
2637db96d56Sopenharmony_ci    }
2647db96d56Sopenharmony_ci    st->inverted_registry = \
2657db96d56Sopenharmony_ci        PyObject_GetAttrString(copyreg, "_inverted_registry");
2667db96d56Sopenharmony_ci    if (!st->inverted_registry)
2677db96d56Sopenharmony_ci        goto error;
2687db96d56Sopenharmony_ci    if (!PyDict_CheckExact(st->inverted_registry)) {
2697db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
2707db96d56Sopenharmony_ci                     "copyreg._inverted_registry should be a dict, "
2717db96d56Sopenharmony_ci                     "not %.200s", Py_TYPE(st->inverted_registry)->tp_name);
2727db96d56Sopenharmony_ci        goto error;
2737db96d56Sopenharmony_ci    }
2747db96d56Sopenharmony_ci    st->extension_cache = PyObject_GetAttrString(copyreg, "_extension_cache");
2757db96d56Sopenharmony_ci    if (!st->extension_cache)
2767db96d56Sopenharmony_ci        goto error;
2777db96d56Sopenharmony_ci    if (!PyDict_CheckExact(st->extension_cache)) {
2787db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
2797db96d56Sopenharmony_ci                     "copyreg._extension_cache should be a dict, "
2807db96d56Sopenharmony_ci                     "not %.200s", Py_TYPE(st->extension_cache)->tp_name);
2817db96d56Sopenharmony_ci        goto error;
2827db96d56Sopenharmony_ci    }
2837db96d56Sopenharmony_ci    Py_CLEAR(copyreg);
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_ci    /* Load the 2.x -> 3.x stdlib module mapping tables */
2867db96d56Sopenharmony_ci    compat_pickle = PyImport_ImportModule("_compat_pickle");
2877db96d56Sopenharmony_ci    if (!compat_pickle)
2887db96d56Sopenharmony_ci        goto error;
2897db96d56Sopenharmony_ci    st->name_mapping_2to3 = \
2907db96d56Sopenharmony_ci        PyObject_GetAttrString(compat_pickle, "NAME_MAPPING");
2917db96d56Sopenharmony_ci    if (!st->name_mapping_2to3)
2927db96d56Sopenharmony_ci        goto error;
2937db96d56Sopenharmony_ci    if (!PyDict_CheckExact(st->name_mapping_2to3)) {
2947db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
2957db96d56Sopenharmony_ci                     "_compat_pickle.NAME_MAPPING should be a dict, not %.200s",
2967db96d56Sopenharmony_ci                     Py_TYPE(st->name_mapping_2to3)->tp_name);
2977db96d56Sopenharmony_ci        goto error;
2987db96d56Sopenharmony_ci    }
2997db96d56Sopenharmony_ci    st->import_mapping_2to3 = \
3007db96d56Sopenharmony_ci        PyObject_GetAttrString(compat_pickle, "IMPORT_MAPPING");
3017db96d56Sopenharmony_ci    if (!st->import_mapping_2to3)
3027db96d56Sopenharmony_ci        goto error;
3037db96d56Sopenharmony_ci    if (!PyDict_CheckExact(st->import_mapping_2to3)) {
3047db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
3057db96d56Sopenharmony_ci                     "_compat_pickle.IMPORT_MAPPING should be a dict, "
3067db96d56Sopenharmony_ci                     "not %.200s", Py_TYPE(st->import_mapping_2to3)->tp_name);
3077db96d56Sopenharmony_ci        goto error;
3087db96d56Sopenharmony_ci    }
3097db96d56Sopenharmony_ci    /* ... and the 3.x -> 2.x mapping tables */
3107db96d56Sopenharmony_ci    st->name_mapping_3to2 = \
3117db96d56Sopenharmony_ci        PyObject_GetAttrString(compat_pickle, "REVERSE_NAME_MAPPING");
3127db96d56Sopenharmony_ci    if (!st->name_mapping_3to2)
3137db96d56Sopenharmony_ci        goto error;
3147db96d56Sopenharmony_ci    if (!PyDict_CheckExact(st->name_mapping_3to2)) {
3157db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
3167db96d56Sopenharmony_ci                     "_compat_pickle.REVERSE_NAME_MAPPING should be a dict, "
3177db96d56Sopenharmony_ci                     "not %.200s", Py_TYPE(st->name_mapping_3to2)->tp_name);
3187db96d56Sopenharmony_ci        goto error;
3197db96d56Sopenharmony_ci    }
3207db96d56Sopenharmony_ci    st->import_mapping_3to2 = \
3217db96d56Sopenharmony_ci        PyObject_GetAttrString(compat_pickle, "REVERSE_IMPORT_MAPPING");
3227db96d56Sopenharmony_ci    if (!st->import_mapping_3to2)
3237db96d56Sopenharmony_ci        goto error;
3247db96d56Sopenharmony_ci    if (!PyDict_CheckExact(st->import_mapping_3to2)) {
3257db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
3267db96d56Sopenharmony_ci                     "_compat_pickle.REVERSE_IMPORT_MAPPING should be a dict, "
3277db96d56Sopenharmony_ci                     "not %.200s", Py_TYPE(st->import_mapping_3to2)->tp_name);
3287db96d56Sopenharmony_ci        goto error;
3297db96d56Sopenharmony_ci    }
3307db96d56Sopenharmony_ci    Py_CLEAR(compat_pickle);
3317db96d56Sopenharmony_ci
3327db96d56Sopenharmony_ci    codecs = PyImport_ImportModule("codecs");
3337db96d56Sopenharmony_ci    if (codecs == NULL)
3347db96d56Sopenharmony_ci        goto error;
3357db96d56Sopenharmony_ci    st->codecs_encode = PyObject_GetAttrString(codecs, "encode");
3367db96d56Sopenharmony_ci    if (st->codecs_encode == NULL) {
3377db96d56Sopenharmony_ci        goto error;
3387db96d56Sopenharmony_ci    }
3397db96d56Sopenharmony_ci    if (!PyCallable_Check(st->codecs_encode)) {
3407db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
3417db96d56Sopenharmony_ci                     "codecs.encode should be a callable, not %.200s",
3427db96d56Sopenharmony_ci                     Py_TYPE(st->codecs_encode)->tp_name);
3437db96d56Sopenharmony_ci        goto error;
3447db96d56Sopenharmony_ci    }
3457db96d56Sopenharmony_ci    Py_CLEAR(codecs);
3467db96d56Sopenharmony_ci
3477db96d56Sopenharmony_ci    functools = PyImport_ImportModule("functools");
3487db96d56Sopenharmony_ci    if (!functools)
3497db96d56Sopenharmony_ci        goto error;
3507db96d56Sopenharmony_ci    st->partial = PyObject_GetAttrString(functools, "partial");
3517db96d56Sopenharmony_ci    if (!st->partial)
3527db96d56Sopenharmony_ci        goto error;
3537db96d56Sopenharmony_ci    Py_CLEAR(functools);
3547db96d56Sopenharmony_ci
3557db96d56Sopenharmony_ci    return 0;
3567db96d56Sopenharmony_ci
3577db96d56Sopenharmony_ci  error:
3587db96d56Sopenharmony_ci    Py_CLEAR(copyreg);
3597db96d56Sopenharmony_ci    Py_CLEAR(compat_pickle);
3607db96d56Sopenharmony_ci    Py_CLEAR(codecs);
3617db96d56Sopenharmony_ci    Py_CLEAR(functools);
3627db96d56Sopenharmony_ci    _Pickle_ClearState(st);
3637db96d56Sopenharmony_ci    return -1;
3647db96d56Sopenharmony_ci}
3657db96d56Sopenharmony_ci
3667db96d56Sopenharmony_ci/* Helper for calling a function with a single argument quickly.
3677db96d56Sopenharmony_ci
3687db96d56Sopenharmony_ci   This function steals the reference of the given argument. */
3697db96d56Sopenharmony_cistatic PyObject *
3707db96d56Sopenharmony_ci_Pickle_FastCall(PyObject *func, PyObject *obj)
3717db96d56Sopenharmony_ci{
3727db96d56Sopenharmony_ci    PyObject *result;
3737db96d56Sopenharmony_ci
3747db96d56Sopenharmony_ci    result = PyObject_CallOneArg(func, obj);
3757db96d56Sopenharmony_ci    Py_DECREF(obj);
3767db96d56Sopenharmony_ci    return result;
3777db96d56Sopenharmony_ci}
3787db96d56Sopenharmony_ci
3797db96d56Sopenharmony_ci/*************************************************************************/
3807db96d56Sopenharmony_ci
3817db96d56Sopenharmony_ci/* Retrieve and deconstruct a method for avoiding a reference cycle
3827db96d56Sopenharmony_ci   (pickler -> bound method of pickler -> pickler) */
3837db96d56Sopenharmony_cistatic int
3847db96d56Sopenharmony_ciinit_method_ref(PyObject *self, PyObject *name,
3857db96d56Sopenharmony_ci                PyObject **method_func, PyObject **method_self)
3867db96d56Sopenharmony_ci{
3877db96d56Sopenharmony_ci    PyObject *func, *func2;
3887db96d56Sopenharmony_ci    int ret;
3897db96d56Sopenharmony_ci
3907db96d56Sopenharmony_ci    /* *method_func and *method_self should be consistent.  All refcount decrements
3917db96d56Sopenharmony_ci       should be occurred after setting *method_self and *method_func. */
3927db96d56Sopenharmony_ci    ret = _PyObject_LookupAttr(self, name, &func);
3937db96d56Sopenharmony_ci    if (func == NULL) {
3947db96d56Sopenharmony_ci        *method_self = NULL;
3957db96d56Sopenharmony_ci        Py_CLEAR(*method_func);
3967db96d56Sopenharmony_ci        return ret;
3977db96d56Sopenharmony_ci    }
3987db96d56Sopenharmony_ci
3997db96d56Sopenharmony_ci    if (PyMethod_Check(func) && PyMethod_GET_SELF(func) == self) {
4007db96d56Sopenharmony_ci        /* Deconstruct a bound Python method */
4017db96d56Sopenharmony_ci        func2 = PyMethod_GET_FUNCTION(func);
4027db96d56Sopenharmony_ci        Py_INCREF(func2);
4037db96d56Sopenharmony_ci        *method_self = self; /* borrowed */
4047db96d56Sopenharmony_ci        Py_XSETREF(*method_func, func2);
4057db96d56Sopenharmony_ci        Py_DECREF(func);
4067db96d56Sopenharmony_ci        return 0;
4077db96d56Sopenharmony_ci    }
4087db96d56Sopenharmony_ci    else {
4097db96d56Sopenharmony_ci        *method_self = NULL;
4107db96d56Sopenharmony_ci        Py_XSETREF(*method_func, func);
4117db96d56Sopenharmony_ci        return 0;
4127db96d56Sopenharmony_ci    }
4137db96d56Sopenharmony_ci}
4147db96d56Sopenharmony_ci
4157db96d56Sopenharmony_ci/* Bind a method if it was deconstructed */
4167db96d56Sopenharmony_cistatic PyObject *
4177db96d56Sopenharmony_cireconstruct_method(PyObject *func, PyObject *self)
4187db96d56Sopenharmony_ci{
4197db96d56Sopenharmony_ci    if (self) {
4207db96d56Sopenharmony_ci        return PyMethod_New(func, self);
4217db96d56Sopenharmony_ci    }
4227db96d56Sopenharmony_ci    else {
4237db96d56Sopenharmony_ci        Py_INCREF(func);
4247db96d56Sopenharmony_ci        return func;
4257db96d56Sopenharmony_ci    }
4267db96d56Sopenharmony_ci}
4277db96d56Sopenharmony_ci
4287db96d56Sopenharmony_cistatic PyObject *
4297db96d56Sopenharmony_cicall_method(PyObject *func, PyObject *self, PyObject *obj)
4307db96d56Sopenharmony_ci{
4317db96d56Sopenharmony_ci    if (self) {
4327db96d56Sopenharmony_ci        return PyObject_CallFunctionObjArgs(func, self, obj, NULL);
4337db96d56Sopenharmony_ci    }
4347db96d56Sopenharmony_ci    else {
4357db96d56Sopenharmony_ci        return PyObject_CallOneArg(func, obj);
4367db96d56Sopenharmony_ci    }
4377db96d56Sopenharmony_ci}
4387db96d56Sopenharmony_ci
4397db96d56Sopenharmony_ci/*************************************************************************/
4407db96d56Sopenharmony_ci
4417db96d56Sopenharmony_ci/* Internal data type used as the unpickling stack. */
4427db96d56Sopenharmony_citypedef struct {
4437db96d56Sopenharmony_ci    PyObject_VAR_HEAD
4447db96d56Sopenharmony_ci    PyObject **data;
4457db96d56Sopenharmony_ci    int mark_set;          /* is MARK set? */
4467db96d56Sopenharmony_ci    Py_ssize_t fence;      /* position of top MARK or 0 */
4477db96d56Sopenharmony_ci    Py_ssize_t allocated;  /* number of slots in data allocated */
4487db96d56Sopenharmony_ci} Pdata;
4497db96d56Sopenharmony_ci
4507db96d56Sopenharmony_cistatic void
4517db96d56Sopenharmony_ciPdata_dealloc(Pdata *self)
4527db96d56Sopenharmony_ci{
4537db96d56Sopenharmony_ci    Py_ssize_t i = Py_SIZE(self);
4547db96d56Sopenharmony_ci    while (--i >= 0) {
4557db96d56Sopenharmony_ci        Py_DECREF(self->data[i]);
4567db96d56Sopenharmony_ci    }
4577db96d56Sopenharmony_ci    PyMem_Free(self->data);
4587db96d56Sopenharmony_ci    PyObject_Free(self);
4597db96d56Sopenharmony_ci}
4607db96d56Sopenharmony_ci
4617db96d56Sopenharmony_cistatic PyTypeObject Pdata_Type = {
4627db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(NULL, 0)
4637db96d56Sopenharmony_ci    "_pickle.Pdata",              /*tp_name*/
4647db96d56Sopenharmony_ci    sizeof(Pdata),                /*tp_basicsize*/
4657db96d56Sopenharmony_ci    sizeof(PyObject *),           /*tp_itemsize*/
4667db96d56Sopenharmony_ci    (destructor)Pdata_dealloc,    /*tp_dealloc*/
4677db96d56Sopenharmony_ci};
4687db96d56Sopenharmony_ci
4697db96d56Sopenharmony_cistatic PyObject *
4707db96d56Sopenharmony_ciPdata_New(void)
4717db96d56Sopenharmony_ci{
4727db96d56Sopenharmony_ci    Pdata *self;
4737db96d56Sopenharmony_ci
4747db96d56Sopenharmony_ci    if (!(self = PyObject_New(Pdata, &Pdata_Type)))
4757db96d56Sopenharmony_ci        return NULL;
4767db96d56Sopenharmony_ci    Py_SET_SIZE(self, 0);
4777db96d56Sopenharmony_ci    self->mark_set = 0;
4787db96d56Sopenharmony_ci    self->fence = 0;
4797db96d56Sopenharmony_ci    self->allocated = 8;
4807db96d56Sopenharmony_ci    self->data = PyMem_Malloc(self->allocated * sizeof(PyObject *));
4817db96d56Sopenharmony_ci    if (self->data)
4827db96d56Sopenharmony_ci        return (PyObject *)self;
4837db96d56Sopenharmony_ci    Py_DECREF(self);
4847db96d56Sopenharmony_ci    return PyErr_NoMemory();
4857db96d56Sopenharmony_ci}
4867db96d56Sopenharmony_ci
4877db96d56Sopenharmony_ci
4887db96d56Sopenharmony_ci/* Retain only the initial clearto items.  If clearto >= the current
4897db96d56Sopenharmony_ci * number of items, this is a (non-erroneous) NOP.
4907db96d56Sopenharmony_ci */
4917db96d56Sopenharmony_cistatic int
4927db96d56Sopenharmony_ciPdata_clear(Pdata *self, Py_ssize_t clearto)
4937db96d56Sopenharmony_ci{
4947db96d56Sopenharmony_ci    Py_ssize_t i = Py_SIZE(self);
4957db96d56Sopenharmony_ci
4967db96d56Sopenharmony_ci    assert(clearto >= self->fence);
4977db96d56Sopenharmony_ci    if (clearto >= i)
4987db96d56Sopenharmony_ci        return 0;
4997db96d56Sopenharmony_ci
5007db96d56Sopenharmony_ci    while (--i >= clearto) {
5017db96d56Sopenharmony_ci        Py_CLEAR(self->data[i]);
5027db96d56Sopenharmony_ci    }
5037db96d56Sopenharmony_ci    Py_SET_SIZE(self, clearto);
5047db96d56Sopenharmony_ci    return 0;
5057db96d56Sopenharmony_ci}
5067db96d56Sopenharmony_ci
5077db96d56Sopenharmony_cistatic int
5087db96d56Sopenharmony_ciPdata_grow(Pdata *self)
5097db96d56Sopenharmony_ci{
5107db96d56Sopenharmony_ci    PyObject **data = self->data;
5117db96d56Sopenharmony_ci    size_t allocated = (size_t)self->allocated;
5127db96d56Sopenharmony_ci    size_t new_allocated;
5137db96d56Sopenharmony_ci
5147db96d56Sopenharmony_ci    new_allocated = (allocated >> 3) + 6;
5157db96d56Sopenharmony_ci    /* check for integer overflow */
5167db96d56Sopenharmony_ci    if (new_allocated > (size_t)PY_SSIZE_T_MAX - allocated)
5177db96d56Sopenharmony_ci        goto nomemory;
5187db96d56Sopenharmony_ci    new_allocated += allocated;
5197db96d56Sopenharmony_ci    PyMem_RESIZE(data, PyObject *, new_allocated);
5207db96d56Sopenharmony_ci    if (data == NULL)
5217db96d56Sopenharmony_ci        goto nomemory;
5227db96d56Sopenharmony_ci
5237db96d56Sopenharmony_ci    self->data = data;
5247db96d56Sopenharmony_ci    self->allocated = (Py_ssize_t)new_allocated;
5257db96d56Sopenharmony_ci    return 0;
5267db96d56Sopenharmony_ci
5277db96d56Sopenharmony_ci  nomemory:
5287db96d56Sopenharmony_ci    PyErr_NoMemory();
5297db96d56Sopenharmony_ci    return -1;
5307db96d56Sopenharmony_ci}
5317db96d56Sopenharmony_ci
5327db96d56Sopenharmony_cistatic int
5337db96d56Sopenharmony_ciPdata_stack_underflow(Pdata *self)
5347db96d56Sopenharmony_ci{
5357db96d56Sopenharmony_ci    PickleState *st = _Pickle_GetGlobalState();
5367db96d56Sopenharmony_ci    PyErr_SetString(st->UnpicklingError,
5377db96d56Sopenharmony_ci                    self->mark_set ?
5387db96d56Sopenharmony_ci                    "unexpected MARK found" :
5397db96d56Sopenharmony_ci                    "unpickling stack underflow");
5407db96d56Sopenharmony_ci    return -1;
5417db96d56Sopenharmony_ci}
5427db96d56Sopenharmony_ci
5437db96d56Sopenharmony_ci/* D is a Pdata*.  Pop the topmost element and store it into V, which
5447db96d56Sopenharmony_ci * must be an lvalue holding PyObject*.  On stack underflow, UnpicklingError
5457db96d56Sopenharmony_ci * is raised and V is set to NULL.
5467db96d56Sopenharmony_ci */
5477db96d56Sopenharmony_cistatic PyObject *
5487db96d56Sopenharmony_ciPdata_pop(Pdata *self)
5497db96d56Sopenharmony_ci{
5507db96d56Sopenharmony_ci    if (Py_SIZE(self) <= self->fence) {
5517db96d56Sopenharmony_ci        Pdata_stack_underflow(self);
5527db96d56Sopenharmony_ci        return NULL;
5537db96d56Sopenharmony_ci    }
5547db96d56Sopenharmony_ci    Py_SET_SIZE(self, Py_SIZE(self) - 1);
5557db96d56Sopenharmony_ci    return self->data[Py_SIZE(self)];
5567db96d56Sopenharmony_ci}
5577db96d56Sopenharmony_ci#define PDATA_POP(D, V) do { (V) = Pdata_pop((D)); } while (0)
5587db96d56Sopenharmony_ci
5597db96d56Sopenharmony_cistatic int
5607db96d56Sopenharmony_ciPdata_push(Pdata *self, PyObject *obj)
5617db96d56Sopenharmony_ci{
5627db96d56Sopenharmony_ci    if (Py_SIZE(self) == self->allocated && Pdata_grow(self) < 0) {
5637db96d56Sopenharmony_ci        return -1;
5647db96d56Sopenharmony_ci    }
5657db96d56Sopenharmony_ci    self->data[Py_SIZE(self)] = obj;
5667db96d56Sopenharmony_ci    Py_SET_SIZE(self, Py_SIZE(self) + 1);
5677db96d56Sopenharmony_ci    return 0;
5687db96d56Sopenharmony_ci}
5697db96d56Sopenharmony_ci
5707db96d56Sopenharmony_ci/* Push an object on stack, transferring its ownership to the stack. */
5717db96d56Sopenharmony_ci#define PDATA_PUSH(D, O, ER) do {                               \
5727db96d56Sopenharmony_ci        if (Pdata_push((D), (O)) < 0) return (ER); } while(0)
5737db96d56Sopenharmony_ci
5747db96d56Sopenharmony_ci/* Push an object on stack, adding a new reference to the object. */
5757db96d56Sopenharmony_ci#define PDATA_APPEND(D, O, ER) do {                             \
5767db96d56Sopenharmony_ci        Py_INCREF((O));                                         \
5777db96d56Sopenharmony_ci        if (Pdata_push((D), (O)) < 0) return (ER); } while(0)
5787db96d56Sopenharmony_ci
5797db96d56Sopenharmony_cistatic PyObject *
5807db96d56Sopenharmony_ciPdata_poptuple(Pdata *self, Py_ssize_t start)
5817db96d56Sopenharmony_ci{
5827db96d56Sopenharmony_ci    PyObject *tuple;
5837db96d56Sopenharmony_ci    Py_ssize_t len, i, j;
5847db96d56Sopenharmony_ci
5857db96d56Sopenharmony_ci    if (start < self->fence) {
5867db96d56Sopenharmony_ci        Pdata_stack_underflow(self);
5877db96d56Sopenharmony_ci        return NULL;
5887db96d56Sopenharmony_ci    }
5897db96d56Sopenharmony_ci    len = Py_SIZE(self) - start;
5907db96d56Sopenharmony_ci    tuple = PyTuple_New(len);
5917db96d56Sopenharmony_ci    if (tuple == NULL)
5927db96d56Sopenharmony_ci        return NULL;
5937db96d56Sopenharmony_ci    for (i = start, j = 0; j < len; i++, j++)
5947db96d56Sopenharmony_ci        PyTuple_SET_ITEM(tuple, j, self->data[i]);
5957db96d56Sopenharmony_ci
5967db96d56Sopenharmony_ci    Py_SET_SIZE(self, start);
5977db96d56Sopenharmony_ci    return tuple;
5987db96d56Sopenharmony_ci}
5997db96d56Sopenharmony_ci
6007db96d56Sopenharmony_cistatic PyObject *
6017db96d56Sopenharmony_ciPdata_poplist(Pdata *self, Py_ssize_t start)
6027db96d56Sopenharmony_ci{
6037db96d56Sopenharmony_ci    PyObject *list;
6047db96d56Sopenharmony_ci    Py_ssize_t len, i, j;
6057db96d56Sopenharmony_ci
6067db96d56Sopenharmony_ci    len = Py_SIZE(self) - start;
6077db96d56Sopenharmony_ci    list = PyList_New(len);
6087db96d56Sopenharmony_ci    if (list == NULL)
6097db96d56Sopenharmony_ci        return NULL;
6107db96d56Sopenharmony_ci    for (i = start, j = 0; j < len; i++, j++)
6117db96d56Sopenharmony_ci        PyList_SET_ITEM(list, j, self->data[i]);
6127db96d56Sopenharmony_ci
6137db96d56Sopenharmony_ci    Py_SET_SIZE(self, start);
6147db96d56Sopenharmony_ci    return list;
6157db96d56Sopenharmony_ci}
6167db96d56Sopenharmony_ci
6177db96d56Sopenharmony_citypedef struct {
6187db96d56Sopenharmony_ci    PyObject *me_key;
6197db96d56Sopenharmony_ci    Py_ssize_t me_value;
6207db96d56Sopenharmony_ci} PyMemoEntry;
6217db96d56Sopenharmony_ci
6227db96d56Sopenharmony_citypedef struct {
6237db96d56Sopenharmony_ci    size_t mt_mask;
6247db96d56Sopenharmony_ci    size_t mt_used;
6257db96d56Sopenharmony_ci    size_t mt_allocated;
6267db96d56Sopenharmony_ci    PyMemoEntry *mt_table;
6277db96d56Sopenharmony_ci} PyMemoTable;
6287db96d56Sopenharmony_ci
6297db96d56Sopenharmony_citypedef struct PicklerObject {
6307db96d56Sopenharmony_ci    PyObject_HEAD
6317db96d56Sopenharmony_ci    PyMemoTable *memo;          /* Memo table, keep track of the seen
6327db96d56Sopenharmony_ci                                   objects to support self-referential objects
6337db96d56Sopenharmony_ci                                   pickling. */
6347db96d56Sopenharmony_ci    PyObject *pers_func;        /* persistent_id() method, can be NULL */
6357db96d56Sopenharmony_ci    PyObject *pers_func_self;   /* borrowed reference to self if pers_func
6367db96d56Sopenharmony_ci                                   is an unbound method, NULL otherwise */
6377db96d56Sopenharmony_ci    PyObject *dispatch_table;   /* private dispatch_table, can be NULL */
6387db96d56Sopenharmony_ci    PyObject *reducer_override; /* hook for invoking user-defined callbacks
6397db96d56Sopenharmony_ci                                   instead of save_global when pickling
6407db96d56Sopenharmony_ci                                   functions and classes*/
6417db96d56Sopenharmony_ci
6427db96d56Sopenharmony_ci    PyObject *write;            /* write() method of the output stream. */
6437db96d56Sopenharmony_ci    PyObject *output_buffer;    /* Write into a local bytearray buffer before
6447db96d56Sopenharmony_ci                                   flushing to the stream. */
6457db96d56Sopenharmony_ci    Py_ssize_t output_len;      /* Length of output_buffer. */
6467db96d56Sopenharmony_ci    Py_ssize_t max_output_len;  /* Allocation size of output_buffer. */
6477db96d56Sopenharmony_ci    int proto;                  /* Pickle protocol number, >= 0 */
6487db96d56Sopenharmony_ci    int bin;                    /* Boolean, true if proto > 0 */
6497db96d56Sopenharmony_ci    int framing;                /* True when framing is enabled, proto >= 4 */
6507db96d56Sopenharmony_ci    Py_ssize_t frame_start;     /* Position in output_buffer where the
6517db96d56Sopenharmony_ci                                   current frame begins. -1 if there
6527db96d56Sopenharmony_ci                                   is no frame currently open. */
6537db96d56Sopenharmony_ci
6547db96d56Sopenharmony_ci    Py_ssize_t buf_size;        /* Size of the current buffered pickle data */
6557db96d56Sopenharmony_ci    int fast;                   /* Enable fast mode if set to a true value.
6567db96d56Sopenharmony_ci                                   The fast mode disable the usage of memo,
6577db96d56Sopenharmony_ci                                   therefore speeding the pickling process by
6587db96d56Sopenharmony_ci                                   not generating superfluous PUT opcodes. It
6597db96d56Sopenharmony_ci                                   should not be used if with self-referential
6607db96d56Sopenharmony_ci                                   objects. */
6617db96d56Sopenharmony_ci    int fast_nesting;
6627db96d56Sopenharmony_ci    int fix_imports;            /* Indicate whether Pickler should fix
6637db96d56Sopenharmony_ci                                   the name of globals for Python 2.x. */
6647db96d56Sopenharmony_ci    PyObject *fast_memo;
6657db96d56Sopenharmony_ci    PyObject *buffer_callback;  /* Callback for out-of-band buffers, or NULL */
6667db96d56Sopenharmony_ci} PicklerObject;
6677db96d56Sopenharmony_ci
6687db96d56Sopenharmony_citypedef struct UnpicklerObject {
6697db96d56Sopenharmony_ci    PyObject_HEAD
6707db96d56Sopenharmony_ci    Pdata *stack;               /* Pickle data stack, store unpickled objects. */
6717db96d56Sopenharmony_ci
6727db96d56Sopenharmony_ci    /* The unpickler memo is just an array of PyObject *s. Using a dict
6737db96d56Sopenharmony_ci       is unnecessary, since the keys are contiguous ints. */
6747db96d56Sopenharmony_ci    PyObject **memo;
6757db96d56Sopenharmony_ci    size_t memo_size;       /* Capacity of the memo array */
6767db96d56Sopenharmony_ci    size_t memo_len;        /* Number of objects in the memo */
6777db96d56Sopenharmony_ci
6787db96d56Sopenharmony_ci    PyObject *pers_func;        /* persistent_load() method, can be NULL. */
6797db96d56Sopenharmony_ci    PyObject *pers_func_self;   /* borrowed reference to self if pers_func
6807db96d56Sopenharmony_ci                                   is an unbound method, NULL otherwise */
6817db96d56Sopenharmony_ci
6827db96d56Sopenharmony_ci    Py_buffer buffer;
6837db96d56Sopenharmony_ci    char *input_buffer;
6847db96d56Sopenharmony_ci    char *input_line;
6857db96d56Sopenharmony_ci    Py_ssize_t input_len;
6867db96d56Sopenharmony_ci    Py_ssize_t next_read_idx;
6877db96d56Sopenharmony_ci    Py_ssize_t prefetched_idx;  /* index of first prefetched byte */
6887db96d56Sopenharmony_ci
6897db96d56Sopenharmony_ci    PyObject *read;             /* read() method of the input stream. */
6907db96d56Sopenharmony_ci    PyObject *readinto;         /* readinto() method of the input stream. */
6917db96d56Sopenharmony_ci    PyObject *readline;         /* readline() method of the input stream. */
6927db96d56Sopenharmony_ci    PyObject *peek;             /* peek() method of the input stream, or NULL */
6937db96d56Sopenharmony_ci    PyObject *buffers;          /* iterable of out-of-band buffers, or NULL */
6947db96d56Sopenharmony_ci
6957db96d56Sopenharmony_ci    char *encoding;             /* Name of the encoding to be used for
6967db96d56Sopenharmony_ci                                   decoding strings pickled using Python
6977db96d56Sopenharmony_ci                                   2.x. The default value is "ASCII" */
6987db96d56Sopenharmony_ci    char *errors;               /* Name of errors handling scheme to used when
6997db96d56Sopenharmony_ci                                   decoding strings. The default value is
7007db96d56Sopenharmony_ci                                   "strict". */
7017db96d56Sopenharmony_ci    Py_ssize_t *marks;          /* Mark stack, used for unpickling container
7027db96d56Sopenharmony_ci                                   objects. */
7037db96d56Sopenharmony_ci    Py_ssize_t num_marks;       /* Number of marks in the mark stack. */
7047db96d56Sopenharmony_ci    Py_ssize_t marks_size;      /* Current allocated size of the mark stack. */
7057db96d56Sopenharmony_ci    int proto;                  /* Protocol of the pickle loaded. */
7067db96d56Sopenharmony_ci    int fix_imports;            /* Indicate whether Unpickler should fix
7077db96d56Sopenharmony_ci                                   the name of globals pickled by Python 2.x. */
7087db96d56Sopenharmony_ci} UnpicklerObject;
7097db96d56Sopenharmony_ci
7107db96d56Sopenharmony_citypedef struct {
7117db96d56Sopenharmony_ci    PyObject_HEAD
7127db96d56Sopenharmony_ci    PicklerObject *pickler; /* Pickler whose memo table we're proxying. */
7137db96d56Sopenharmony_ci}  PicklerMemoProxyObject;
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_citypedef struct {
7167db96d56Sopenharmony_ci    PyObject_HEAD
7177db96d56Sopenharmony_ci    UnpicklerObject *unpickler;
7187db96d56Sopenharmony_ci} UnpicklerMemoProxyObject;
7197db96d56Sopenharmony_ci
7207db96d56Sopenharmony_ci/* Forward declarations */
7217db96d56Sopenharmony_cistatic int save(PicklerObject *, PyObject *, int);
7227db96d56Sopenharmony_cistatic int save_reduce(PicklerObject *, PyObject *, PyObject *);
7237db96d56Sopenharmony_cistatic PyTypeObject Pickler_Type;
7247db96d56Sopenharmony_cistatic PyTypeObject Unpickler_Type;
7257db96d56Sopenharmony_ci
7267db96d56Sopenharmony_ci#include "clinic/_pickle.c.h"
7277db96d56Sopenharmony_ci
7287db96d56Sopenharmony_ci/*************************************************************************
7297db96d56Sopenharmony_ci A custom hashtable mapping void* to Python ints. This is used by the pickler
7307db96d56Sopenharmony_ci for memoization. Using a custom hashtable rather than PyDict allows us to skip
7317db96d56Sopenharmony_ci a bunch of unnecessary object creation. This makes a huge performance
7327db96d56Sopenharmony_ci difference. */
7337db96d56Sopenharmony_ci
7347db96d56Sopenharmony_ci#define MT_MINSIZE 8
7357db96d56Sopenharmony_ci#define PERTURB_SHIFT 5
7367db96d56Sopenharmony_ci
7377db96d56Sopenharmony_ci
7387db96d56Sopenharmony_cistatic PyMemoTable *
7397db96d56Sopenharmony_ciPyMemoTable_New(void)
7407db96d56Sopenharmony_ci{
7417db96d56Sopenharmony_ci    PyMemoTable *memo = PyMem_Malloc(sizeof(PyMemoTable));
7427db96d56Sopenharmony_ci    if (memo == NULL) {
7437db96d56Sopenharmony_ci        PyErr_NoMemory();
7447db96d56Sopenharmony_ci        return NULL;
7457db96d56Sopenharmony_ci    }
7467db96d56Sopenharmony_ci
7477db96d56Sopenharmony_ci    memo->mt_used = 0;
7487db96d56Sopenharmony_ci    memo->mt_allocated = MT_MINSIZE;
7497db96d56Sopenharmony_ci    memo->mt_mask = MT_MINSIZE - 1;
7507db96d56Sopenharmony_ci    memo->mt_table = PyMem_Malloc(MT_MINSIZE * sizeof(PyMemoEntry));
7517db96d56Sopenharmony_ci    if (memo->mt_table == NULL) {
7527db96d56Sopenharmony_ci        PyMem_Free(memo);
7537db96d56Sopenharmony_ci        PyErr_NoMemory();
7547db96d56Sopenharmony_ci        return NULL;
7557db96d56Sopenharmony_ci    }
7567db96d56Sopenharmony_ci    memset(memo->mt_table, 0, MT_MINSIZE * sizeof(PyMemoEntry));
7577db96d56Sopenharmony_ci
7587db96d56Sopenharmony_ci    return memo;
7597db96d56Sopenharmony_ci}
7607db96d56Sopenharmony_ci
7617db96d56Sopenharmony_cistatic PyMemoTable *
7627db96d56Sopenharmony_ciPyMemoTable_Copy(PyMemoTable *self)
7637db96d56Sopenharmony_ci{
7647db96d56Sopenharmony_ci    PyMemoTable *new = PyMemoTable_New();
7657db96d56Sopenharmony_ci    if (new == NULL)
7667db96d56Sopenharmony_ci        return NULL;
7677db96d56Sopenharmony_ci
7687db96d56Sopenharmony_ci    new->mt_used = self->mt_used;
7697db96d56Sopenharmony_ci    new->mt_allocated = self->mt_allocated;
7707db96d56Sopenharmony_ci    new->mt_mask = self->mt_mask;
7717db96d56Sopenharmony_ci    /* The table we get from _New() is probably smaller than we wanted.
7727db96d56Sopenharmony_ci       Free it and allocate one that's the right size. */
7737db96d56Sopenharmony_ci    PyMem_Free(new->mt_table);
7747db96d56Sopenharmony_ci    new->mt_table = PyMem_NEW(PyMemoEntry, self->mt_allocated);
7757db96d56Sopenharmony_ci    if (new->mt_table == NULL) {
7767db96d56Sopenharmony_ci        PyMem_Free(new);
7777db96d56Sopenharmony_ci        PyErr_NoMemory();
7787db96d56Sopenharmony_ci        return NULL;
7797db96d56Sopenharmony_ci    }
7807db96d56Sopenharmony_ci    for (size_t i = 0; i < self->mt_allocated; i++) {
7817db96d56Sopenharmony_ci        Py_XINCREF(self->mt_table[i].me_key);
7827db96d56Sopenharmony_ci    }
7837db96d56Sopenharmony_ci    memcpy(new->mt_table, self->mt_table,
7847db96d56Sopenharmony_ci           sizeof(PyMemoEntry) * self->mt_allocated);
7857db96d56Sopenharmony_ci
7867db96d56Sopenharmony_ci    return new;
7877db96d56Sopenharmony_ci}
7887db96d56Sopenharmony_ci
7897db96d56Sopenharmony_cistatic Py_ssize_t
7907db96d56Sopenharmony_ciPyMemoTable_Size(PyMemoTable *self)
7917db96d56Sopenharmony_ci{
7927db96d56Sopenharmony_ci    return self->mt_used;
7937db96d56Sopenharmony_ci}
7947db96d56Sopenharmony_ci
7957db96d56Sopenharmony_cistatic int
7967db96d56Sopenharmony_ciPyMemoTable_Clear(PyMemoTable *self)
7977db96d56Sopenharmony_ci{
7987db96d56Sopenharmony_ci    Py_ssize_t i = self->mt_allocated;
7997db96d56Sopenharmony_ci
8007db96d56Sopenharmony_ci    while (--i >= 0) {
8017db96d56Sopenharmony_ci        Py_XDECREF(self->mt_table[i].me_key);
8027db96d56Sopenharmony_ci    }
8037db96d56Sopenharmony_ci    self->mt_used = 0;
8047db96d56Sopenharmony_ci    memset(self->mt_table, 0, self->mt_allocated * sizeof(PyMemoEntry));
8057db96d56Sopenharmony_ci    return 0;
8067db96d56Sopenharmony_ci}
8077db96d56Sopenharmony_ci
8087db96d56Sopenharmony_cistatic void
8097db96d56Sopenharmony_ciPyMemoTable_Del(PyMemoTable *self)
8107db96d56Sopenharmony_ci{
8117db96d56Sopenharmony_ci    if (self == NULL)
8127db96d56Sopenharmony_ci        return;
8137db96d56Sopenharmony_ci    PyMemoTable_Clear(self);
8147db96d56Sopenharmony_ci
8157db96d56Sopenharmony_ci    PyMem_Free(self->mt_table);
8167db96d56Sopenharmony_ci    PyMem_Free(self);
8177db96d56Sopenharmony_ci}
8187db96d56Sopenharmony_ci
8197db96d56Sopenharmony_ci/* Since entries cannot be deleted from this hashtable, _PyMemoTable_Lookup()
8207db96d56Sopenharmony_ci   can be considerably simpler than dictobject.c's lookdict(). */
8217db96d56Sopenharmony_cistatic PyMemoEntry *
8227db96d56Sopenharmony_ci_PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
8237db96d56Sopenharmony_ci{
8247db96d56Sopenharmony_ci    size_t i;
8257db96d56Sopenharmony_ci    size_t perturb;
8267db96d56Sopenharmony_ci    size_t mask = self->mt_mask;
8277db96d56Sopenharmony_ci    PyMemoEntry *table = self->mt_table;
8287db96d56Sopenharmony_ci    PyMemoEntry *entry;
8297db96d56Sopenharmony_ci    Py_hash_t hash = (Py_hash_t)key >> 3;
8307db96d56Sopenharmony_ci
8317db96d56Sopenharmony_ci    i = hash & mask;
8327db96d56Sopenharmony_ci    entry = &table[i];
8337db96d56Sopenharmony_ci    if (entry->me_key == NULL || entry->me_key == key)
8347db96d56Sopenharmony_ci        return entry;
8357db96d56Sopenharmony_ci
8367db96d56Sopenharmony_ci    for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
8377db96d56Sopenharmony_ci        i = (i << 2) + i + perturb + 1;
8387db96d56Sopenharmony_ci        entry = &table[i & mask];
8397db96d56Sopenharmony_ci        if (entry->me_key == NULL || entry->me_key == key)
8407db96d56Sopenharmony_ci            return entry;
8417db96d56Sopenharmony_ci    }
8427db96d56Sopenharmony_ci    Py_UNREACHABLE();
8437db96d56Sopenharmony_ci}
8447db96d56Sopenharmony_ci
8457db96d56Sopenharmony_ci/* Returns -1 on failure, 0 on success. */
8467db96d56Sopenharmony_cistatic int
8477db96d56Sopenharmony_ci_PyMemoTable_ResizeTable(PyMemoTable *self, size_t min_size)
8487db96d56Sopenharmony_ci{
8497db96d56Sopenharmony_ci    PyMemoEntry *oldtable = NULL;
8507db96d56Sopenharmony_ci    PyMemoEntry *oldentry, *newentry;
8517db96d56Sopenharmony_ci    size_t new_size = MT_MINSIZE;
8527db96d56Sopenharmony_ci    size_t to_process;
8537db96d56Sopenharmony_ci
8547db96d56Sopenharmony_ci    assert(min_size > 0);
8557db96d56Sopenharmony_ci
8567db96d56Sopenharmony_ci    if (min_size > PY_SSIZE_T_MAX) {
8577db96d56Sopenharmony_ci        PyErr_NoMemory();
8587db96d56Sopenharmony_ci        return -1;
8597db96d56Sopenharmony_ci    }
8607db96d56Sopenharmony_ci
8617db96d56Sopenharmony_ci    /* Find the smallest valid table size >= min_size. */
8627db96d56Sopenharmony_ci    while (new_size < min_size) {
8637db96d56Sopenharmony_ci        new_size <<= 1;
8647db96d56Sopenharmony_ci    }
8657db96d56Sopenharmony_ci    /* new_size needs to be a power of two. */
8667db96d56Sopenharmony_ci    assert((new_size & (new_size - 1)) == 0);
8677db96d56Sopenharmony_ci
8687db96d56Sopenharmony_ci    /* Allocate new table. */
8697db96d56Sopenharmony_ci    oldtable = self->mt_table;
8707db96d56Sopenharmony_ci    self->mt_table = PyMem_NEW(PyMemoEntry, new_size);
8717db96d56Sopenharmony_ci    if (self->mt_table == NULL) {
8727db96d56Sopenharmony_ci        self->mt_table = oldtable;
8737db96d56Sopenharmony_ci        PyErr_NoMemory();
8747db96d56Sopenharmony_ci        return -1;
8757db96d56Sopenharmony_ci    }
8767db96d56Sopenharmony_ci    self->mt_allocated = new_size;
8777db96d56Sopenharmony_ci    self->mt_mask = new_size - 1;
8787db96d56Sopenharmony_ci    memset(self->mt_table, 0, sizeof(PyMemoEntry) * new_size);
8797db96d56Sopenharmony_ci
8807db96d56Sopenharmony_ci    /* Copy entries from the old table. */
8817db96d56Sopenharmony_ci    to_process = self->mt_used;
8827db96d56Sopenharmony_ci    for (oldentry = oldtable; to_process > 0; oldentry++) {
8837db96d56Sopenharmony_ci        if (oldentry->me_key != NULL) {
8847db96d56Sopenharmony_ci            to_process--;
8857db96d56Sopenharmony_ci            /* newentry is a pointer to a chunk of the new
8867db96d56Sopenharmony_ci               mt_table, so we're setting the key:value pair
8877db96d56Sopenharmony_ci               in-place. */
8887db96d56Sopenharmony_ci            newentry = _PyMemoTable_Lookup(self, oldentry->me_key);
8897db96d56Sopenharmony_ci            newentry->me_key = oldentry->me_key;
8907db96d56Sopenharmony_ci            newentry->me_value = oldentry->me_value;
8917db96d56Sopenharmony_ci        }
8927db96d56Sopenharmony_ci    }
8937db96d56Sopenharmony_ci
8947db96d56Sopenharmony_ci    /* Deallocate the old table. */
8957db96d56Sopenharmony_ci    PyMem_Free(oldtable);
8967db96d56Sopenharmony_ci    return 0;
8977db96d56Sopenharmony_ci}
8987db96d56Sopenharmony_ci
8997db96d56Sopenharmony_ci/* Returns NULL on failure, a pointer to the value otherwise. */
9007db96d56Sopenharmony_cistatic Py_ssize_t *
9017db96d56Sopenharmony_ciPyMemoTable_Get(PyMemoTable *self, PyObject *key)
9027db96d56Sopenharmony_ci{
9037db96d56Sopenharmony_ci    PyMemoEntry *entry = _PyMemoTable_Lookup(self, key);
9047db96d56Sopenharmony_ci    if (entry->me_key == NULL)
9057db96d56Sopenharmony_ci        return NULL;
9067db96d56Sopenharmony_ci    return &entry->me_value;
9077db96d56Sopenharmony_ci}
9087db96d56Sopenharmony_ci
9097db96d56Sopenharmony_ci/* Returns -1 on failure, 0 on success. */
9107db96d56Sopenharmony_cistatic int
9117db96d56Sopenharmony_ciPyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
9127db96d56Sopenharmony_ci{
9137db96d56Sopenharmony_ci    PyMemoEntry *entry;
9147db96d56Sopenharmony_ci
9157db96d56Sopenharmony_ci    assert(key != NULL);
9167db96d56Sopenharmony_ci
9177db96d56Sopenharmony_ci    entry = _PyMemoTable_Lookup(self, key);
9187db96d56Sopenharmony_ci    if (entry->me_key != NULL) {
9197db96d56Sopenharmony_ci        entry->me_value = value;
9207db96d56Sopenharmony_ci        return 0;
9217db96d56Sopenharmony_ci    }
9227db96d56Sopenharmony_ci    Py_INCREF(key);
9237db96d56Sopenharmony_ci    entry->me_key = key;
9247db96d56Sopenharmony_ci    entry->me_value = value;
9257db96d56Sopenharmony_ci    self->mt_used++;
9267db96d56Sopenharmony_ci
9277db96d56Sopenharmony_ci    /* If we added a key, we can safely resize. Otherwise just return!
9287db96d56Sopenharmony_ci     * If used >= 2/3 size, adjust size. Normally, this quaduples the size.
9297db96d56Sopenharmony_ci     *
9307db96d56Sopenharmony_ci     * Quadrupling the size improves average table sparseness
9317db96d56Sopenharmony_ci     * (reducing collisions) at the cost of some memory. It also halves
9327db96d56Sopenharmony_ci     * the number of expensive resize operations in a growing memo table.
9337db96d56Sopenharmony_ci     *
9347db96d56Sopenharmony_ci     * Very large memo tables (over 50K items) use doubling instead.
9357db96d56Sopenharmony_ci     * This may help applications with severe memory constraints.
9367db96d56Sopenharmony_ci     */
9377db96d56Sopenharmony_ci    if (SIZE_MAX / 3 >= self->mt_used && self->mt_used * 3 < self->mt_allocated * 2) {
9387db96d56Sopenharmony_ci        return 0;
9397db96d56Sopenharmony_ci    }
9407db96d56Sopenharmony_ci    // self->mt_used is always < PY_SSIZE_T_MAX, so this can't overflow.
9417db96d56Sopenharmony_ci    size_t desired_size = (self->mt_used > 50000 ? 2 : 4) * self->mt_used;
9427db96d56Sopenharmony_ci    return _PyMemoTable_ResizeTable(self, desired_size);
9437db96d56Sopenharmony_ci}
9447db96d56Sopenharmony_ci
9457db96d56Sopenharmony_ci#undef MT_MINSIZE
9467db96d56Sopenharmony_ci#undef PERTURB_SHIFT
9477db96d56Sopenharmony_ci
9487db96d56Sopenharmony_ci/*************************************************************************/
9497db96d56Sopenharmony_ci
9507db96d56Sopenharmony_ci
9517db96d56Sopenharmony_cistatic int
9527db96d56Sopenharmony_ci_Pickler_ClearBuffer(PicklerObject *self)
9537db96d56Sopenharmony_ci{
9547db96d56Sopenharmony_ci    Py_XSETREF(self->output_buffer,
9557db96d56Sopenharmony_ci              PyBytes_FromStringAndSize(NULL, self->max_output_len));
9567db96d56Sopenharmony_ci    if (self->output_buffer == NULL)
9577db96d56Sopenharmony_ci        return -1;
9587db96d56Sopenharmony_ci    self->output_len = 0;
9597db96d56Sopenharmony_ci    self->frame_start = -1;
9607db96d56Sopenharmony_ci    return 0;
9617db96d56Sopenharmony_ci}
9627db96d56Sopenharmony_ci
9637db96d56Sopenharmony_cistatic void
9647db96d56Sopenharmony_ci_write_size64(char *out, size_t value)
9657db96d56Sopenharmony_ci{
9667db96d56Sopenharmony_ci    size_t i;
9677db96d56Sopenharmony_ci
9687db96d56Sopenharmony_ci    static_assert(sizeof(size_t) <= 8, "size_t is larger than 64-bit");
9697db96d56Sopenharmony_ci
9707db96d56Sopenharmony_ci    for (i = 0; i < sizeof(size_t); i++) {
9717db96d56Sopenharmony_ci        out[i] = (unsigned char)((value >> (8 * i)) & 0xff);
9727db96d56Sopenharmony_ci    }
9737db96d56Sopenharmony_ci    for (i = sizeof(size_t); i < 8; i++) {
9747db96d56Sopenharmony_ci        out[i] = 0;
9757db96d56Sopenharmony_ci    }
9767db96d56Sopenharmony_ci}
9777db96d56Sopenharmony_ci
9787db96d56Sopenharmony_cistatic int
9797db96d56Sopenharmony_ci_Pickler_CommitFrame(PicklerObject *self)
9807db96d56Sopenharmony_ci{
9817db96d56Sopenharmony_ci    size_t frame_len;
9827db96d56Sopenharmony_ci    char *qdata;
9837db96d56Sopenharmony_ci
9847db96d56Sopenharmony_ci    if (!self->framing || self->frame_start == -1)
9857db96d56Sopenharmony_ci        return 0;
9867db96d56Sopenharmony_ci    frame_len = self->output_len - self->frame_start - FRAME_HEADER_SIZE;
9877db96d56Sopenharmony_ci    qdata = PyBytes_AS_STRING(self->output_buffer) + self->frame_start;
9887db96d56Sopenharmony_ci    if (frame_len >= FRAME_SIZE_MIN) {
9897db96d56Sopenharmony_ci        qdata[0] = FRAME;
9907db96d56Sopenharmony_ci        _write_size64(qdata + 1, frame_len);
9917db96d56Sopenharmony_ci    }
9927db96d56Sopenharmony_ci    else {
9937db96d56Sopenharmony_ci        memmove(qdata, qdata + FRAME_HEADER_SIZE, frame_len);
9947db96d56Sopenharmony_ci        self->output_len -= FRAME_HEADER_SIZE;
9957db96d56Sopenharmony_ci    }
9967db96d56Sopenharmony_ci    self->frame_start = -1;
9977db96d56Sopenharmony_ci    return 0;
9987db96d56Sopenharmony_ci}
9997db96d56Sopenharmony_ci
10007db96d56Sopenharmony_cistatic PyObject *
10017db96d56Sopenharmony_ci_Pickler_GetString(PicklerObject *self)
10027db96d56Sopenharmony_ci{
10037db96d56Sopenharmony_ci    PyObject *output_buffer = self->output_buffer;
10047db96d56Sopenharmony_ci
10057db96d56Sopenharmony_ci    assert(self->output_buffer != NULL);
10067db96d56Sopenharmony_ci
10077db96d56Sopenharmony_ci    if (_Pickler_CommitFrame(self))
10087db96d56Sopenharmony_ci        return NULL;
10097db96d56Sopenharmony_ci
10107db96d56Sopenharmony_ci    self->output_buffer = NULL;
10117db96d56Sopenharmony_ci    /* Resize down to exact size */
10127db96d56Sopenharmony_ci    if (_PyBytes_Resize(&output_buffer, self->output_len) < 0)
10137db96d56Sopenharmony_ci        return NULL;
10147db96d56Sopenharmony_ci    return output_buffer;
10157db96d56Sopenharmony_ci}
10167db96d56Sopenharmony_ci
10177db96d56Sopenharmony_cistatic int
10187db96d56Sopenharmony_ci_Pickler_FlushToFile(PicklerObject *self)
10197db96d56Sopenharmony_ci{
10207db96d56Sopenharmony_ci    PyObject *output, *result;
10217db96d56Sopenharmony_ci
10227db96d56Sopenharmony_ci    assert(self->write != NULL);
10237db96d56Sopenharmony_ci
10247db96d56Sopenharmony_ci    /* This will commit the frame first */
10257db96d56Sopenharmony_ci    output = _Pickler_GetString(self);
10267db96d56Sopenharmony_ci    if (output == NULL)
10277db96d56Sopenharmony_ci        return -1;
10287db96d56Sopenharmony_ci
10297db96d56Sopenharmony_ci    result = _Pickle_FastCall(self->write, output);
10307db96d56Sopenharmony_ci    Py_XDECREF(result);
10317db96d56Sopenharmony_ci    return (result == NULL) ? -1 : 0;
10327db96d56Sopenharmony_ci}
10337db96d56Sopenharmony_ci
10347db96d56Sopenharmony_cistatic int
10357db96d56Sopenharmony_ci_Pickler_OpcodeBoundary(PicklerObject *self)
10367db96d56Sopenharmony_ci{
10377db96d56Sopenharmony_ci    Py_ssize_t frame_len;
10387db96d56Sopenharmony_ci
10397db96d56Sopenharmony_ci    if (!self->framing || self->frame_start == -1) {
10407db96d56Sopenharmony_ci        return 0;
10417db96d56Sopenharmony_ci    }
10427db96d56Sopenharmony_ci    frame_len = self->output_len - self->frame_start - FRAME_HEADER_SIZE;
10437db96d56Sopenharmony_ci    if (frame_len >= FRAME_SIZE_TARGET) {
10447db96d56Sopenharmony_ci        if(_Pickler_CommitFrame(self)) {
10457db96d56Sopenharmony_ci            return -1;
10467db96d56Sopenharmony_ci        }
10477db96d56Sopenharmony_ci        /* Flush the content of the committed frame to the underlying
10487db96d56Sopenharmony_ci         * file and reuse the pickler buffer for the next frame so as
10497db96d56Sopenharmony_ci         * to limit memory usage when dumping large complex objects to
10507db96d56Sopenharmony_ci         * a file.
10517db96d56Sopenharmony_ci         *
10527db96d56Sopenharmony_ci         * self->write is NULL when called via dumps.
10537db96d56Sopenharmony_ci         */
10547db96d56Sopenharmony_ci        if (self->write != NULL) {
10557db96d56Sopenharmony_ci            if (_Pickler_FlushToFile(self) < 0) {
10567db96d56Sopenharmony_ci                return -1;
10577db96d56Sopenharmony_ci            }
10587db96d56Sopenharmony_ci            if (_Pickler_ClearBuffer(self) < 0) {
10597db96d56Sopenharmony_ci                return -1;
10607db96d56Sopenharmony_ci            }
10617db96d56Sopenharmony_ci        }
10627db96d56Sopenharmony_ci    }
10637db96d56Sopenharmony_ci    return 0;
10647db96d56Sopenharmony_ci}
10657db96d56Sopenharmony_ci
10667db96d56Sopenharmony_cistatic Py_ssize_t
10677db96d56Sopenharmony_ci_Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t data_len)
10687db96d56Sopenharmony_ci{
10697db96d56Sopenharmony_ci    Py_ssize_t i, n, required;
10707db96d56Sopenharmony_ci    char *buffer;
10717db96d56Sopenharmony_ci    int need_new_frame;
10727db96d56Sopenharmony_ci
10737db96d56Sopenharmony_ci    assert(s != NULL);
10747db96d56Sopenharmony_ci    need_new_frame = (self->framing && self->frame_start == -1);
10757db96d56Sopenharmony_ci
10767db96d56Sopenharmony_ci    if (need_new_frame)
10777db96d56Sopenharmony_ci        n = data_len + FRAME_HEADER_SIZE;
10787db96d56Sopenharmony_ci    else
10797db96d56Sopenharmony_ci        n = data_len;
10807db96d56Sopenharmony_ci
10817db96d56Sopenharmony_ci    required = self->output_len + n;
10827db96d56Sopenharmony_ci    if (required > self->max_output_len) {
10837db96d56Sopenharmony_ci        /* Make place in buffer for the pickle chunk */
10847db96d56Sopenharmony_ci        if (self->output_len >= PY_SSIZE_T_MAX / 2 - n) {
10857db96d56Sopenharmony_ci            PyErr_NoMemory();
10867db96d56Sopenharmony_ci            return -1;
10877db96d56Sopenharmony_ci        }
10887db96d56Sopenharmony_ci        self->max_output_len = (self->output_len + n) / 2 * 3;
10897db96d56Sopenharmony_ci        if (_PyBytes_Resize(&self->output_buffer, self->max_output_len) < 0)
10907db96d56Sopenharmony_ci            return -1;
10917db96d56Sopenharmony_ci    }
10927db96d56Sopenharmony_ci    buffer = PyBytes_AS_STRING(self->output_buffer);
10937db96d56Sopenharmony_ci    if (need_new_frame) {
10947db96d56Sopenharmony_ci        /* Setup new frame */
10957db96d56Sopenharmony_ci        Py_ssize_t frame_start = self->output_len;
10967db96d56Sopenharmony_ci        self->frame_start = frame_start;
10977db96d56Sopenharmony_ci        for (i = 0; i < FRAME_HEADER_SIZE; i++) {
10987db96d56Sopenharmony_ci            /* Write an invalid value, for debugging */
10997db96d56Sopenharmony_ci            buffer[frame_start + i] = 0xFE;
11007db96d56Sopenharmony_ci        }
11017db96d56Sopenharmony_ci        self->output_len += FRAME_HEADER_SIZE;
11027db96d56Sopenharmony_ci    }
11037db96d56Sopenharmony_ci    if (data_len < 8) {
11047db96d56Sopenharmony_ci        /* This is faster than memcpy when the string is short. */
11057db96d56Sopenharmony_ci        for (i = 0; i < data_len; i++) {
11067db96d56Sopenharmony_ci            buffer[self->output_len + i] = s[i];
11077db96d56Sopenharmony_ci        }
11087db96d56Sopenharmony_ci    }
11097db96d56Sopenharmony_ci    else {
11107db96d56Sopenharmony_ci        memcpy(buffer + self->output_len, s, data_len);
11117db96d56Sopenharmony_ci    }
11127db96d56Sopenharmony_ci    self->output_len += data_len;
11137db96d56Sopenharmony_ci    return data_len;
11147db96d56Sopenharmony_ci}
11157db96d56Sopenharmony_ci
11167db96d56Sopenharmony_cistatic PicklerObject *
11177db96d56Sopenharmony_ci_Pickler_New(void)
11187db96d56Sopenharmony_ci{
11197db96d56Sopenharmony_ci    PicklerObject *self;
11207db96d56Sopenharmony_ci
11217db96d56Sopenharmony_ci    self = PyObject_GC_New(PicklerObject, &Pickler_Type);
11227db96d56Sopenharmony_ci    if (self == NULL)
11237db96d56Sopenharmony_ci        return NULL;
11247db96d56Sopenharmony_ci
11257db96d56Sopenharmony_ci    self->pers_func = NULL;
11267db96d56Sopenharmony_ci    self->dispatch_table = NULL;
11277db96d56Sopenharmony_ci    self->buffer_callback = NULL;
11287db96d56Sopenharmony_ci    self->write = NULL;
11297db96d56Sopenharmony_ci    self->proto = 0;
11307db96d56Sopenharmony_ci    self->bin = 0;
11317db96d56Sopenharmony_ci    self->framing = 0;
11327db96d56Sopenharmony_ci    self->frame_start = -1;
11337db96d56Sopenharmony_ci    self->fast = 0;
11347db96d56Sopenharmony_ci    self->fast_nesting = 0;
11357db96d56Sopenharmony_ci    self->fix_imports = 0;
11367db96d56Sopenharmony_ci    self->fast_memo = NULL;
11377db96d56Sopenharmony_ci    self->max_output_len = WRITE_BUF_SIZE;
11387db96d56Sopenharmony_ci    self->output_len = 0;
11397db96d56Sopenharmony_ci    self->reducer_override = NULL;
11407db96d56Sopenharmony_ci
11417db96d56Sopenharmony_ci    self->memo = PyMemoTable_New();
11427db96d56Sopenharmony_ci    self->output_buffer = PyBytes_FromStringAndSize(NULL,
11437db96d56Sopenharmony_ci                                                    self->max_output_len);
11447db96d56Sopenharmony_ci
11457db96d56Sopenharmony_ci    if (self->memo == NULL || self->output_buffer == NULL) {
11467db96d56Sopenharmony_ci        Py_DECREF(self);
11477db96d56Sopenharmony_ci        return NULL;
11487db96d56Sopenharmony_ci    }
11497db96d56Sopenharmony_ci
11507db96d56Sopenharmony_ci    PyObject_GC_Track(self);
11517db96d56Sopenharmony_ci    return self;
11527db96d56Sopenharmony_ci}
11537db96d56Sopenharmony_ci
11547db96d56Sopenharmony_cistatic int
11557db96d56Sopenharmony_ci_Pickler_SetProtocol(PicklerObject *self, PyObject *protocol, int fix_imports)
11567db96d56Sopenharmony_ci{
11577db96d56Sopenharmony_ci    long proto;
11587db96d56Sopenharmony_ci
11597db96d56Sopenharmony_ci    if (protocol == Py_None) {
11607db96d56Sopenharmony_ci        proto = DEFAULT_PROTOCOL;
11617db96d56Sopenharmony_ci    }
11627db96d56Sopenharmony_ci    else {
11637db96d56Sopenharmony_ci        proto = PyLong_AsLong(protocol);
11647db96d56Sopenharmony_ci        if (proto < 0) {
11657db96d56Sopenharmony_ci            if (proto == -1 && PyErr_Occurred())
11667db96d56Sopenharmony_ci                return -1;
11677db96d56Sopenharmony_ci            proto = HIGHEST_PROTOCOL;
11687db96d56Sopenharmony_ci        }
11697db96d56Sopenharmony_ci        else if (proto > HIGHEST_PROTOCOL) {
11707db96d56Sopenharmony_ci            PyErr_Format(PyExc_ValueError, "pickle protocol must be <= %d",
11717db96d56Sopenharmony_ci                         HIGHEST_PROTOCOL);
11727db96d56Sopenharmony_ci            return -1;
11737db96d56Sopenharmony_ci        }
11747db96d56Sopenharmony_ci    }
11757db96d56Sopenharmony_ci    self->proto = (int)proto;
11767db96d56Sopenharmony_ci    self->bin = proto > 0;
11777db96d56Sopenharmony_ci    self->fix_imports = fix_imports && proto < 3;
11787db96d56Sopenharmony_ci    return 0;
11797db96d56Sopenharmony_ci}
11807db96d56Sopenharmony_ci
11817db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. This may
11827db96d56Sopenharmony_ci   be called once on a freshly created Pickler. */
11837db96d56Sopenharmony_cistatic int
11847db96d56Sopenharmony_ci_Pickler_SetOutputStream(PicklerObject *self, PyObject *file)
11857db96d56Sopenharmony_ci{
11867db96d56Sopenharmony_ci    assert(file != NULL);
11877db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(file, &_Py_ID(write), &self->write) < 0) {
11887db96d56Sopenharmony_ci        return -1;
11897db96d56Sopenharmony_ci    }
11907db96d56Sopenharmony_ci    if (self->write == NULL) {
11917db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError,
11927db96d56Sopenharmony_ci                        "file must have a 'write' attribute");
11937db96d56Sopenharmony_ci        return -1;
11947db96d56Sopenharmony_ci    }
11957db96d56Sopenharmony_ci
11967db96d56Sopenharmony_ci    return 0;
11977db96d56Sopenharmony_ci}
11987db96d56Sopenharmony_ci
11997db96d56Sopenharmony_cistatic int
12007db96d56Sopenharmony_ci_Pickler_SetBufferCallback(PicklerObject *self, PyObject *buffer_callback)
12017db96d56Sopenharmony_ci{
12027db96d56Sopenharmony_ci    if (buffer_callback == Py_None) {
12037db96d56Sopenharmony_ci        buffer_callback = NULL;
12047db96d56Sopenharmony_ci    }
12057db96d56Sopenharmony_ci    if (buffer_callback != NULL && self->proto < 5) {
12067db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError,
12077db96d56Sopenharmony_ci                        "buffer_callback needs protocol >= 5");
12087db96d56Sopenharmony_ci        return -1;
12097db96d56Sopenharmony_ci    }
12107db96d56Sopenharmony_ci
12117db96d56Sopenharmony_ci    Py_XINCREF(buffer_callback);
12127db96d56Sopenharmony_ci    self->buffer_callback = buffer_callback;
12137db96d56Sopenharmony_ci    return 0;
12147db96d56Sopenharmony_ci}
12157db96d56Sopenharmony_ci
12167db96d56Sopenharmony_ci/* Returns the size of the input on success, -1 on failure. This takes its
12177db96d56Sopenharmony_ci   own reference to `input`. */
12187db96d56Sopenharmony_cistatic Py_ssize_t
12197db96d56Sopenharmony_ci_Unpickler_SetStringInput(UnpicklerObject *self, PyObject *input)
12207db96d56Sopenharmony_ci{
12217db96d56Sopenharmony_ci    if (self->buffer.buf != NULL)
12227db96d56Sopenharmony_ci        PyBuffer_Release(&self->buffer);
12237db96d56Sopenharmony_ci    if (PyObject_GetBuffer(input, &self->buffer, PyBUF_CONTIG_RO) < 0)
12247db96d56Sopenharmony_ci        return -1;
12257db96d56Sopenharmony_ci    self->input_buffer = self->buffer.buf;
12267db96d56Sopenharmony_ci    self->input_len = self->buffer.len;
12277db96d56Sopenharmony_ci    self->next_read_idx = 0;
12287db96d56Sopenharmony_ci    self->prefetched_idx = self->input_len;
12297db96d56Sopenharmony_ci    return self->input_len;
12307db96d56Sopenharmony_ci}
12317db96d56Sopenharmony_ci
12327db96d56Sopenharmony_cistatic int
12337db96d56Sopenharmony_cibad_readline(void)
12347db96d56Sopenharmony_ci{
12357db96d56Sopenharmony_ci    PickleState *st = _Pickle_GetGlobalState();
12367db96d56Sopenharmony_ci    PyErr_SetString(st->UnpicklingError, "pickle data was truncated");
12377db96d56Sopenharmony_ci    return -1;
12387db96d56Sopenharmony_ci}
12397db96d56Sopenharmony_ci
12407db96d56Sopenharmony_ci/* Skip any consumed data that was only prefetched using peek() */
12417db96d56Sopenharmony_cistatic int
12427db96d56Sopenharmony_ci_Unpickler_SkipConsumed(UnpicklerObject *self)
12437db96d56Sopenharmony_ci{
12447db96d56Sopenharmony_ci    Py_ssize_t consumed;
12457db96d56Sopenharmony_ci    PyObject *r;
12467db96d56Sopenharmony_ci
12477db96d56Sopenharmony_ci    consumed = self->next_read_idx - self->prefetched_idx;
12487db96d56Sopenharmony_ci    if (consumed <= 0)
12497db96d56Sopenharmony_ci        return 0;
12507db96d56Sopenharmony_ci
12517db96d56Sopenharmony_ci    assert(self->peek);  /* otherwise we did something wrong */
12527db96d56Sopenharmony_ci    /* This makes a useless copy... */
12537db96d56Sopenharmony_ci    r = PyObject_CallFunction(self->read, "n", consumed);
12547db96d56Sopenharmony_ci    if (r == NULL)
12557db96d56Sopenharmony_ci        return -1;
12567db96d56Sopenharmony_ci    Py_DECREF(r);
12577db96d56Sopenharmony_ci
12587db96d56Sopenharmony_ci    self->prefetched_idx = self->next_read_idx;
12597db96d56Sopenharmony_ci    return 0;
12607db96d56Sopenharmony_ci}
12617db96d56Sopenharmony_ci
12627db96d56Sopenharmony_cistatic const Py_ssize_t READ_WHOLE_LINE = -1;
12637db96d56Sopenharmony_ci
12647db96d56Sopenharmony_ci/* If reading from a file, we need to only pull the bytes we need, since there
12657db96d56Sopenharmony_ci   may be multiple pickle objects arranged contiguously in the same input
12667db96d56Sopenharmony_ci   buffer.
12677db96d56Sopenharmony_ci
12687db96d56Sopenharmony_ci   If `n` is READ_WHOLE_LINE, read a whole line. Otherwise, read up to `n`
12697db96d56Sopenharmony_ci   bytes from the input stream/buffer.
12707db96d56Sopenharmony_ci
12717db96d56Sopenharmony_ci   Update the unpickler's input buffer with the newly-read data. Returns -1 on
12727db96d56Sopenharmony_ci   failure; on success, returns the number of bytes read from the file.
12737db96d56Sopenharmony_ci
12747db96d56Sopenharmony_ci   On success, self->input_len will be 0; this is intentional so that when
12757db96d56Sopenharmony_ci   unpickling from a file, the "we've run out of data" code paths will trigger,
12767db96d56Sopenharmony_ci   causing the Unpickler to go back to the file for more data. Use the returned
12777db96d56Sopenharmony_ci   size to tell you how much data you can process. */
12787db96d56Sopenharmony_cistatic Py_ssize_t
12797db96d56Sopenharmony_ci_Unpickler_ReadFromFile(UnpicklerObject *self, Py_ssize_t n)
12807db96d56Sopenharmony_ci{
12817db96d56Sopenharmony_ci    PyObject *data;
12827db96d56Sopenharmony_ci    Py_ssize_t read_size;
12837db96d56Sopenharmony_ci
12847db96d56Sopenharmony_ci    assert(self->read != NULL);
12857db96d56Sopenharmony_ci
12867db96d56Sopenharmony_ci    if (_Unpickler_SkipConsumed(self) < 0)
12877db96d56Sopenharmony_ci        return -1;
12887db96d56Sopenharmony_ci
12897db96d56Sopenharmony_ci    if (n == READ_WHOLE_LINE) {
12907db96d56Sopenharmony_ci        data = PyObject_CallNoArgs(self->readline);
12917db96d56Sopenharmony_ci    }
12927db96d56Sopenharmony_ci    else {
12937db96d56Sopenharmony_ci        PyObject *len;
12947db96d56Sopenharmony_ci        /* Prefetch some data without advancing the file pointer, if possible */
12957db96d56Sopenharmony_ci        if (self->peek && n < PREFETCH) {
12967db96d56Sopenharmony_ci            len = PyLong_FromSsize_t(PREFETCH);
12977db96d56Sopenharmony_ci            if (len == NULL)
12987db96d56Sopenharmony_ci                return -1;
12997db96d56Sopenharmony_ci            data = _Pickle_FastCall(self->peek, len);
13007db96d56Sopenharmony_ci            if (data == NULL) {
13017db96d56Sopenharmony_ci                if (!PyErr_ExceptionMatches(PyExc_NotImplementedError))
13027db96d56Sopenharmony_ci                    return -1;
13037db96d56Sopenharmony_ci                /* peek() is probably not supported by the given file object */
13047db96d56Sopenharmony_ci                PyErr_Clear();
13057db96d56Sopenharmony_ci                Py_CLEAR(self->peek);
13067db96d56Sopenharmony_ci            }
13077db96d56Sopenharmony_ci            else {
13087db96d56Sopenharmony_ci                read_size = _Unpickler_SetStringInput(self, data);
13097db96d56Sopenharmony_ci                Py_DECREF(data);
13107db96d56Sopenharmony_ci                self->prefetched_idx = 0;
13117db96d56Sopenharmony_ci                if (n <= read_size)
13127db96d56Sopenharmony_ci                    return n;
13137db96d56Sopenharmony_ci            }
13147db96d56Sopenharmony_ci        }
13157db96d56Sopenharmony_ci        len = PyLong_FromSsize_t(n);
13167db96d56Sopenharmony_ci        if (len == NULL)
13177db96d56Sopenharmony_ci            return -1;
13187db96d56Sopenharmony_ci        data = _Pickle_FastCall(self->read, len);
13197db96d56Sopenharmony_ci    }
13207db96d56Sopenharmony_ci    if (data == NULL)
13217db96d56Sopenharmony_ci        return -1;
13227db96d56Sopenharmony_ci
13237db96d56Sopenharmony_ci    read_size = _Unpickler_SetStringInput(self, data);
13247db96d56Sopenharmony_ci    Py_DECREF(data);
13257db96d56Sopenharmony_ci    return read_size;
13267db96d56Sopenharmony_ci}
13277db96d56Sopenharmony_ci
13287db96d56Sopenharmony_ci/* Don't call it directly: use _Unpickler_Read() */
13297db96d56Sopenharmony_cistatic Py_ssize_t
13307db96d56Sopenharmony_ci_Unpickler_ReadImpl(UnpicklerObject *self, char **s, Py_ssize_t n)
13317db96d56Sopenharmony_ci{
13327db96d56Sopenharmony_ci    Py_ssize_t num_read;
13337db96d56Sopenharmony_ci
13347db96d56Sopenharmony_ci    *s = NULL;
13357db96d56Sopenharmony_ci    if (self->next_read_idx > PY_SSIZE_T_MAX - n) {
13367db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
13377db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError,
13387db96d56Sopenharmony_ci                        "read would overflow (invalid bytecode)");
13397db96d56Sopenharmony_ci        return -1;
13407db96d56Sopenharmony_ci    }
13417db96d56Sopenharmony_ci
13427db96d56Sopenharmony_ci    /* This case is handled by the _Unpickler_Read() macro for efficiency */
13437db96d56Sopenharmony_ci    assert(self->next_read_idx + n > self->input_len);
13447db96d56Sopenharmony_ci
13457db96d56Sopenharmony_ci    if (!self->read)
13467db96d56Sopenharmony_ci        return bad_readline();
13477db96d56Sopenharmony_ci
13487db96d56Sopenharmony_ci    /* Extend the buffer to satisfy desired size */
13497db96d56Sopenharmony_ci    num_read = _Unpickler_ReadFromFile(self, n);
13507db96d56Sopenharmony_ci    if (num_read < 0)
13517db96d56Sopenharmony_ci        return -1;
13527db96d56Sopenharmony_ci    if (num_read < n)
13537db96d56Sopenharmony_ci        return bad_readline();
13547db96d56Sopenharmony_ci    *s = self->input_buffer;
13557db96d56Sopenharmony_ci    self->next_read_idx = n;
13567db96d56Sopenharmony_ci    return n;
13577db96d56Sopenharmony_ci}
13587db96d56Sopenharmony_ci
13597db96d56Sopenharmony_ci/* Read `n` bytes from the unpickler's data source, storing the result in `buf`.
13607db96d56Sopenharmony_ci *
13617db96d56Sopenharmony_ci * This should only be used for non-small data reads where potentially
13627db96d56Sopenharmony_ci * avoiding a copy is beneficial.  This method does not try to prefetch
13637db96d56Sopenharmony_ci * more data into the input buffer.
13647db96d56Sopenharmony_ci *
13657db96d56Sopenharmony_ci * _Unpickler_Read() is recommended in most cases.
13667db96d56Sopenharmony_ci */
13677db96d56Sopenharmony_cistatic Py_ssize_t
13687db96d56Sopenharmony_ci_Unpickler_ReadInto(UnpicklerObject *self, char *buf, Py_ssize_t n)
13697db96d56Sopenharmony_ci{
13707db96d56Sopenharmony_ci    assert(n != READ_WHOLE_LINE);
13717db96d56Sopenharmony_ci
13727db96d56Sopenharmony_ci    /* Read from available buffer data, if any */
13737db96d56Sopenharmony_ci    Py_ssize_t in_buffer = self->input_len - self->next_read_idx;
13747db96d56Sopenharmony_ci    if (in_buffer > 0) {
13757db96d56Sopenharmony_ci        Py_ssize_t to_read = Py_MIN(in_buffer, n);
13767db96d56Sopenharmony_ci        memcpy(buf, self->input_buffer + self->next_read_idx, to_read);
13777db96d56Sopenharmony_ci        self->next_read_idx += to_read;
13787db96d56Sopenharmony_ci        buf += to_read;
13797db96d56Sopenharmony_ci        n -= to_read;
13807db96d56Sopenharmony_ci        if (n == 0) {
13817db96d56Sopenharmony_ci            /* Entire read was satisfied from buffer */
13827db96d56Sopenharmony_ci            return n;
13837db96d56Sopenharmony_ci        }
13847db96d56Sopenharmony_ci    }
13857db96d56Sopenharmony_ci
13867db96d56Sopenharmony_ci    /* Read from file */
13877db96d56Sopenharmony_ci    if (!self->read) {
13887db96d56Sopenharmony_ci        /* We're unpickling memory, this means the input is truncated */
13897db96d56Sopenharmony_ci        return bad_readline();
13907db96d56Sopenharmony_ci    }
13917db96d56Sopenharmony_ci    if (_Unpickler_SkipConsumed(self) < 0) {
13927db96d56Sopenharmony_ci        return -1;
13937db96d56Sopenharmony_ci    }
13947db96d56Sopenharmony_ci
13957db96d56Sopenharmony_ci    if (!self->readinto) {
13967db96d56Sopenharmony_ci        /* readinto() not supported on file-like object, fall back to read()
13977db96d56Sopenharmony_ci         * and copy into destination buffer (bpo-39681) */
13987db96d56Sopenharmony_ci        PyObject* len = PyLong_FromSsize_t(n);
13997db96d56Sopenharmony_ci        if (len == NULL) {
14007db96d56Sopenharmony_ci            return -1;
14017db96d56Sopenharmony_ci        }
14027db96d56Sopenharmony_ci        PyObject* data = _Pickle_FastCall(self->read, len);
14037db96d56Sopenharmony_ci        if (data == NULL) {
14047db96d56Sopenharmony_ci            return -1;
14057db96d56Sopenharmony_ci        }
14067db96d56Sopenharmony_ci        if (!PyBytes_Check(data)) {
14077db96d56Sopenharmony_ci            PyErr_Format(PyExc_ValueError,
14087db96d56Sopenharmony_ci                         "read() returned non-bytes object (%R)",
14097db96d56Sopenharmony_ci                         Py_TYPE(data));
14107db96d56Sopenharmony_ci            Py_DECREF(data);
14117db96d56Sopenharmony_ci            return -1;
14127db96d56Sopenharmony_ci        }
14137db96d56Sopenharmony_ci        Py_ssize_t read_size = PyBytes_GET_SIZE(data);
14147db96d56Sopenharmony_ci        if (read_size < n) {
14157db96d56Sopenharmony_ci            Py_DECREF(data);
14167db96d56Sopenharmony_ci            return bad_readline();
14177db96d56Sopenharmony_ci        }
14187db96d56Sopenharmony_ci        memcpy(buf, PyBytes_AS_STRING(data), n);
14197db96d56Sopenharmony_ci        Py_DECREF(data);
14207db96d56Sopenharmony_ci        return n;
14217db96d56Sopenharmony_ci    }
14227db96d56Sopenharmony_ci
14237db96d56Sopenharmony_ci    /* Call readinto() into user buffer */
14247db96d56Sopenharmony_ci    PyObject *buf_obj = PyMemoryView_FromMemory(buf, n, PyBUF_WRITE);
14257db96d56Sopenharmony_ci    if (buf_obj == NULL) {
14267db96d56Sopenharmony_ci        return -1;
14277db96d56Sopenharmony_ci    }
14287db96d56Sopenharmony_ci    PyObject *read_size_obj = _Pickle_FastCall(self->readinto, buf_obj);
14297db96d56Sopenharmony_ci    if (read_size_obj == NULL) {
14307db96d56Sopenharmony_ci        return -1;
14317db96d56Sopenharmony_ci    }
14327db96d56Sopenharmony_ci    Py_ssize_t read_size = PyLong_AsSsize_t(read_size_obj);
14337db96d56Sopenharmony_ci    Py_DECREF(read_size_obj);
14347db96d56Sopenharmony_ci
14357db96d56Sopenharmony_ci    if (read_size < 0) {
14367db96d56Sopenharmony_ci        if (!PyErr_Occurred()) {
14377db96d56Sopenharmony_ci            PyErr_SetString(PyExc_ValueError,
14387db96d56Sopenharmony_ci                            "readinto() returned negative size");
14397db96d56Sopenharmony_ci        }
14407db96d56Sopenharmony_ci        return -1;
14417db96d56Sopenharmony_ci    }
14427db96d56Sopenharmony_ci    if (read_size < n) {
14437db96d56Sopenharmony_ci        return bad_readline();
14447db96d56Sopenharmony_ci    }
14457db96d56Sopenharmony_ci    return n;
14467db96d56Sopenharmony_ci}
14477db96d56Sopenharmony_ci
14487db96d56Sopenharmony_ci/* Read `n` bytes from the unpickler's data source, storing the result in `*s`.
14497db96d56Sopenharmony_ci
14507db96d56Sopenharmony_ci   This should be used for all data reads, rather than accessing the unpickler's
14517db96d56Sopenharmony_ci   input buffer directly. This method deals correctly with reading from input
14527db96d56Sopenharmony_ci   streams, which the input buffer doesn't deal with.
14537db96d56Sopenharmony_ci
14547db96d56Sopenharmony_ci   Note that when reading from a file-like object, self->next_read_idx won't
14557db96d56Sopenharmony_ci   be updated (it should remain at 0 for the entire unpickling process). You
14567db96d56Sopenharmony_ci   should use this function's return value to know how many bytes you can
14577db96d56Sopenharmony_ci   consume.
14587db96d56Sopenharmony_ci
14597db96d56Sopenharmony_ci   Returns -1 (with an exception set) on failure. On success, return the
14607db96d56Sopenharmony_ci   number of chars read. */
14617db96d56Sopenharmony_ci#define _Unpickler_Read(self, s, n) \
14627db96d56Sopenharmony_ci    (((n) <= (self)->input_len - (self)->next_read_idx)      \
14637db96d56Sopenharmony_ci     ? (*(s) = (self)->input_buffer + (self)->next_read_idx, \
14647db96d56Sopenharmony_ci        (self)->next_read_idx += (n),                        \
14657db96d56Sopenharmony_ci        (n))                                                 \
14667db96d56Sopenharmony_ci     : _Unpickler_ReadImpl(self, (s), (n)))
14677db96d56Sopenharmony_ci
14687db96d56Sopenharmony_cistatic Py_ssize_t
14697db96d56Sopenharmony_ci_Unpickler_CopyLine(UnpicklerObject *self, char *line, Py_ssize_t len,
14707db96d56Sopenharmony_ci                    char **result)
14717db96d56Sopenharmony_ci{
14727db96d56Sopenharmony_ci    char *input_line = PyMem_Realloc(self->input_line, len + 1);
14737db96d56Sopenharmony_ci    if (input_line == NULL) {
14747db96d56Sopenharmony_ci        PyErr_NoMemory();
14757db96d56Sopenharmony_ci        return -1;
14767db96d56Sopenharmony_ci    }
14777db96d56Sopenharmony_ci
14787db96d56Sopenharmony_ci    memcpy(input_line, line, len);
14797db96d56Sopenharmony_ci    input_line[len] = '\0';
14807db96d56Sopenharmony_ci    self->input_line = input_line;
14817db96d56Sopenharmony_ci    *result = self->input_line;
14827db96d56Sopenharmony_ci    return len;
14837db96d56Sopenharmony_ci}
14847db96d56Sopenharmony_ci
14857db96d56Sopenharmony_ci/* Read a line from the input stream/buffer. If we run off the end of the input
14867db96d56Sopenharmony_ci   before hitting \n, raise an error.
14877db96d56Sopenharmony_ci
14887db96d56Sopenharmony_ci   Returns the number of chars read, or -1 on failure. */
14897db96d56Sopenharmony_cistatic Py_ssize_t
14907db96d56Sopenharmony_ci_Unpickler_Readline(UnpicklerObject *self, char **result)
14917db96d56Sopenharmony_ci{
14927db96d56Sopenharmony_ci    Py_ssize_t i, num_read;
14937db96d56Sopenharmony_ci
14947db96d56Sopenharmony_ci    for (i = self->next_read_idx; i < self->input_len; i++) {
14957db96d56Sopenharmony_ci        if (self->input_buffer[i] == '\n') {
14967db96d56Sopenharmony_ci            char *line_start = self->input_buffer + self->next_read_idx;
14977db96d56Sopenharmony_ci            num_read = i - self->next_read_idx + 1;
14987db96d56Sopenharmony_ci            self->next_read_idx = i + 1;
14997db96d56Sopenharmony_ci            return _Unpickler_CopyLine(self, line_start, num_read, result);
15007db96d56Sopenharmony_ci        }
15017db96d56Sopenharmony_ci    }
15027db96d56Sopenharmony_ci    if (!self->read)
15037db96d56Sopenharmony_ci        return bad_readline();
15047db96d56Sopenharmony_ci
15057db96d56Sopenharmony_ci    num_read = _Unpickler_ReadFromFile(self, READ_WHOLE_LINE);
15067db96d56Sopenharmony_ci    if (num_read < 0)
15077db96d56Sopenharmony_ci        return -1;
15087db96d56Sopenharmony_ci    if (num_read == 0 || self->input_buffer[num_read - 1] != '\n')
15097db96d56Sopenharmony_ci        return bad_readline();
15107db96d56Sopenharmony_ci    self->next_read_idx = num_read;
15117db96d56Sopenharmony_ci    return _Unpickler_CopyLine(self, self->input_buffer, num_read, result);
15127db96d56Sopenharmony_ci}
15137db96d56Sopenharmony_ci
15147db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. The memo array
15157db96d56Sopenharmony_ci   will be modified in place. */
15167db96d56Sopenharmony_cistatic int
15177db96d56Sopenharmony_ci_Unpickler_ResizeMemoList(UnpicklerObject *self, size_t new_size)
15187db96d56Sopenharmony_ci{
15197db96d56Sopenharmony_ci    size_t i;
15207db96d56Sopenharmony_ci
15217db96d56Sopenharmony_ci    assert(new_size > self->memo_size);
15227db96d56Sopenharmony_ci
15237db96d56Sopenharmony_ci    PyObject **memo_new = self->memo;
15247db96d56Sopenharmony_ci    PyMem_RESIZE(memo_new, PyObject *, new_size);
15257db96d56Sopenharmony_ci    if (memo_new == NULL) {
15267db96d56Sopenharmony_ci        PyErr_NoMemory();
15277db96d56Sopenharmony_ci        return -1;
15287db96d56Sopenharmony_ci    }
15297db96d56Sopenharmony_ci    self->memo = memo_new;
15307db96d56Sopenharmony_ci    for (i = self->memo_size; i < new_size; i++)
15317db96d56Sopenharmony_ci        self->memo[i] = NULL;
15327db96d56Sopenharmony_ci    self->memo_size = new_size;
15337db96d56Sopenharmony_ci    return 0;
15347db96d56Sopenharmony_ci}
15357db96d56Sopenharmony_ci
15367db96d56Sopenharmony_ci/* Returns NULL if idx is out of bounds. */
15377db96d56Sopenharmony_cistatic PyObject *
15387db96d56Sopenharmony_ci_Unpickler_MemoGet(UnpicklerObject *self, size_t idx)
15397db96d56Sopenharmony_ci{
15407db96d56Sopenharmony_ci    if (idx >= self->memo_size)
15417db96d56Sopenharmony_ci        return NULL;
15427db96d56Sopenharmony_ci
15437db96d56Sopenharmony_ci    return self->memo[idx];
15447db96d56Sopenharmony_ci}
15457db96d56Sopenharmony_ci
15467db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success.
15477db96d56Sopenharmony_ci   This takes its own reference to `value`. */
15487db96d56Sopenharmony_cistatic int
15497db96d56Sopenharmony_ci_Unpickler_MemoPut(UnpicklerObject *self, size_t idx, PyObject *value)
15507db96d56Sopenharmony_ci{
15517db96d56Sopenharmony_ci    PyObject *old_item;
15527db96d56Sopenharmony_ci
15537db96d56Sopenharmony_ci    if (idx >= self->memo_size) {
15547db96d56Sopenharmony_ci        if (_Unpickler_ResizeMemoList(self, idx * 2) < 0)
15557db96d56Sopenharmony_ci            return -1;
15567db96d56Sopenharmony_ci        assert(idx < self->memo_size);
15577db96d56Sopenharmony_ci    }
15587db96d56Sopenharmony_ci    Py_INCREF(value);
15597db96d56Sopenharmony_ci    old_item = self->memo[idx];
15607db96d56Sopenharmony_ci    self->memo[idx] = value;
15617db96d56Sopenharmony_ci    if (old_item != NULL) {
15627db96d56Sopenharmony_ci        Py_DECREF(old_item);
15637db96d56Sopenharmony_ci    }
15647db96d56Sopenharmony_ci    else {
15657db96d56Sopenharmony_ci        self->memo_len++;
15667db96d56Sopenharmony_ci    }
15677db96d56Sopenharmony_ci    return 0;
15687db96d56Sopenharmony_ci}
15697db96d56Sopenharmony_ci
15707db96d56Sopenharmony_cistatic PyObject **
15717db96d56Sopenharmony_ci_Unpickler_NewMemo(Py_ssize_t new_size)
15727db96d56Sopenharmony_ci{
15737db96d56Sopenharmony_ci    PyObject **memo = PyMem_NEW(PyObject *, new_size);
15747db96d56Sopenharmony_ci    if (memo == NULL) {
15757db96d56Sopenharmony_ci        PyErr_NoMemory();
15767db96d56Sopenharmony_ci        return NULL;
15777db96d56Sopenharmony_ci    }
15787db96d56Sopenharmony_ci    memset(memo, 0, new_size * sizeof(PyObject *));
15797db96d56Sopenharmony_ci    return memo;
15807db96d56Sopenharmony_ci}
15817db96d56Sopenharmony_ci
15827db96d56Sopenharmony_ci/* Free the unpickler's memo, taking care to decref any items left in it. */
15837db96d56Sopenharmony_cistatic void
15847db96d56Sopenharmony_ci_Unpickler_MemoCleanup(UnpicklerObject *self)
15857db96d56Sopenharmony_ci{
15867db96d56Sopenharmony_ci    Py_ssize_t i;
15877db96d56Sopenharmony_ci    PyObject **memo = self->memo;
15887db96d56Sopenharmony_ci
15897db96d56Sopenharmony_ci    if (self->memo == NULL)
15907db96d56Sopenharmony_ci        return;
15917db96d56Sopenharmony_ci    self->memo = NULL;
15927db96d56Sopenharmony_ci    i = self->memo_size;
15937db96d56Sopenharmony_ci    while (--i >= 0) {
15947db96d56Sopenharmony_ci        Py_XDECREF(memo[i]);
15957db96d56Sopenharmony_ci    }
15967db96d56Sopenharmony_ci    PyMem_Free(memo);
15977db96d56Sopenharmony_ci}
15987db96d56Sopenharmony_ci
15997db96d56Sopenharmony_cistatic UnpicklerObject *
16007db96d56Sopenharmony_ci_Unpickler_New(void)
16017db96d56Sopenharmony_ci{
16027db96d56Sopenharmony_ci    UnpicklerObject *self;
16037db96d56Sopenharmony_ci
16047db96d56Sopenharmony_ci    self = PyObject_GC_New(UnpicklerObject, &Unpickler_Type);
16057db96d56Sopenharmony_ci    if (self == NULL)
16067db96d56Sopenharmony_ci        return NULL;
16077db96d56Sopenharmony_ci
16087db96d56Sopenharmony_ci    self->pers_func = NULL;
16097db96d56Sopenharmony_ci    self->input_buffer = NULL;
16107db96d56Sopenharmony_ci    self->input_line = NULL;
16117db96d56Sopenharmony_ci    self->input_len = 0;
16127db96d56Sopenharmony_ci    self->next_read_idx = 0;
16137db96d56Sopenharmony_ci    self->prefetched_idx = 0;
16147db96d56Sopenharmony_ci    self->read = NULL;
16157db96d56Sopenharmony_ci    self->readinto = NULL;
16167db96d56Sopenharmony_ci    self->readline = NULL;
16177db96d56Sopenharmony_ci    self->peek = NULL;
16187db96d56Sopenharmony_ci    self->buffers = NULL;
16197db96d56Sopenharmony_ci    self->encoding = NULL;
16207db96d56Sopenharmony_ci    self->errors = NULL;
16217db96d56Sopenharmony_ci    self->marks = NULL;
16227db96d56Sopenharmony_ci    self->num_marks = 0;
16237db96d56Sopenharmony_ci    self->marks_size = 0;
16247db96d56Sopenharmony_ci    self->proto = 0;
16257db96d56Sopenharmony_ci    self->fix_imports = 0;
16267db96d56Sopenharmony_ci    memset(&self->buffer, 0, sizeof(Py_buffer));
16277db96d56Sopenharmony_ci    self->memo_size = 32;
16287db96d56Sopenharmony_ci    self->memo_len = 0;
16297db96d56Sopenharmony_ci    self->memo = _Unpickler_NewMemo(self->memo_size);
16307db96d56Sopenharmony_ci    self->stack = (Pdata *)Pdata_New();
16317db96d56Sopenharmony_ci
16327db96d56Sopenharmony_ci    if (self->memo == NULL || self->stack == NULL) {
16337db96d56Sopenharmony_ci        Py_DECREF(self);
16347db96d56Sopenharmony_ci        return NULL;
16357db96d56Sopenharmony_ci    }
16367db96d56Sopenharmony_ci
16377db96d56Sopenharmony_ci    PyObject_GC_Track(self);
16387db96d56Sopenharmony_ci    return self;
16397db96d56Sopenharmony_ci}
16407db96d56Sopenharmony_ci
16417db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. This may
16427db96d56Sopenharmony_ci   be called once on a freshly created Unpickler. */
16437db96d56Sopenharmony_cistatic int
16447db96d56Sopenharmony_ci_Unpickler_SetInputStream(UnpicklerObject *self, PyObject *file)
16457db96d56Sopenharmony_ci{
16467db96d56Sopenharmony_ci    /* Optional file methods */
16477db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(file, &_Py_ID(peek), &self->peek) < 0) {
16487db96d56Sopenharmony_ci        return -1;
16497db96d56Sopenharmony_ci    }
16507db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(file, &_Py_ID(readinto), &self->readinto) < 0) {
16517db96d56Sopenharmony_ci        return -1;
16527db96d56Sopenharmony_ci    }
16537db96d56Sopenharmony_ci    (void)_PyObject_LookupAttr(file, &_Py_ID(read), &self->read);
16547db96d56Sopenharmony_ci    (void)_PyObject_LookupAttr(file, &_Py_ID(readline), &self->readline);
16557db96d56Sopenharmony_ci    if (!self->readline || !self->read) {
16567db96d56Sopenharmony_ci        if (!PyErr_Occurred()) {
16577db96d56Sopenharmony_ci            PyErr_SetString(PyExc_TypeError,
16587db96d56Sopenharmony_ci                            "file must have 'read' and 'readline' attributes");
16597db96d56Sopenharmony_ci        }
16607db96d56Sopenharmony_ci        Py_CLEAR(self->read);
16617db96d56Sopenharmony_ci        Py_CLEAR(self->readinto);
16627db96d56Sopenharmony_ci        Py_CLEAR(self->readline);
16637db96d56Sopenharmony_ci        Py_CLEAR(self->peek);
16647db96d56Sopenharmony_ci        return -1;
16657db96d56Sopenharmony_ci    }
16667db96d56Sopenharmony_ci    return 0;
16677db96d56Sopenharmony_ci}
16687db96d56Sopenharmony_ci
16697db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. This may
16707db96d56Sopenharmony_ci   be called once on a freshly created Unpickler. */
16717db96d56Sopenharmony_cistatic int
16727db96d56Sopenharmony_ci_Unpickler_SetInputEncoding(UnpicklerObject *self,
16737db96d56Sopenharmony_ci                            const char *encoding,
16747db96d56Sopenharmony_ci                            const char *errors)
16757db96d56Sopenharmony_ci{
16767db96d56Sopenharmony_ci    if (encoding == NULL)
16777db96d56Sopenharmony_ci        encoding = "ASCII";
16787db96d56Sopenharmony_ci    if (errors == NULL)
16797db96d56Sopenharmony_ci        errors = "strict";
16807db96d56Sopenharmony_ci
16817db96d56Sopenharmony_ci    self->encoding = _PyMem_Strdup(encoding);
16827db96d56Sopenharmony_ci    self->errors = _PyMem_Strdup(errors);
16837db96d56Sopenharmony_ci    if (self->encoding == NULL || self->errors == NULL) {
16847db96d56Sopenharmony_ci        PyErr_NoMemory();
16857db96d56Sopenharmony_ci        return -1;
16867db96d56Sopenharmony_ci    }
16877db96d56Sopenharmony_ci    return 0;
16887db96d56Sopenharmony_ci}
16897db96d56Sopenharmony_ci
16907db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. This may
16917db96d56Sopenharmony_ci   be called once on a freshly created Unpickler. */
16927db96d56Sopenharmony_cistatic int
16937db96d56Sopenharmony_ci_Unpickler_SetBuffers(UnpicklerObject *self, PyObject *buffers)
16947db96d56Sopenharmony_ci{
16957db96d56Sopenharmony_ci    if (buffers == NULL || buffers == Py_None) {
16967db96d56Sopenharmony_ci        self->buffers = NULL;
16977db96d56Sopenharmony_ci    }
16987db96d56Sopenharmony_ci    else {
16997db96d56Sopenharmony_ci        self->buffers = PyObject_GetIter(buffers);
17007db96d56Sopenharmony_ci        if (self->buffers == NULL) {
17017db96d56Sopenharmony_ci            return -1;
17027db96d56Sopenharmony_ci        }
17037db96d56Sopenharmony_ci    }
17047db96d56Sopenharmony_ci    return 0;
17057db96d56Sopenharmony_ci}
17067db96d56Sopenharmony_ci
17077db96d56Sopenharmony_ci/* Generate a GET opcode for an object stored in the memo. */
17087db96d56Sopenharmony_cistatic int
17097db96d56Sopenharmony_cimemo_get(PicklerObject *self, PyObject *key)
17107db96d56Sopenharmony_ci{
17117db96d56Sopenharmony_ci    Py_ssize_t *value;
17127db96d56Sopenharmony_ci    char pdata[30];
17137db96d56Sopenharmony_ci    Py_ssize_t len;
17147db96d56Sopenharmony_ci
17157db96d56Sopenharmony_ci    value = PyMemoTable_Get(self->memo, key);
17167db96d56Sopenharmony_ci    if (value == NULL)  {
17177db96d56Sopenharmony_ci        PyErr_SetObject(PyExc_KeyError, key);
17187db96d56Sopenharmony_ci        return -1;
17197db96d56Sopenharmony_ci    }
17207db96d56Sopenharmony_ci
17217db96d56Sopenharmony_ci    if (!self->bin) {
17227db96d56Sopenharmony_ci        pdata[0] = GET;
17237db96d56Sopenharmony_ci        PyOS_snprintf(pdata + 1, sizeof(pdata) - 1,
17247db96d56Sopenharmony_ci                      "%zd\n", *value);
17257db96d56Sopenharmony_ci        len = strlen(pdata);
17267db96d56Sopenharmony_ci    }
17277db96d56Sopenharmony_ci    else {
17287db96d56Sopenharmony_ci        if (*value < 256) {
17297db96d56Sopenharmony_ci            pdata[0] = BINGET;
17307db96d56Sopenharmony_ci            pdata[1] = (unsigned char)(*value & 0xff);
17317db96d56Sopenharmony_ci            len = 2;
17327db96d56Sopenharmony_ci        }
17337db96d56Sopenharmony_ci        else if ((size_t)*value <= 0xffffffffUL) {
17347db96d56Sopenharmony_ci            pdata[0] = LONG_BINGET;
17357db96d56Sopenharmony_ci            pdata[1] = (unsigned char)(*value & 0xff);
17367db96d56Sopenharmony_ci            pdata[2] = (unsigned char)((*value >> 8) & 0xff);
17377db96d56Sopenharmony_ci            pdata[3] = (unsigned char)((*value >> 16) & 0xff);
17387db96d56Sopenharmony_ci            pdata[4] = (unsigned char)((*value >> 24) & 0xff);
17397db96d56Sopenharmony_ci            len = 5;
17407db96d56Sopenharmony_ci        }
17417db96d56Sopenharmony_ci        else { /* unlikely */
17427db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
17437db96d56Sopenharmony_ci            PyErr_SetString(st->PicklingError,
17447db96d56Sopenharmony_ci                            "memo id too large for LONG_BINGET");
17457db96d56Sopenharmony_ci            return -1;
17467db96d56Sopenharmony_ci        }
17477db96d56Sopenharmony_ci    }
17487db96d56Sopenharmony_ci
17497db96d56Sopenharmony_ci    if (_Pickler_Write(self, pdata, len) < 0)
17507db96d56Sopenharmony_ci        return -1;
17517db96d56Sopenharmony_ci
17527db96d56Sopenharmony_ci    return 0;
17537db96d56Sopenharmony_ci}
17547db96d56Sopenharmony_ci
17557db96d56Sopenharmony_ci/* Store an object in the memo, assign it a new unique ID based on the number
17567db96d56Sopenharmony_ci   of objects currently stored in the memo and generate a PUT opcode. */
17577db96d56Sopenharmony_cistatic int
17587db96d56Sopenharmony_cimemo_put(PicklerObject *self, PyObject *obj)
17597db96d56Sopenharmony_ci{
17607db96d56Sopenharmony_ci    char pdata[30];
17617db96d56Sopenharmony_ci    Py_ssize_t len;
17627db96d56Sopenharmony_ci    Py_ssize_t idx;
17637db96d56Sopenharmony_ci
17647db96d56Sopenharmony_ci    const char memoize_op = MEMOIZE;
17657db96d56Sopenharmony_ci
17667db96d56Sopenharmony_ci    if (self->fast)
17677db96d56Sopenharmony_ci        return 0;
17687db96d56Sopenharmony_ci
17697db96d56Sopenharmony_ci    idx = PyMemoTable_Size(self->memo);
17707db96d56Sopenharmony_ci    if (PyMemoTable_Set(self->memo, obj, idx) < 0)
17717db96d56Sopenharmony_ci        return -1;
17727db96d56Sopenharmony_ci
17737db96d56Sopenharmony_ci    if (self->proto >= 4) {
17747db96d56Sopenharmony_ci        if (_Pickler_Write(self, &memoize_op, 1) < 0)
17757db96d56Sopenharmony_ci            return -1;
17767db96d56Sopenharmony_ci        return 0;
17777db96d56Sopenharmony_ci    }
17787db96d56Sopenharmony_ci    else if (!self->bin) {
17797db96d56Sopenharmony_ci        pdata[0] = PUT;
17807db96d56Sopenharmony_ci        PyOS_snprintf(pdata + 1, sizeof(pdata) - 1,
17817db96d56Sopenharmony_ci                      "%zd\n", idx);
17827db96d56Sopenharmony_ci        len = strlen(pdata);
17837db96d56Sopenharmony_ci    }
17847db96d56Sopenharmony_ci    else {
17857db96d56Sopenharmony_ci        if (idx < 256) {
17867db96d56Sopenharmony_ci            pdata[0] = BINPUT;
17877db96d56Sopenharmony_ci            pdata[1] = (unsigned char)idx;
17887db96d56Sopenharmony_ci            len = 2;
17897db96d56Sopenharmony_ci        }
17907db96d56Sopenharmony_ci        else if ((size_t)idx <= 0xffffffffUL) {
17917db96d56Sopenharmony_ci            pdata[0] = LONG_BINPUT;
17927db96d56Sopenharmony_ci            pdata[1] = (unsigned char)(idx & 0xff);
17937db96d56Sopenharmony_ci            pdata[2] = (unsigned char)((idx >> 8) & 0xff);
17947db96d56Sopenharmony_ci            pdata[3] = (unsigned char)((idx >> 16) & 0xff);
17957db96d56Sopenharmony_ci            pdata[4] = (unsigned char)((idx >> 24) & 0xff);
17967db96d56Sopenharmony_ci            len = 5;
17977db96d56Sopenharmony_ci        }
17987db96d56Sopenharmony_ci        else { /* unlikely */
17997db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
18007db96d56Sopenharmony_ci            PyErr_SetString(st->PicklingError,
18017db96d56Sopenharmony_ci                            "memo id too large for LONG_BINPUT");
18027db96d56Sopenharmony_ci            return -1;
18037db96d56Sopenharmony_ci        }
18047db96d56Sopenharmony_ci    }
18057db96d56Sopenharmony_ci    if (_Pickler_Write(self, pdata, len) < 0)
18067db96d56Sopenharmony_ci        return -1;
18077db96d56Sopenharmony_ci
18087db96d56Sopenharmony_ci    return 0;
18097db96d56Sopenharmony_ci}
18107db96d56Sopenharmony_ci
18117db96d56Sopenharmony_cistatic PyObject *
18127db96d56Sopenharmony_ciget_dotted_path(PyObject *obj, PyObject *name)
18137db96d56Sopenharmony_ci{
18147db96d56Sopenharmony_ci    PyObject *dotted_path;
18157db96d56Sopenharmony_ci    Py_ssize_t i, n;
18167db96d56Sopenharmony_ci    _Py_DECLARE_STR(dot, ".");
18177db96d56Sopenharmony_ci    dotted_path = PyUnicode_Split(name, &_Py_STR(dot), -1);
18187db96d56Sopenharmony_ci    if (dotted_path == NULL)
18197db96d56Sopenharmony_ci        return NULL;
18207db96d56Sopenharmony_ci    n = PyList_GET_SIZE(dotted_path);
18217db96d56Sopenharmony_ci    assert(n >= 1);
18227db96d56Sopenharmony_ci    for (i = 0; i < n; i++) {
18237db96d56Sopenharmony_ci        PyObject *subpath = PyList_GET_ITEM(dotted_path, i);
18247db96d56Sopenharmony_ci        if (_PyUnicode_EqualToASCIIString(subpath, "<locals>")) {
18257db96d56Sopenharmony_ci            if (obj == NULL)
18267db96d56Sopenharmony_ci                PyErr_Format(PyExc_AttributeError,
18277db96d56Sopenharmony_ci                             "Can't pickle local object %R", name);
18287db96d56Sopenharmony_ci            else
18297db96d56Sopenharmony_ci                PyErr_Format(PyExc_AttributeError,
18307db96d56Sopenharmony_ci                             "Can't pickle local attribute %R on %R", name, obj);
18317db96d56Sopenharmony_ci            Py_DECREF(dotted_path);
18327db96d56Sopenharmony_ci            return NULL;
18337db96d56Sopenharmony_ci        }
18347db96d56Sopenharmony_ci    }
18357db96d56Sopenharmony_ci    return dotted_path;
18367db96d56Sopenharmony_ci}
18377db96d56Sopenharmony_ci
18387db96d56Sopenharmony_cistatic PyObject *
18397db96d56Sopenharmony_ciget_deep_attribute(PyObject *obj, PyObject *names, PyObject **pparent)
18407db96d56Sopenharmony_ci{
18417db96d56Sopenharmony_ci    Py_ssize_t i, n;
18427db96d56Sopenharmony_ci    PyObject *parent = NULL;
18437db96d56Sopenharmony_ci
18447db96d56Sopenharmony_ci    assert(PyList_CheckExact(names));
18457db96d56Sopenharmony_ci    Py_INCREF(obj);
18467db96d56Sopenharmony_ci    n = PyList_GET_SIZE(names);
18477db96d56Sopenharmony_ci    for (i = 0; i < n; i++) {
18487db96d56Sopenharmony_ci        PyObject *name = PyList_GET_ITEM(names, i);
18497db96d56Sopenharmony_ci        Py_XDECREF(parent);
18507db96d56Sopenharmony_ci        parent = obj;
18517db96d56Sopenharmony_ci        (void)_PyObject_LookupAttr(parent, name, &obj);
18527db96d56Sopenharmony_ci        if (obj == NULL) {
18537db96d56Sopenharmony_ci            Py_DECREF(parent);
18547db96d56Sopenharmony_ci            return NULL;
18557db96d56Sopenharmony_ci        }
18567db96d56Sopenharmony_ci    }
18577db96d56Sopenharmony_ci    if (pparent != NULL)
18587db96d56Sopenharmony_ci        *pparent = parent;
18597db96d56Sopenharmony_ci    else
18607db96d56Sopenharmony_ci        Py_XDECREF(parent);
18617db96d56Sopenharmony_ci    return obj;
18627db96d56Sopenharmony_ci}
18637db96d56Sopenharmony_ci
18647db96d56Sopenharmony_ci
18657db96d56Sopenharmony_cistatic PyObject *
18667db96d56Sopenharmony_cigetattribute(PyObject *obj, PyObject *name, int allow_qualname)
18677db96d56Sopenharmony_ci{
18687db96d56Sopenharmony_ci    PyObject *dotted_path, *attr;
18697db96d56Sopenharmony_ci
18707db96d56Sopenharmony_ci    if (allow_qualname) {
18717db96d56Sopenharmony_ci        dotted_path = get_dotted_path(obj, name);
18727db96d56Sopenharmony_ci        if (dotted_path == NULL)
18737db96d56Sopenharmony_ci            return NULL;
18747db96d56Sopenharmony_ci        attr = get_deep_attribute(obj, dotted_path, NULL);
18757db96d56Sopenharmony_ci        Py_DECREF(dotted_path);
18767db96d56Sopenharmony_ci    }
18777db96d56Sopenharmony_ci    else {
18787db96d56Sopenharmony_ci        (void)_PyObject_LookupAttr(obj, name, &attr);
18797db96d56Sopenharmony_ci    }
18807db96d56Sopenharmony_ci    if (attr == NULL && !PyErr_Occurred()) {
18817db96d56Sopenharmony_ci        PyErr_Format(PyExc_AttributeError,
18827db96d56Sopenharmony_ci                     "Can't get attribute %R on %R", name, obj);
18837db96d56Sopenharmony_ci    }
18847db96d56Sopenharmony_ci    return attr;
18857db96d56Sopenharmony_ci}
18867db96d56Sopenharmony_ci
18877db96d56Sopenharmony_cistatic int
18887db96d56Sopenharmony_ci_checkmodule(PyObject *module_name, PyObject *module,
18897db96d56Sopenharmony_ci             PyObject *global, PyObject *dotted_path)
18907db96d56Sopenharmony_ci{
18917db96d56Sopenharmony_ci    if (module == Py_None) {
18927db96d56Sopenharmony_ci        return -1;
18937db96d56Sopenharmony_ci    }
18947db96d56Sopenharmony_ci    if (PyUnicode_Check(module_name) &&
18957db96d56Sopenharmony_ci            _PyUnicode_EqualToASCIIString(module_name, "__main__")) {
18967db96d56Sopenharmony_ci        return -1;
18977db96d56Sopenharmony_ci    }
18987db96d56Sopenharmony_ci
18997db96d56Sopenharmony_ci    PyObject *candidate = get_deep_attribute(module, dotted_path, NULL);
19007db96d56Sopenharmony_ci    if (candidate == NULL) {
19017db96d56Sopenharmony_ci        return -1;
19027db96d56Sopenharmony_ci    }
19037db96d56Sopenharmony_ci    if (candidate != global) {
19047db96d56Sopenharmony_ci        Py_DECREF(candidate);
19057db96d56Sopenharmony_ci        return -1;
19067db96d56Sopenharmony_ci    }
19077db96d56Sopenharmony_ci    Py_DECREF(candidate);
19087db96d56Sopenharmony_ci    return 0;
19097db96d56Sopenharmony_ci}
19107db96d56Sopenharmony_ci
19117db96d56Sopenharmony_cistatic PyObject *
19127db96d56Sopenharmony_ciwhichmodule(PyObject *global, PyObject *dotted_path)
19137db96d56Sopenharmony_ci{
19147db96d56Sopenharmony_ci    PyObject *module_name;
19157db96d56Sopenharmony_ci    PyObject *module = NULL;
19167db96d56Sopenharmony_ci    Py_ssize_t i;
19177db96d56Sopenharmony_ci    PyObject *modules;
19187db96d56Sopenharmony_ci
19197db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(global, &_Py_ID(__module__), &module_name) < 0) {
19207db96d56Sopenharmony_ci        return NULL;
19217db96d56Sopenharmony_ci    }
19227db96d56Sopenharmony_ci    if (module_name) {
19237db96d56Sopenharmony_ci        /* In some rare cases (e.g., bound methods of extension types),
19247db96d56Sopenharmony_ci           __module__ can be None. If it is so, then search sys.modules for
19257db96d56Sopenharmony_ci           the module of global. */
19267db96d56Sopenharmony_ci        if (module_name != Py_None)
19277db96d56Sopenharmony_ci            return module_name;
19287db96d56Sopenharmony_ci        Py_CLEAR(module_name);
19297db96d56Sopenharmony_ci    }
19307db96d56Sopenharmony_ci    assert(module_name == NULL);
19317db96d56Sopenharmony_ci
19327db96d56Sopenharmony_ci    /* Fallback on walking sys.modules */
19337db96d56Sopenharmony_ci    PyThreadState *tstate = _PyThreadState_GET();
19347db96d56Sopenharmony_ci    modules = _PySys_GetAttr(tstate, &_Py_ID(modules));
19357db96d56Sopenharmony_ci    if (modules == NULL) {
19367db96d56Sopenharmony_ci        PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules");
19377db96d56Sopenharmony_ci        return NULL;
19387db96d56Sopenharmony_ci    }
19397db96d56Sopenharmony_ci    if (PyDict_CheckExact(modules)) {
19407db96d56Sopenharmony_ci        i = 0;
19417db96d56Sopenharmony_ci        while (PyDict_Next(modules, &i, &module_name, &module)) {
19427db96d56Sopenharmony_ci            if (_checkmodule(module_name, module, global, dotted_path) == 0) {
19437db96d56Sopenharmony_ci                Py_INCREF(module_name);
19447db96d56Sopenharmony_ci                return module_name;
19457db96d56Sopenharmony_ci            }
19467db96d56Sopenharmony_ci            if (PyErr_Occurred()) {
19477db96d56Sopenharmony_ci                return NULL;
19487db96d56Sopenharmony_ci            }
19497db96d56Sopenharmony_ci        }
19507db96d56Sopenharmony_ci    }
19517db96d56Sopenharmony_ci    else {
19527db96d56Sopenharmony_ci        PyObject *iterator = PyObject_GetIter(modules);
19537db96d56Sopenharmony_ci        if (iterator == NULL) {
19547db96d56Sopenharmony_ci            return NULL;
19557db96d56Sopenharmony_ci        }
19567db96d56Sopenharmony_ci        while ((module_name = PyIter_Next(iterator))) {
19577db96d56Sopenharmony_ci            module = PyObject_GetItem(modules, module_name);
19587db96d56Sopenharmony_ci            if (module == NULL) {
19597db96d56Sopenharmony_ci                Py_DECREF(module_name);
19607db96d56Sopenharmony_ci                Py_DECREF(iterator);
19617db96d56Sopenharmony_ci                return NULL;
19627db96d56Sopenharmony_ci            }
19637db96d56Sopenharmony_ci            if (_checkmodule(module_name, module, global, dotted_path) == 0) {
19647db96d56Sopenharmony_ci                Py_DECREF(module);
19657db96d56Sopenharmony_ci                Py_DECREF(iterator);
19667db96d56Sopenharmony_ci                return module_name;
19677db96d56Sopenharmony_ci            }
19687db96d56Sopenharmony_ci            Py_DECREF(module);
19697db96d56Sopenharmony_ci            Py_DECREF(module_name);
19707db96d56Sopenharmony_ci            if (PyErr_Occurred()) {
19717db96d56Sopenharmony_ci                Py_DECREF(iterator);
19727db96d56Sopenharmony_ci                return NULL;
19737db96d56Sopenharmony_ci            }
19747db96d56Sopenharmony_ci        }
19757db96d56Sopenharmony_ci        Py_DECREF(iterator);
19767db96d56Sopenharmony_ci    }
19777db96d56Sopenharmony_ci
19787db96d56Sopenharmony_ci    /* If no module is found, use __main__. */
19797db96d56Sopenharmony_ci    module_name = &_Py_ID(__main__);
19807db96d56Sopenharmony_ci    Py_INCREF(module_name);
19817db96d56Sopenharmony_ci    return module_name;
19827db96d56Sopenharmony_ci}
19837db96d56Sopenharmony_ci
19847db96d56Sopenharmony_ci/* fast_save_enter() and fast_save_leave() are guards against recursive
19857db96d56Sopenharmony_ci   objects when Pickler is used with the "fast mode" (i.e., with object
19867db96d56Sopenharmony_ci   memoization disabled). If the nesting of a list or dict object exceed
19877db96d56Sopenharmony_ci   FAST_NESTING_LIMIT, these guards will start keeping an internal
19887db96d56Sopenharmony_ci   reference to the seen list or dict objects and check whether these objects
19897db96d56Sopenharmony_ci   are recursive. These are not strictly necessary, since save() has a
19907db96d56Sopenharmony_ci   hard-coded recursion limit, but they give a nicer error message than the
19917db96d56Sopenharmony_ci   typical RuntimeError. */
19927db96d56Sopenharmony_cistatic int
19937db96d56Sopenharmony_cifast_save_enter(PicklerObject *self, PyObject *obj)
19947db96d56Sopenharmony_ci{
19957db96d56Sopenharmony_ci    /* if fast_nesting < 0, we're doing an error exit. */
19967db96d56Sopenharmony_ci    if (++self->fast_nesting >= FAST_NESTING_LIMIT) {
19977db96d56Sopenharmony_ci        PyObject *key = NULL;
19987db96d56Sopenharmony_ci        if (self->fast_memo == NULL) {
19997db96d56Sopenharmony_ci            self->fast_memo = PyDict_New();
20007db96d56Sopenharmony_ci            if (self->fast_memo == NULL) {
20017db96d56Sopenharmony_ci                self->fast_nesting = -1;
20027db96d56Sopenharmony_ci                return 0;
20037db96d56Sopenharmony_ci            }
20047db96d56Sopenharmony_ci        }
20057db96d56Sopenharmony_ci        key = PyLong_FromVoidPtr(obj);
20067db96d56Sopenharmony_ci        if (key == NULL) {
20077db96d56Sopenharmony_ci            self->fast_nesting = -1;
20087db96d56Sopenharmony_ci            return 0;
20097db96d56Sopenharmony_ci        }
20107db96d56Sopenharmony_ci        int r = PyDict_Contains(self->fast_memo, key);
20117db96d56Sopenharmony_ci        if (r > 0) {
20127db96d56Sopenharmony_ci            PyErr_Format(PyExc_ValueError,
20137db96d56Sopenharmony_ci                         "fast mode: can't pickle cyclic objects "
20147db96d56Sopenharmony_ci                         "including object type %.200s at %p",
20157db96d56Sopenharmony_ci                         Py_TYPE(obj)->tp_name, obj);
20167db96d56Sopenharmony_ci        }
20177db96d56Sopenharmony_ci        else if (r == 0) {
20187db96d56Sopenharmony_ci            r = PyDict_SetItem(self->fast_memo, key, Py_None);
20197db96d56Sopenharmony_ci        }
20207db96d56Sopenharmony_ci        Py_DECREF(key);
20217db96d56Sopenharmony_ci        if (r != 0) {
20227db96d56Sopenharmony_ci            self->fast_nesting = -1;
20237db96d56Sopenharmony_ci            return 0;
20247db96d56Sopenharmony_ci        }
20257db96d56Sopenharmony_ci    }
20267db96d56Sopenharmony_ci    return 1;
20277db96d56Sopenharmony_ci}
20287db96d56Sopenharmony_ci
20297db96d56Sopenharmony_cistatic int
20307db96d56Sopenharmony_cifast_save_leave(PicklerObject *self, PyObject *obj)
20317db96d56Sopenharmony_ci{
20327db96d56Sopenharmony_ci    if (self->fast_nesting-- >= FAST_NESTING_LIMIT) {
20337db96d56Sopenharmony_ci        PyObject *key = PyLong_FromVoidPtr(obj);
20347db96d56Sopenharmony_ci        if (key == NULL)
20357db96d56Sopenharmony_ci            return 0;
20367db96d56Sopenharmony_ci        if (PyDict_DelItem(self->fast_memo, key) < 0) {
20377db96d56Sopenharmony_ci            Py_DECREF(key);
20387db96d56Sopenharmony_ci            return 0;
20397db96d56Sopenharmony_ci        }
20407db96d56Sopenharmony_ci        Py_DECREF(key);
20417db96d56Sopenharmony_ci    }
20427db96d56Sopenharmony_ci    return 1;
20437db96d56Sopenharmony_ci}
20447db96d56Sopenharmony_ci
20457db96d56Sopenharmony_cistatic int
20467db96d56Sopenharmony_cisave_none(PicklerObject *self, PyObject *obj)
20477db96d56Sopenharmony_ci{
20487db96d56Sopenharmony_ci    const char none_op = NONE;
20497db96d56Sopenharmony_ci    if (_Pickler_Write(self, &none_op, 1) < 0)
20507db96d56Sopenharmony_ci        return -1;
20517db96d56Sopenharmony_ci
20527db96d56Sopenharmony_ci    return 0;
20537db96d56Sopenharmony_ci}
20547db96d56Sopenharmony_ci
20557db96d56Sopenharmony_cistatic int
20567db96d56Sopenharmony_cisave_bool(PicklerObject *self, PyObject *obj)
20577db96d56Sopenharmony_ci{
20587db96d56Sopenharmony_ci    if (self->proto >= 2) {
20597db96d56Sopenharmony_ci        const char bool_op = (obj == Py_True) ? NEWTRUE : NEWFALSE;
20607db96d56Sopenharmony_ci        if (_Pickler_Write(self, &bool_op, 1) < 0)
20617db96d56Sopenharmony_ci            return -1;
20627db96d56Sopenharmony_ci    }
20637db96d56Sopenharmony_ci    else {
20647db96d56Sopenharmony_ci        /* These aren't opcodes -- they're ways to pickle bools before protocol 2
20657db96d56Sopenharmony_ci         * so that unpicklers written before bools were introduced unpickle them
20667db96d56Sopenharmony_ci         * as ints, but unpicklers after can recognize that bools were intended.
20677db96d56Sopenharmony_ci         * Note that protocol 2 added direct ways to pickle bools.
20687db96d56Sopenharmony_ci         */
20697db96d56Sopenharmony_ci        const char *bool_str = (obj == Py_True) ? "I01\n" : "I00\n";
20707db96d56Sopenharmony_ci        if (_Pickler_Write(self, bool_str, strlen(bool_str)) < 0)
20717db96d56Sopenharmony_ci            return -1;
20727db96d56Sopenharmony_ci    }
20737db96d56Sopenharmony_ci    return 0;
20747db96d56Sopenharmony_ci}
20757db96d56Sopenharmony_ci
20767db96d56Sopenharmony_cistatic int
20777db96d56Sopenharmony_cisave_long(PicklerObject *self, PyObject *obj)
20787db96d56Sopenharmony_ci{
20797db96d56Sopenharmony_ci    PyObject *repr = NULL;
20807db96d56Sopenharmony_ci    Py_ssize_t size;
20817db96d56Sopenharmony_ci    long val;
20827db96d56Sopenharmony_ci    int overflow;
20837db96d56Sopenharmony_ci    int status = 0;
20847db96d56Sopenharmony_ci
20857db96d56Sopenharmony_ci    val= PyLong_AsLongAndOverflow(obj, &overflow);
20867db96d56Sopenharmony_ci    if (!overflow && (sizeof(long) <= 4 ||
20877db96d56Sopenharmony_ci            (val <= 0x7fffffffL && val >= (-0x7fffffffL - 1))))
20887db96d56Sopenharmony_ci    {
20897db96d56Sopenharmony_ci        /* result fits in a signed 4-byte integer.
20907db96d56Sopenharmony_ci
20917db96d56Sopenharmony_ci           Note: we can't use -0x80000000L in the above condition because some
20927db96d56Sopenharmony_ci           compilers (e.g., MSVC) will promote 0x80000000L to an unsigned type
20937db96d56Sopenharmony_ci           before applying the unary minus when sizeof(long) <= 4. The
20947db96d56Sopenharmony_ci           resulting value stays unsigned which is commonly not what we want,
20957db96d56Sopenharmony_ci           so MSVC happily warns us about it.  However, that result would have
20967db96d56Sopenharmony_ci           been fine because we guard for sizeof(long) <= 4 which turns the
20977db96d56Sopenharmony_ci           condition true in that particular case. */
20987db96d56Sopenharmony_ci        char pdata[32];
20997db96d56Sopenharmony_ci        Py_ssize_t len = 0;
21007db96d56Sopenharmony_ci
21017db96d56Sopenharmony_ci        if (self->bin) {
21027db96d56Sopenharmony_ci            pdata[1] = (unsigned char)(val & 0xff);
21037db96d56Sopenharmony_ci            pdata[2] = (unsigned char)((val >> 8) & 0xff);
21047db96d56Sopenharmony_ci            pdata[3] = (unsigned char)((val >> 16) & 0xff);
21057db96d56Sopenharmony_ci            pdata[4] = (unsigned char)((val >> 24) & 0xff);
21067db96d56Sopenharmony_ci
21077db96d56Sopenharmony_ci            if ((pdata[4] != 0) || (pdata[3] != 0)) {
21087db96d56Sopenharmony_ci                pdata[0] = BININT;
21097db96d56Sopenharmony_ci                len = 5;
21107db96d56Sopenharmony_ci            }
21117db96d56Sopenharmony_ci            else if (pdata[2] != 0) {
21127db96d56Sopenharmony_ci                pdata[0] = BININT2;
21137db96d56Sopenharmony_ci                len = 3;
21147db96d56Sopenharmony_ci            }
21157db96d56Sopenharmony_ci            else {
21167db96d56Sopenharmony_ci                pdata[0] = BININT1;
21177db96d56Sopenharmony_ci                len = 2;
21187db96d56Sopenharmony_ci            }
21197db96d56Sopenharmony_ci        }
21207db96d56Sopenharmony_ci        else {
21217db96d56Sopenharmony_ci            sprintf(pdata, "%c%ld\n", INT,  val);
21227db96d56Sopenharmony_ci            len = strlen(pdata);
21237db96d56Sopenharmony_ci        }
21247db96d56Sopenharmony_ci        if (_Pickler_Write(self, pdata, len) < 0)
21257db96d56Sopenharmony_ci            return -1;
21267db96d56Sopenharmony_ci
21277db96d56Sopenharmony_ci        return 0;
21287db96d56Sopenharmony_ci    }
21297db96d56Sopenharmony_ci    assert(!PyErr_Occurred());
21307db96d56Sopenharmony_ci
21317db96d56Sopenharmony_ci    if (self->proto >= 2) {
21327db96d56Sopenharmony_ci        /* Linear-time pickling. */
21337db96d56Sopenharmony_ci        size_t nbits;
21347db96d56Sopenharmony_ci        size_t nbytes;
21357db96d56Sopenharmony_ci        unsigned char *pdata;
21367db96d56Sopenharmony_ci        char header[5];
21377db96d56Sopenharmony_ci        int i;
21387db96d56Sopenharmony_ci        int sign = _PyLong_Sign(obj);
21397db96d56Sopenharmony_ci
21407db96d56Sopenharmony_ci        if (sign == 0) {
21417db96d56Sopenharmony_ci            header[0] = LONG1;
21427db96d56Sopenharmony_ci            header[1] = 0;      /* It's 0 -- an empty bytestring. */
21437db96d56Sopenharmony_ci            if (_Pickler_Write(self, header, 2) < 0)
21447db96d56Sopenharmony_ci                goto error;
21457db96d56Sopenharmony_ci            return 0;
21467db96d56Sopenharmony_ci        }
21477db96d56Sopenharmony_ci        nbits = _PyLong_NumBits(obj);
21487db96d56Sopenharmony_ci        if (nbits == (size_t)-1 && PyErr_Occurred())
21497db96d56Sopenharmony_ci            goto error;
21507db96d56Sopenharmony_ci        /* How many bytes do we need?  There are nbits >> 3 full
21517db96d56Sopenharmony_ci         * bytes of data, and nbits & 7 leftover bits.  If there
21527db96d56Sopenharmony_ci         * are any leftover bits, then we clearly need another
21537db96d56Sopenharmony_ci         * byte.  What's not so obvious is that we *probably*
21547db96d56Sopenharmony_ci         * need another byte even if there aren't any leftovers:
21557db96d56Sopenharmony_ci         * the most-significant bit of the most-significant byte
21567db96d56Sopenharmony_ci         * acts like a sign bit, and it's usually got a sense
21577db96d56Sopenharmony_ci         * opposite of the one we need.  The exception is ints
21587db96d56Sopenharmony_ci         * of the form -(2**(8*j-1)) for j > 0.  Such an int is
21597db96d56Sopenharmony_ci         * its own 256's-complement, so has the right sign bit
21607db96d56Sopenharmony_ci         * even without the extra byte.  That's a pain to check
21617db96d56Sopenharmony_ci         * for in advance, though, so we always grab an extra
21627db96d56Sopenharmony_ci         * byte at the start, and cut it back later if possible.
21637db96d56Sopenharmony_ci         */
21647db96d56Sopenharmony_ci        nbytes = (nbits >> 3) + 1;
21657db96d56Sopenharmony_ci        if (nbytes > 0x7fffffffL) {
21667db96d56Sopenharmony_ci            PyErr_SetString(PyExc_OverflowError,
21677db96d56Sopenharmony_ci                            "int too large to pickle");
21687db96d56Sopenharmony_ci            goto error;
21697db96d56Sopenharmony_ci        }
21707db96d56Sopenharmony_ci        repr = PyBytes_FromStringAndSize(NULL, (Py_ssize_t)nbytes);
21717db96d56Sopenharmony_ci        if (repr == NULL)
21727db96d56Sopenharmony_ci            goto error;
21737db96d56Sopenharmony_ci        pdata = (unsigned char *)PyBytes_AS_STRING(repr);
21747db96d56Sopenharmony_ci        i = _PyLong_AsByteArray((PyLongObject *)obj,
21757db96d56Sopenharmony_ci                                pdata, nbytes,
21767db96d56Sopenharmony_ci                                1 /* little endian */ , 1 /* signed */ );
21777db96d56Sopenharmony_ci        if (i < 0)
21787db96d56Sopenharmony_ci            goto error;
21797db96d56Sopenharmony_ci        /* If the int is negative, this may be a byte more than
21807db96d56Sopenharmony_ci         * needed.  This is so iff the MSB is all redundant sign
21817db96d56Sopenharmony_ci         * bits.
21827db96d56Sopenharmony_ci         */
21837db96d56Sopenharmony_ci        if (sign < 0 &&
21847db96d56Sopenharmony_ci            nbytes > 1 &&
21857db96d56Sopenharmony_ci            pdata[nbytes - 1] == 0xff &&
21867db96d56Sopenharmony_ci            (pdata[nbytes - 2] & 0x80) != 0) {
21877db96d56Sopenharmony_ci            nbytes--;
21887db96d56Sopenharmony_ci        }
21897db96d56Sopenharmony_ci
21907db96d56Sopenharmony_ci        if (nbytes < 256) {
21917db96d56Sopenharmony_ci            header[0] = LONG1;
21927db96d56Sopenharmony_ci            header[1] = (unsigned char)nbytes;
21937db96d56Sopenharmony_ci            size = 2;
21947db96d56Sopenharmony_ci        }
21957db96d56Sopenharmony_ci        else {
21967db96d56Sopenharmony_ci            header[0] = LONG4;
21977db96d56Sopenharmony_ci            size = (Py_ssize_t) nbytes;
21987db96d56Sopenharmony_ci            for (i = 1; i < 5; i++) {
21997db96d56Sopenharmony_ci                header[i] = (unsigned char)(size & 0xff);
22007db96d56Sopenharmony_ci                size >>= 8;
22017db96d56Sopenharmony_ci            }
22027db96d56Sopenharmony_ci            size = 5;
22037db96d56Sopenharmony_ci        }
22047db96d56Sopenharmony_ci        if (_Pickler_Write(self, header, size) < 0 ||
22057db96d56Sopenharmony_ci            _Pickler_Write(self, (char *)pdata, (int)nbytes) < 0)
22067db96d56Sopenharmony_ci            goto error;
22077db96d56Sopenharmony_ci    }
22087db96d56Sopenharmony_ci    else {
22097db96d56Sopenharmony_ci        const char long_op = LONG;
22107db96d56Sopenharmony_ci        const char *string;
22117db96d56Sopenharmony_ci
22127db96d56Sopenharmony_ci        /* proto < 2: write the repr and newline.  This is quadratic-time (in
22137db96d56Sopenharmony_ci           the number of digits), in both directions.  We add a trailing 'L'
22147db96d56Sopenharmony_ci           to the repr, for compatibility with Python 2.x. */
22157db96d56Sopenharmony_ci
22167db96d56Sopenharmony_ci        repr = PyObject_Repr(obj);
22177db96d56Sopenharmony_ci        if (repr == NULL)
22187db96d56Sopenharmony_ci            goto error;
22197db96d56Sopenharmony_ci
22207db96d56Sopenharmony_ci        string = PyUnicode_AsUTF8AndSize(repr, &size);
22217db96d56Sopenharmony_ci        if (string == NULL)
22227db96d56Sopenharmony_ci            goto error;
22237db96d56Sopenharmony_ci
22247db96d56Sopenharmony_ci        if (_Pickler_Write(self, &long_op, 1) < 0 ||
22257db96d56Sopenharmony_ci            _Pickler_Write(self, string, size) < 0 ||
22267db96d56Sopenharmony_ci            _Pickler_Write(self, "L\n", 2) < 0)
22277db96d56Sopenharmony_ci            goto error;
22287db96d56Sopenharmony_ci    }
22297db96d56Sopenharmony_ci
22307db96d56Sopenharmony_ci    if (0) {
22317db96d56Sopenharmony_ci  error:
22327db96d56Sopenharmony_ci      status = -1;
22337db96d56Sopenharmony_ci    }
22347db96d56Sopenharmony_ci    Py_XDECREF(repr);
22357db96d56Sopenharmony_ci
22367db96d56Sopenharmony_ci    return status;
22377db96d56Sopenharmony_ci}
22387db96d56Sopenharmony_ci
22397db96d56Sopenharmony_cistatic int
22407db96d56Sopenharmony_cisave_float(PicklerObject *self, PyObject *obj)
22417db96d56Sopenharmony_ci{
22427db96d56Sopenharmony_ci    double x = PyFloat_AS_DOUBLE((PyFloatObject *)obj);
22437db96d56Sopenharmony_ci
22447db96d56Sopenharmony_ci    if (self->bin) {
22457db96d56Sopenharmony_ci        char pdata[9];
22467db96d56Sopenharmony_ci        pdata[0] = BINFLOAT;
22477db96d56Sopenharmony_ci        if (PyFloat_Pack8(x, &pdata[1], 0) < 0)
22487db96d56Sopenharmony_ci            return -1;
22497db96d56Sopenharmony_ci        if (_Pickler_Write(self, pdata, 9) < 0)
22507db96d56Sopenharmony_ci            return -1;
22517db96d56Sopenharmony_ci   }
22527db96d56Sopenharmony_ci    else {
22537db96d56Sopenharmony_ci        int result = -1;
22547db96d56Sopenharmony_ci        char *buf = NULL;
22557db96d56Sopenharmony_ci        char op = FLOAT;
22567db96d56Sopenharmony_ci
22577db96d56Sopenharmony_ci        if (_Pickler_Write(self, &op, 1) < 0)
22587db96d56Sopenharmony_ci            goto done;
22597db96d56Sopenharmony_ci
22607db96d56Sopenharmony_ci        buf = PyOS_double_to_string(x, 'r', 0, Py_DTSF_ADD_DOT_0, NULL);
22617db96d56Sopenharmony_ci        if (!buf) {
22627db96d56Sopenharmony_ci            PyErr_NoMemory();
22637db96d56Sopenharmony_ci            goto done;
22647db96d56Sopenharmony_ci        }
22657db96d56Sopenharmony_ci
22667db96d56Sopenharmony_ci        if (_Pickler_Write(self, buf, strlen(buf)) < 0)
22677db96d56Sopenharmony_ci            goto done;
22687db96d56Sopenharmony_ci
22697db96d56Sopenharmony_ci        if (_Pickler_Write(self, "\n", 1) < 0)
22707db96d56Sopenharmony_ci            goto done;
22717db96d56Sopenharmony_ci
22727db96d56Sopenharmony_ci        result = 0;
22737db96d56Sopenharmony_cidone:
22747db96d56Sopenharmony_ci        PyMem_Free(buf);
22757db96d56Sopenharmony_ci        return result;
22767db96d56Sopenharmony_ci    }
22777db96d56Sopenharmony_ci
22787db96d56Sopenharmony_ci    return 0;
22797db96d56Sopenharmony_ci}
22807db96d56Sopenharmony_ci
22817db96d56Sopenharmony_ci/* Perform direct write of the header and payload of the binary object.
22827db96d56Sopenharmony_ci
22837db96d56Sopenharmony_ci   The large contiguous data is written directly into the underlying file
22847db96d56Sopenharmony_ci   object, bypassing the output_buffer of the Pickler.  We intentionally
22857db96d56Sopenharmony_ci   do not insert a protocol 4 frame opcode to make it possible to optimize
22867db96d56Sopenharmony_ci   file.read calls in the loader.
22877db96d56Sopenharmony_ci */
22887db96d56Sopenharmony_cistatic int
22897db96d56Sopenharmony_ci_Pickler_write_bytes(PicklerObject *self,
22907db96d56Sopenharmony_ci                     const char *header, Py_ssize_t header_size,
22917db96d56Sopenharmony_ci                     const char *data, Py_ssize_t data_size,
22927db96d56Sopenharmony_ci                     PyObject *payload)
22937db96d56Sopenharmony_ci{
22947db96d56Sopenharmony_ci    int bypass_buffer = (data_size >= FRAME_SIZE_TARGET);
22957db96d56Sopenharmony_ci    int framing = self->framing;
22967db96d56Sopenharmony_ci
22977db96d56Sopenharmony_ci    if (bypass_buffer) {
22987db96d56Sopenharmony_ci        assert(self->output_buffer != NULL);
22997db96d56Sopenharmony_ci        /* Commit the previous frame. */
23007db96d56Sopenharmony_ci        if (_Pickler_CommitFrame(self)) {
23017db96d56Sopenharmony_ci            return -1;
23027db96d56Sopenharmony_ci        }
23037db96d56Sopenharmony_ci        /* Disable framing temporarily */
23047db96d56Sopenharmony_ci        self->framing = 0;
23057db96d56Sopenharmony_ci    }
23067db96d56Sopenharmony_ci
23077db96d56Sopenharmony_ci    if (_Pickler_Write(self, header, header_size) < 0) {
23087db96d56Sopenharmony_ci        return -1;
23097db96d56Sopenharmony_ci    }
23107db96d56Sopenharmony_ci
23117db96d56Sopenharmony_ci    if (bypass_buffer && self->write != NULL) {
23127db96d56Sopenharmony_ci        /* Bypass the in-memory buffer to directly stream large data
23137db96d56Sopenharmony_ci           into the underlying file object. */
23147db96d56Sopenharmony_ci        PyObject *result, *mem = NULL;
23157db96d56Sopenharmony_ci        /* Dump the output buffer to the file. */
23167db96d56Sopenharmony_ci        if (_Pickler_FlushToFile(self) < 0) {
23177db96d56Sopenharmony_ci            return -1;
23187db96d56Sopenharmony_ci        }
23197db96d56Sopenharmony_ci
23207db96d56Sopenharmony_ci        /* Stream write the payload into the file without going through the
23217db96d56Sopenharmony_ci           output buffer. */
23227db96d56Sopenharmony_ci        if (payload == NULL) {
23237db96d56Sopenharmony_ci            /* TODO: It would be better to use a memoryview with a linked
23247db96d56Sopenharmony_ci               original string if this is possible. */
23257db96d56Sopenharmony_ci            payload = mem = PyBytes_FromStringAndSize(data, data_size);
23267db96d56Sopenharmony_ci            if (payload == NULL) {
23277db96d56Sopenharmony_ci                return -1;
23287db96d56Sopenharmony_ci            }
23297db96d56Sopenharmony_ci        }
23307db96d56Sopenharmony_ci        result = PyObject_CallOneArg(self->write, payload);
23317db96d56Sopenharmony_ci        Py_XDECREF(mem);
23327db96d56Sopenharmony_ci        if (result == NULL) {
23337db96d56Sopenharmony_ci            return -1;
23347db96d56Sopenharmony_ci        }
23357db96d56Sopenharmony_ci        Py_DECREF(result);
23367db96d56Sopenharmony_ci
23377db96d56Sopenharmony_ci        /* Reinitialize the buffer for subsequent calls to _Pickler_Write. */
23387db96d56Sopenharmony_ci        if (_Pickler_ClearBuffer(self) < 0) {
23397db96d56Sopenharmony_ci            return -1;
23407db96d56Sopenharmony_ci        }
23417db96d56Sopenharmony_ci    }
23427db96d56Sopenharmony_ci    else {
23437db96d56Sopenharmony_ci        if (_Pickler_Write(self, data, data_size) < 0) {
23447db96d56Sopenharmony_ci            return -1;
23457db96d56Sopenharmony_ci        }
23467db96d56Sopenharmony_ci    }
23477db96d56Sopenharmony_ci
23487db96d56Sopenharmony_ci    /* Re-enable framing for subsequent calls to _Pickler_Write. */
23497db96d56Sopenharmony_ci    self->framing = framing;
23507db96d56Sopenharmony_ci
23517db96d56Sopenharmony_ci    return 0;
23527db96d56Sopenharmony_ci}
23537db96d56Sopenharmony_ci
23547db96d56Sopenharmony_cistatic int
23557db96d56Sopenharmony_ci_save_bytes_data(PicklerObject *self, PyObject *obj, const char *data,
23567db96d56Sopenharmony_ci                 Py_ssize_t size)
23577db96d56Sopenharmony_ci{
23587db96d56Sopenharmony_ci    assert(self->proto >= 3);
23597db96d56Sopenharmony_ci
23607db96d56Sopenharmony_ci    char header[9];
23617db96d56Sopenharmony_ci    Py_ssize_t len;
23627db96d56Sopenharmony_ci
23637db96d56Sopenharmony_ci    if (size < 0)
23647db96d56Sopenharmony_ci        return -1;
23657db96d56Sopenharmony_ci
23667db96d56Sopenharmony_ci    if (size <= 0xff) {
23677db96d56Sopenharmony_ci        header[0] = SHORT_BINBYTES;
23687db96d56Sopenharmony_ci        header[1] = (unsigned char)size;
23697db96d56Sopenharmony_ci        len = 2;
23707db96d56Sopenharmony_ci    }
23717db96d56Sopenharmony_ci    else if ((size_t)size <= 0xffffffffUL) {
23727db96d56Sopenharmony_ci        header[0] = BINBYTES;
23737db96d56Sopenharmony_ci        header[1] = (unsigned char)(size & 0xff);
23747db96d56Sopenharmony_ci        header[2] = (unsigned char)((size >> 8) & 0xff);
23757db96d56Sopenharmony_ci        header[3] = (unsigned char)((size >> 16) & 0xff);
23767db96d56Sopenharmony_ci        header[4] = (unsigned char)((size >> 24) & 0xff);
23777db96d56Sopenharmony_ci        len = 5;
23787db96d56Sopenharmony_ci    }
23797db96d56Sopenharmony_ci    else if (self->proto >= 4) {
23807db96d56Sopenharmony_ci        header[0] = BINBYTES8;
23817db96d56Sopenharmony_ci        _write_size64(header + 1, size);
23827db96d56Sopenharmony_ci        len = 9;
23837db96d56Sopenharmony_ci    }
23847db96d56Sopenharmony_ci    else {
23857db96d56Sopenharmony_ci        PyErr_SetString(PyExc_OverflowError,
23867db96d56Sopenharmony_ci                        "serializing a bytes object larger than 4 GiB "
23877db96d56Sopenharmony_ci                        "requires pickle protocol 4 or higher");
23887db96d56Sopenharmony_ci        return -1;
23897db96d56Sopenharmony_ci    }
23907db96d56Sopenharmony_ci
23917db96d56Sopenharmony_ci    if (_Pickler_write_bytes(self, header, len, data, size, obj) < 0) {
23927db96d56Sopenharmony_ci        return -1;
23937db96d56Sopenharmony_ci    }
23947db96d56Sopenharmony_ci
23957db96d56Sopenharmony_ci    if (memo_put(self, obj) < 0) {
23967db96d56Sopenharmony_ci        return -1;
23977db96d56Sopenharmony_ci    }
23987db96d56Sopenharmony_ci
23997db96d56Sopenharmony_ci    return 0;
24007db96d56Sopenharmony_ci}
24017db96d56Sopenharmony_ci
24027db96d56Sopenharmony_cistatic int
24037db96d56Sopenharmony_cisave_bytes(PicklerObject *self, PyObject *obj)
24047db96d56Sopenharmony_ci{
24057db96d56Sopenharmony_ci    if (self->proto < 3) {
24067db96d56Sopenharmony_ci        /* Older pickle protocols do not have an opcode for pickling bytes
24077db96d56Sopenharmony_ci           objects. Therefore, we need to fake the copy protocol (i.e.,
24087db96d56Sopenharmony_ci           the __reduce__ method) to permit bytes object unpickling.
24097db96d56Sopenharmony_ci
24107db96d56Sopenharmony_ci           Here we use a hack to be compatible with Python 2. Since in Python
24117db96d56Sopenharmony_ci           2 'bytes' is just an alias for 'str' (which has different
24127db96d56Sopenharmony_ci           parameters than the actual bytes object), we use codecs.encode
24137db96d56Sopenharmony_ci           to create the appropriate 'str' object when unpickled using
24147db96d56Sopenharmony_ci           Python 2 *and* the appropriate 'bytes' object when unpickled
24157db96d56Sopenharmony_ci           using Python 3. Again this is a hack and we don't need to do this
24167db96d56Sopenharmony_ci           with newer protocols. */
24177db96d56Sopenharmony_ci        PyObject *reduce_value;
24187db96d56Sopenharmony_ci        int status;
24197db96d56Sopenharmony_ci
24207db96d56Sopenharmony_ci        if (PyBytes_GET_SIZE(obj) == 0) {
24217db96d56Sopenharmony_ci            reduce_value = Py_BuildValue("(O())", (PyObject*)&PyBytes_Type);
24227db96d56Sopenharmony_ci        }
24237db96d56Sopenharmony_ci        else {
24247db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
24257db96d56Sopenharmony_ci            PyObject *unicode_str =
24267db96d56Sopenharmony_ci                PyUnicode_DecodeLatin1(PyBytes_AS_STRING(obj),
24277db96d56Sopenharmony_ci                                       PyBytes_GET_SIZE(obj),
24287db96d56Sopenharmony_ci                                       "strict");
24297db96d56Sopenharmony_ci
24307db96d56Sopenharmony_ci            if (unicode_str == NULL)
24317db96d56Sopenharmony_ci                return -1;
24327db96d56Sopenharmony_ci            reduce_value = Py_BuildValue("(O(OO))",
24337db96d56Sopenharmony_ci                                         st->codecs_encode, unicode_str,
24347db96d56Sopenharmony_ci                                         &_Py_ID(latin1));
24357db96d56Sopenharmony_ci            Py_DECREF(unicode_str);
24367db96d56Sopenharmony_ci        }
24377db96d56Sopenharmony_ci
24387db96d56Sopenharmony_ci        if (reduce_value == NULL)
24397db96d56Sopenharmony_ci            return -1;
24407db96d56Sopenharmony_ci
24417db96d56Sopenharmony_ci        /* save_reduce() will memoize the object automatically. */
24427db96d56Sopenharmony_ci        status = save_reduce(self, reduce_value, obj);
24437db96d56Sopenharmony_ci        Py_DECREF(reduce_value);
24447db96d56Sopenharmony_ci        return status;
24457db96d56Sopenharmony_ci    }
24467db96d56Sopenharmony_ci    else {
24477db96d56Sopenharmony_ci        return _save_bytes_data(self, obj, PyBytes_AS_STRING(obj),
24487db96d56Sopenharmony_ci                                PyBytes_GET_SIZE(obj));
24497db96d56Sopenharmony_ci    }
24507db96d56Sopenharmony_ci}
24517db96d56Sopenharmony_ci
24527db96d56Sopenharmony_cistatic int
24537db96d56Sopenharmony_ci_save_bytearray_data(PicklerObject *self, PyObject *obj, const char *data,
24547db96d56Sopenharmony_ci                     Py_ssize_t size)
24557db96d56Sopenharmony_ci{
24567db96d56Sopenharmony_ci    assert(self->proto >= 5);
24577db96d56Sopenharmony_ci
24587db96d56Sopenharmony_ci    char header[9];
24597db96d56Sopenharmony_ci    Py_ssize_t len;
24607db96d56Sopenharmony_ci
24617db96d56Sopenharmony_ci    if (size < 0)
24627db96d56Sopenharmony_ci        return -1;
24637db96d56Sopenharmony_ci
24647db96d56Sopenharmony_ci    header[0] = BYTEARRAY8;
24657db96d56Sopenharmony_ci    _write_size64(header + 1, size);
24667db96d56Sopenharmony_ci    len = 9;
24677db96d56Sopenharmony_ci
24687db96d56Sopenharmony_ci    if (_Pickler_write_bytes(self, header, len, data, size, obj) < 0) {
24697db96d56Sopenharmony_ci        return -1;
24707db96d56Sopenharmony_ci    }
24717db96d56Sopenharmony_ci
24727db96d56Sopenharmony_ci    if (memo_put(self, obj) < 0) {
24737db96d56Sopenharmony_ci        return -1;
24747db96d56Sopenharmony_ci    }
24757db96d56Sopenharmony_ci
24767db96d56Sopenharmony_ci    return 0;
24777db96d56Sopenharmony_ci}
24787db96d56Sopenharmony_ci
24797db96d56Sopenharmony_cistatic int
24807db96d56Sopenharmony_cisave_bytearray(PicklerObject *self, PyObject *obj)
24817db96d56Sopenharmony_ci{
24827db96d56Sopenharmony_ci    if (self->proto < 5) {
24837db96d56Sopenharmony_ci        /* Older pickle protocols do not have an opcode for pickling
24847db96d56Sopenharmony_ci         * bytearrays. */
24857db96d56Sopenharmony_ci        PyObject *reduce_value = NULL;
24867db96d56Sopenharmony_ci        int status;
24877db96d56Sopenharmony_ci
24887db96d56Sopenharmony_ci        if (PyByteArray_GET_SIZE(obj) == 0) {
24897db96d56Sopenharmony_ci            reduce_value = Py_BuildValue("(O())",
24907db96d56Sopenharmony_ci                                         (PyObject *) &PyByteArray_Type);
24917db96d56Sopenharmony_ci        }
24927db96d56Sopenharmony_ci        else {
24937db96d56Sopenharmony_ci            PyObject *bytes_obj = PyBytes_FromObject(obj);
24947db96d56Sopenharmony_ci            if (bytes_obj != NULL) {
24957db96d56Sopenharmony_ci                reduce_value = Py_BuildValue("(O(O))",
24967db96d56Sopenharmony_ci                                             (PyObject *) &PyByteArray_Type,
24977db96d56Sopenharmony_ci                                             bytes_obj);
24987db96d56Sopenharmony_ci                Py_DECREF(bytes_obj);
24997db96d56Sopenharmony_ci            }
25007db96d56Sopenharmony_ci        }
25017db96d56Sopenharmony_ci        if (reduce_value == NULL)
25027db96d56Sopenharmony_ci            return -1;
25037db96d56Sopenharmony_ci
25047db96d56Sopenharmony_ci        /* save_reduce() will memoize the object automatically. */
25057db96d56Sopenharmony_ci        status = save_reduce(self, reduce_value, obj);
25067db96d56Sopenharmony_ci        Py_DECREF(reduce_value);
25077db96d56Sopenharmony_ci        return status;
25087db96d56Sopenharmony_ci    }
25097db96d56Sopenharmony_ci    else {
25107db96d56Sopenharmony_ci        return _save_bytearray_data(self, obj, PyByteArray_AS_STRING(obj),
25117db96d56Sopenharmony_ci                                    PyByteArray_GET_SIZE(obj));
25127db96d56Sopenharmony_ci    }
25137db96d56Sopenharmony_ci}
25147db96d56Sopenharmony_ci
25157db96d56Sopenharmony_cistatic int
25167db96d56Sopenharmony_cisave_picklebuffer(PicklerObject *self, PyObject *obj)
25177db96d56Sopenharmony_ci{
25187db96d56Sopenharmony_ci    if (self->proto < 5) {
25197db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
25207db96d56Sopenharmony_ci        PyErr_SetString(st->PicklingError,
25217db96d56Sopenharmony_ci                        "PickleBuffer can only pickled with protocol >= 5");
25227db96d56Sopenharmony_ci        return -1;
25237db96d56Sopenharmony_ci    }
25247db96d56Sopenharmony_ci    const Py_buffer* view = PyPickleBuffer_GetBuffer(obj);
25257db96d56Sopenharmony_ci    if (view == NULL) {
25267db96d56Sopenharmony_ci        return -1;
25277db96d56Sopenharmony_ci    }
25287db96d56Sopenharmony_ci    if (view->suboffsets != NULL || !PyBuffer_IsContiguous(view, 'A')) {
25297db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
25307db96d56Sopenharmony_ci        PyErr_SetString(st->PicklingError,
25317db96d56Sopenharmony_ci                        "PickleBuffer can not be pickled when "
25327db96d56Sopenharmony_ci                        "pointing to a non-contiguous buffer");
25337db96d56Sopenharmony_ci        return -1;
25347db96d56Sopenharmony_ci    }
25357db96d56Sopenharmony_ci    int in_band = 1;
25367db96d56Sopenharmony_ci    if (self->buffer_callback != NULL) {
25377db96d56Sopenharmony_ci        PyObject *ret = PyObject_CallOneArg(self->buffer_callback, obj);
25387db96d56Sopenharmony_ci        if (ret == NULL) {
25397db96d56Sopenharmony_ci            return -1;
25407db96d56Sopenharmony_ci        }
25417db96d56Sopenharmony_ci        in_band = PyObject_IsTrue(ret);
25427db96d56Sopenharmony_ci        Py_DECREF(ret);
25437db96d56Sopenharmony_ci        if (in_band == -1) {
25447db96d56Sopenharmony_ci            return -1;
25457db96d56Sopenharmony_ci        }
25467db96d56Sopenharmony_ci    }
25477db96d56Sopenharmony_ci    if (in_band) {
25487db96d56Sopenharmony_ci        /* Write data in-band */
25497db96d56Sopenharmony_ci        if (view->readonly) {
25507db96d56Sopenharmony_ci            return _save_bytes_data(self, obj, (const char*) view->buf,
25517db96d56Sopenharmony_ci                                    view->len);
25527db96d56Sopenharmony_ci        }
25537db96d56Sopenharmony_ci        else {
25547db96d56Sopenharmony_ci            return _save_bytearray_data(self, obj, (const char*) view->buf,
25557db96d56Sopenharmony_ci                                        view->len);
25567db96d56Sopenharmony_ci        }
25577db96d56Sopenharmony_ci    }
25587db96d56Sopenharmony_ci    else {
25597db96d56Sopenharmony_ci        /* Write data out-of-band */
25607db96d56Sopenharmony_ci        const char next_buffer_op = NEXT_BUFFER;
25617db96d56Sopenharmony_ci        if (_Pickler_Write(self, &next_buffer_op, 1) < 0) {
25627db96d56Sopenharmony_ci            return -1;
25637db96d56Sopenharmony_ci        }
25647db96d56Sopenharmony_ci        if (view->readonly) {
25657db96d56Sopenharmony_ci            const char readonly_buffer_op = READONLY_BUFFER;
25667db96d56Sopenharmony_ci            if (_Pickler_Write(self, &readonly_buffer_op, 1) < 0) {
25677db96d56Sopenharmony_ci                return -1;
25687db96d56Sopenharmony_ci            }
25697db96d56Sopenharmony_ci        }
25707db96d56Sopenharmony_ci    }
25717db96d56Sopenharmony_ci    return 0;
25727db96d56Sopenharmony_ci}
25737db96d56Sopenharmony_ci
25747db96d56Sopenharmony_ci/* A copy of PyUnicode_AsRawUnicodeEscapeString() that also translates
25757db96d56Sopenharmony_ci   backslash and newline characters to \uXXXX escapes. */
25767db96d56Sopenharmony_cistatic PyObject *
25777db96d56Sopenharmony_ciraw_unicode_escape(PyObject *obj)
25787db96d56Sopenharmony_ci{
25797db96d56Sopenharmony_ci    char *p;
25807db96d56Sopenharmony_ci    Py_ssize_t i, size;
25817db96d56Sopenharmony_ci    const void *data;
25827db96d56Sopenharmony_ci    unsigned int kind;
25837db96d56Sopenharmony_ci    _PyBytesWriter writer;
25847db96d56Sopenharmony_ci
25857db96d56Sopenharmony_ci    if (PyUnicode_READY(obj))
25867db96d56Sopenharmony_ci        return NULL;
25877db96d56Sopenharmony_ci
25887db96d56Sopenharmony_ci    _PyBytesWriter_Init(&writer);
25897db96d56Sopenharmony_ci
25907db96d56Sopenharmony_ci    size = PyUnicode_GET_LENGTH(obj);
25917db96d56Sopenharmony_ci    data = PyUnicode_DATA(obj);
25927db96d56Sopenharmony_ci    kind = PyUnicode_KIND(obj);
25937db96d56Sopenharmony_ci
25947db96d56Sopenharmony_ci    p = _PyBytesWriter_Alloc(&writer, size);
25957db96d56Sopenharmony_ci    if (p == NULL)
25967db96d56Sopenharmony_ci        goto error;
25977db96d56Sopenharmony_ci    writer.overallocate = 1;
25987db96d56Sopenharmony_ci
25997db96d56Sopenharmony_ci    for (i=0; i < size; i++) {
26007db96d56Sopenharmony_ci        Py_UCS4 ch = PyUnicode_READ(kind, data, i);
26017db96d56Sopenharmony_ci        /* Map 32-bit characters to '\Uxxxxxxxx' */
26027db96d56Sopenharmony_ci        if (ch >= 0x10000) {
26037db96d56Sopenharmony_ci            /* -1: subtract 1 preallocated byte */
26047db96d56Sopenharmony_ci            p = _PyBytesWriter_Prepare(&writer, p, 10-1);
26057db96d56Sopenharmony_ci            if (p == NULL)
26067db96d56Sopenharmony_ci                goto error;
26077db96d56Sopenharmony_ci
26087db96d56Sopenharmony_ci            *p++ = '\\';
26097db96d56Sopenharmony_ci            *p++ = 'U';
26107db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 28) & 0xf];
26117db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 24) & 0xf];
26127db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 20) & 0xf];
26137db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 16) & 0xf];
26147db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 12) & 0xf];
26157db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 8) & 0xf];
26167db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 4) & 0xf];
26177db96d56Sopenharmony_ci            *p++ = Py_hexdigits[ch & 15];
26187db96d56Sopenharmony_ci        }
26197db96d56Sopenharmony_ci        /* Map 16-bit characters, '\\' and '\n' to '\uxxxx' */
26207db96d56Sopenharmony_ci        else if (ch >= 256 ||
26217db96d56Sopenharmony_ci                 ch == '\\' || ch == 0 || ch == '\n' || ch == '\r' ||
26227db96d56Sopenharmony_ci                 ch == 0x1a)
26237db96d56Sopenharmony_ci        {
26247db96d56Sopenharmony_ci            /* -1: subtract 1 preallocated byte */
26257db96d56Sopenharmony_ci            p = _PyBytesWriter_Prepare(&writer, p, 6-1);
26267db96d56Sopenharmony_ci            if (p == NULL)
26277db96d56Sopenharmony_ci                goto error;
26287db96d56Sopenharmony_ci
26297db96d56Sopenharmony_ci            *p++ = '\\';
26307db96d56Sopenharmony_ci            *p++ = 'u';
26317db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 12) & 0xf];
26327db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 8) & 0xf];
26337db96d56Sopenharmony_ci            *p++ = Py_hexdigits[(ch >> 4) & 0xf];
26347db96d56Sopenharmony_ci            *p++ = Py_hexdigits[ch & 15];
26357db96d56Sopenharmony_ci        }
26367db96d56Sopenharmony_ci        /* Copy everything else as-is */
26377db96d56Sopenharmony_ci        else
26387db96d56Sopenharmony_ci            *p++ = (char) ch;
26397db96d56Sopenharmony_ci    }
26407db96d56Sopenharmony_ci
26417db96d56Sopenharmony_ci    return _PyBytesWriter_Finish(&writer, p);
26427db96d56Sopenharmony_ci
26437db96d56Sopenharmony_cierror:
26447db96d56Sopenharmony_ci    _PyBytesWriter_Dealloc(&writer);
26457db96d56Sopenharmony_ci    return NULL;
26467db96d56Sopenharmony_ci}
26477db96d56Sopenharmony_ci
26487db96d56Sopenharmony_cistatic int
26497db96d56Sopenharmony_ciwrite_unicode_binary(PicklerObject *self, PyObject *obj)
26507db96d56Sopenharmony_ci{
26517db96d56Sopenharmony_ci    char header[9];
26527db96d56Sopenharmony_ci    Py_ssize_t len;
26537db96d56Sopenharmony_ci    PyObject *encoded = NULL;
26547db96d56Sopenharmony_ci    Py_ssize_t size;
26557db96d56Sopenharmony_ci    const char *data;
26567db96d56Sopenharmony_ci
26577db96d56Sopenharmony_ci    if (PyUnicode_READY(obj))
26587db96d56Sopenharmony_ci        return -1;
26597db96d56Sopenharmony_ci
26607db96d56Sopenharmony_ci    data = PyUnicode_AsUTF8AndSize(obj, &size);
26617db96d56Sopenharmony_ci    if (data == NULL) {
26627db96d56Sopenharmony_ci        /* Issue #8383: for strings with lone surrogates, fallback on the
26637db96d56Sopenharmony_ci           "surrogatepass" error handler. */
26647db96d56Sopenharmony_ci        PyErr_Clear();
26657db96d56Sopenharmony_ci        encoded = PyUnicode_AsEncodedString(obj, "utf-8", "surrogatepass");
26667db96d56Sopenharmony_ci        if (encoded == NULL)
26677db96d56Sopenharmony_ci            return -1;
26687db96d56Sopenharmony_ci
26697db96d56Sopenharmony_ci        data = PyBytes_AS_STRING(encoded);
26707db96d56Sopenharmony_ci        size = PyBytes_GET_SIZE(encoded);
26717db96d56Sopenharmony_ci    }
26727db96d56Sopenharmony_ci
26737db96d56Sopenharmony_ci    assert(size >= 0);
26747db96d56Sopenharmony_ci    if (size <= 0xff && self->proto >= 4) {
26757db96d56Sopenharmony_ci        header[0] = SHORT_BINUNICODE;
26767db96d56Sopenharmony_ci        header[1] = (unsigned char)(size & 0xff);
26777db96d56Sopenharmony_ci        len = 2;
26787db96d56Sopenharmony_ci    }
26797db96d56Sopenharmony_ci    else if ((size_t)size <= 0xffffffffUL) {
26807db96d56Sopenharmony_ci        header[0] = BINUNICODE;
26817db96d56Sopenharmony_ci        header[1] = (unsigned char)(size & 0xff);
26827db96d56Sopenharmony_ci        header[2] = (unsigned char)((size >> 8) & 0xff);
26837db96d56Sopenharmony_ci        header[3] = (unsigned char)((size >> 16) & 0xff);
26847db96d56Sopenharmony_ci        header[4] = (unsigned char)((size >> 24) & 0xff);
26857db96d56Sopenharmony_ci        len = 5;
26867db96d56Sopenharmony_ci    }
26877db96d56Sopenharmony_ci    else if (self->proto >= 4) {
26887db96d56Sopenharmony_ci        header[0] = BINUNICODE8;
26897db96d56Sopenharmony_ci        _write_size64(header + 1, size);
26907db96d56Sopenharmony_ci        len = 9;
26917db96d56Sopenharmony_ci    }
26927db96d56Sopenharmony_ci    else {
26937db96d56Sopenharmony_ci        PyErr_SetString(PyExc_OverflowError,
26947db96d56Sopenharmony_ci                        "serializing a string larger than 4 GiB "
26957db96d56Sopenharmony_ci                        "requires pickle protocol 4 or higher");
26967db96d56Sopenharmony_ci        Py_XDECREF(encoded);
26977db96d56Sopenharmony_ci        return -1;
26987db96d56Sopenharmony_ci    }
26997db96d56Sopenharmony_ci
27007db96d56Sopenharmony_ci    if (_Pickler_write_bytes(self, header, len, data, size, encoded) < 0) {
27017db96d56Sopenharmony_ci        Py_XDECREF(encoded);
27027db96d56Sopenharmony_ci        return -1;
27037db96d56Sopenharmony_ci    }
27047db96d56Sopenharmony_ci    Py_XDECREF(encoded);
27057db96d56Sopenharmony_ci    return 0;
27067db96d56Sopenharmony_ci}
27077db96d56Sopenharmony_ci
27087db96d56Sopenharmony_cistatic int
27097db96d56Sopenharmony_cisave_unicode(PicklerObject *self, PyObject *obj)
27107db96d56Sopenharmony_ci{
27117db96d56Sopenharmony_ci    if (self->bin) {
27127db96d56Sopenharmony_ci        if (write_unicode_binary(self, obj) < 0)
27137db96d56Sopenharmony_ci            return -1;
27147db96d56Sopenharmony_ci    }
27157db96d56Sopenharmony_ci    else {
27167db96d56Sopenharmony_ci        PyObject *encoded;
27177db96d56Sopenharmony_ci        Py_ssize_t size;
27187db96d56Sopenharmony_ci        const char unicode_op = UNICODE;
27197db96d56Sopenharmony_ci
27207db96d56Sopenharmony_ci        encoded = raw_unicode_escape(obj);
27217db96d56Sopenharmony_ci        if (encoded == NULL)
27227db96d56Sopenharmony_ci            return -1;
27237db96d56Sopenharmony_ci
27247db96d56Sopenharmony_ci        if (_Pickler_Write(self, &unicode_op, 1) < 0) {
27257db96d56Sopenharmony_ci            Py_DECREF(encoded);
27267db96d56Sopenharmony_ci            return -1;
27277db96d56Sopenharmony_ci        }
27287db96d56Sopenharmony_ci
27297db96d56Sopenharmony_ci        size = PyBytes_GET_SIZE(encoded);
27307db96d56Sopenharmony_ci        if (_Pickler_Write(self, PyBytes_AS_STRING(encoded), size) < 0) {
27317db96d56Sopenharmony_ci            Py_DECREF(encoded);
27327db96d56Sopenharmony_ci            return -1;
27337db96d56Sopenharmony_ci        }
27347db96d56Sopenharmony_ci        Py_DECREF(encoded);
27357db96d56Sopenharmony_ci
27367db96d56Sopenharmony_ci        if (_Pickler_Write(self, "\n", 1) < 0)
27377db96d56Sopenharmony_ci            return -1;
27387db96d56Sopenharmony_ci    }
27397db96d56Sopenharmony_ci    if (memo_put(self, obj) < 0)
27407db96d56Sopenharmony_ci        return -1;
27417db96d56Sopenharmony_ci
27427db96d56Sopenharmony_ci    return 0;
27437db96d56Sopenharmony_ci}
27447db96d56Sopenharmony_ci
27457db96d56Sopenharmony_ci/* A helper for save_tuple.  Push the len elements in tuple t on the stack. */
27467db96d56Sopenharmony_cistatic int
27477db96d56Sopenharmony_cistore_tuple_elements(PicklerObject *self, PyObject *t, Py_ssize_t len)
27487db96d56Sopenharmony_ci{
27497db96d56Sopenharmony_ci    Py_ssize_t i;
27507db96d56Sopenharmony_ci
27517db96d56Sopenharmony_ci    assert(PyTuple_Size(t) == len);
27527db96d56Sopenharmony_ci
27537db96d56Sopenharmony_ci    for (i = 0; i < len; i++) {
27547db96d56Sopenharmony_ci        PyObject *element = PyTuple_GET_ITEM(t, i);
27557db96d56Sopenharmony_ci
27567db96d56Sopenharmony_ci        if (element == NULL)
27577db96d56Sopenharmony_ci            return -1;
27587db96d56Sopenharmony_ci        if (save(self, element, 0) < 0)
27597db96d56Sopenharmony_ci            return -1;
27607db96d56Sopenharmony_ci    }
27617db96d56Sopenharmony_ci
27627db96d56Sopenharmony_ci    return 0;
27637db96d56Sopenharmony_ci}
27647db96d56Sopenharmony_ci
27657db96d56Sopenharmony_ci/* Tuples are ubiquitous in the pickle protocols, so many techniques are
27667db96d56Sopenharmony_ci * used across protocols to minimize the space needed to pickle them.
27677db96d56Sopenharmony_ci * Tuples are also the only builtin immutable type that can be recursive
27687db96d56Sopenharmony_ci * (a tuple can be reached from itself), and that requires some subtle
27697db96d56Sopenharmony_ci * magic so that it works in all cases.  IOW, this is a long routine.
27707db96d56Sopenharmony_ci */
27717db96d56Sopenharmony_cistatic int
27727db96d56Sopenharmony_cisave_tuple(PicklerObject *self, PyObject *obj)
27737db96d56Sopenharmony_ci{
27747db96d56Sopenharmony_ci    Py_ssize_t len, i;
27757db96d56Sopenharmony_ci
27767db96d56Sopenharmony_ci    const char mark_op = MARK;
27777db96d56Sopenharmony_ci    const char tuple_op = TUPLE;
27787db96d56Sopenharmony_ci    const char pop_op = POP;
27797db96d56Sopenharmony_ci    const char pop_mark_op = POP_MARK;
27807db96d56Sopenharmony_ci    const char len2opcode[] = {EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3};
27817db96d56Sopenharmony_ci
27827db96d56Sopenharmony_ci    if ((len = PyTuple_Size(obj)) < 0)
27837db96d56Sopenharmony_ci        return -1;
27847db96d56Sopenharmony_ci
27857db96d56Sopenharmony_ci    if (len == 0) {
27867db96d56Sopenharmony_ci        char pdata[2];
27877db96d56Sopenharmony_ci
27887db96d56Sopenharmony_ci        if (self->proto) {
27897db96d56Sopenharmony_ci            pdata[0] = EMPTY_TUPLE;
27907db96d56Sopenharmony_ci            len = 1;
27917db96d56Sopenharmony_ci        }
27927db96d56Sopenharmony_ci        else {
27937db96d56Sopenharmony_ci            pdata[0] = MARK;
27947db96d56Sopenharmony_ci            pdata[1] = TUPLE;
27957db96d56Sopenharmony_ci            len = 2;
27967db96d56Sopenharmony_ci        }
27977db96d56Sopenharmony_ci        if (_Pickler_Write(self, pdata, len) < 0)
27987db96d56Sopenharmony_ci            return -1;
27997db96d56Sopenharmony_ci        return 0;
28007db96d56Sopenharmony_ci    }
28017db96d56Sopenharmony_ci
28027db96d56Sopenharmony_ci    /* The tuple isn't in the memo now.  If it shows up there after
28037db96d56Sopenharmony_ci     * saving the tuple elements, the tuple must be recursive, in
28047db96d56Sopenharmony_ci     * which case we'll pop everything we put on the stack, and fetch
28057db96d56Sopenharmony_ci     * its value from the memo.
28067db96d56Sopenharmony_ci     */
28077db96d56Sopenharmony_ci    if (len <= 3 && self->proto >= 2) {
28087db96d56Sopenharmony_ci        /* Use TUPLE{1,2,3} opcodes. */
28097db96d56Sopenharmony_ci        if (store_tuple_elements(self, obj, len) < 0)
28107db96d56Sopenharmony_ci            return -1;
28117db96d56Sopenharmony_ci
28127db96d56Sopenharmony_ci        if (PyMemoTable_Get(self->memo, obj)) {
28137db96d56Sopenharmony_ci            /* pop the len elements */
28147db96d56Sopenharmony_ci            for (i = 0; i < len; i++)
28157db96d56Sopenharmony_ci                if (_Pickler_Write(self, &pop_op, 1) < 0)
28167db96d56Sopenharmony_ci                    return -1;
28177db96d56Sopenharmony_ci            /* fetch from memo */
28187db96d56Sopenharmony_ci            if (memo_get(self, obj) < 0)
28197db96d56Sopenharmony_ci                return -1;
28207db96d56Sopenharmony_ci
28217db96d56Sopenharmony_ci            return 0;
28227db96d56Sopenharmony_ci        }
28237db96d56Sopenharmony_ci        else { /* Not recursive. */
28247db96d56Sopenharmony_ci            if (_Pickler_Write(self, len2opcode + len, 1) < 0)
28257db96d56Sopenharmony_ci                return -1;
28267db96d56Sopenharmony_ci        }
28277db96d56Sopenharmony_ci        goto memoize;
28287db96d56Sopenharmony_ci    }
28297db96d56Sopenharmony_ci
28307db96d56Sopenharmony_ci    /* proto < 2 and len > 0, or proto >= 2 and len > 3.
28317db96d56Sopenharmony_ci     * Generate MARK e1 e2 ... TUPLE
28327db96d56Sopenharmony_ci     */
28337db96d56Sopenharmony_ci    if (_Pickler_Write(self, &mark_op, 1) < 0)
28347db96d56Sopenharmony_ci        return -1;
28357db96d56Sopenharmony_ci
28367db96d56Sopenharmony_ci    if (store_tuple_elements(self, obj, len) < 0)
28377db96d56Sopenharmony_ci        return -1;
28387db96d56Sopenharmony_ci
28397db96d56Sopenharmony_ci    if (PyMemoTable_Get(self->memo, obj)) {
28407db96d56Sopenharmony_ci        /* pop the stack stuff we pushed */
28417db96d56Sopenharmony_ci        if (self->bin) {
28427db96d56Sopenharmony_ci            if (_Pickler_Write(self, &pop_mark_op, 1) < 0)
28437db96d56Sopenharmony_ci                return -1;
28447db96d56Sopenharmony_ci        }
28457db96d56Sopenharmony_ci        else {
28467db96d56Sopenharmony_ci            /* Note that we pop one more than len, to remove
28477db96d56Sopenharmony_ci             * the MARK too.
28487db96d56Sopenharmony_ci             */
28497db96d56Sopenharmony_ci            for (i = 0; i <= len; i++)
28507db96d56Sopenharmony_ci                if (_Pickler_Write(self, &pop_op, 1) < 0)
28517db96d56Sopenharmony_ci                    return -1;
28527db96d56Sopenharmony_ci        }
28537db96d56Sopenharmony_ci        /* fetch from memo */
28547db96d56Sopenharmony_ci        if (memo_get(self, obj) < 0)
28557db96d56Sopenharmony_ci            return -1;
28567db96d56Sopenharmony_ci
28577db96d56Sopenharmony_ci        return 0;
28587db96d56Sopenharmony_ci    }
28597db96d56Sopenharmony_ci    else { /* Not recursive. */
28607db96d56Sopenharmony_ci        if (_Pickler_Write(self, &tuple_op, 1) < 0)
28617db96d56Sopenharmony_ci            return -1;
28627db96d56Sopenharmony_ci    }
28637db96d56Sopenharmony_ci
28647db96d56Sopenharmony_ci  memoize:
28657db96d56Sopenharmony_ci    if (memo_put(self, obj) < 0)
28667db96d56Sopenharmony_ci        return -1;
28677db96d56Sopenharmony_ci
28687db96d56Sopenharmony_ci    return 0;
28697db96d56Sopenharmony_ci}
28707db96d56Sopenharmony_ci
28717db96d56Sopenharmony_ci/* iter is an iterator giving items, and we batch up chunks of
28727db96d56Sopenharmony_ci *     MARK item item ... item APPENDS
28737db96d56Sopenharmony_ci * opcode sequences.  Calling code should have arranged to first create an
28747db96d56Sopenharmony_ci * empty list, or list-like object, for the APPENDS to operate on.
28757db96d56Sopenharmony_ci * Returns 0 on success, <0 on error.
28767db96d56Sopenharmony_ci */
28777db96d56Sopenharmony_cistatic int
28787db96d56Sopenharmony_cibatch_list(PicklerObject *self, PyObject *iter)
28797db96d56Sopenharmony_ci{
28807db96d56Sopenharmony_ci    PyObject *obj = NULL;
28817db96d56Sopenharmony_ci    PyObject *firstitem = NULL;
28827db96d56Sopenharmony_ci    int i, n;
28837db96d56Sopenharmony_ci
28847db96d56Sopenharmony_ci    const char mark_op = MARK;
28857db96d56Sopenharmony_ci    const char append_op = APPEND;
28867db96d56Sopenharmony_ci    const char appends_op = APPENDS;
28877db96d56Sopenharmony_ci
28887db96d56Sopenharmony_ci    assert(iter != NULL);
28897db96d56Sopenharmony_ci
28907db96d56Sopenharmony_ci    /* XXX: I think this function could be made faster by avoiding the
28917db96d56Sopenharmony_ci       iterator interface and fetching objects directly from list using
28927db96d56Sopenharmony_ci       PyList_GET_ITEM.
28937db96d56Sopenharmony_ci    */
28947db96d56Sopenharmony_ci
28957db96d56Sopenharmony_ci    if (self->proto == 0) {
28967db96d56Sopenharmony_ci        /* APPENDS isn't available; do one at a time. */
28977db96d56Sopenharmony_ci        for (;;) {
28987db96d56Sopenharmony_ci            obj = PyIter_Next(iter);
28997db96d56Sopenharmony_ci            if (obj == NULL) {
29007db96d56Sopenharmony_ci                if (PyErr_Occurred())
29017db96d56Sopenharmony_ci                    return -1;
29027db96d56Sopenharmony_ci                break;
29037db96d56Sopenharmony_ci            }
29047db96d56Sopenharmony_ci            i = save(self, obj, 0);
29057db96d56Sopenharmony_ci            Py_DECREF(obj);
29067db96d56Sopenharmony_ci            if (i < 0)
29077db96d56Sopenharmony_ci                return -1;
29087db96d56Sopenharmony_ci            if (_Pickler_Write(self, &append_op, 1) < 0)
29097db96d56Sopenharmony_ci                return -1;
29107db96d56Sopenharmony_ci        }
29117db96d56Sopenharmony_ci        return 0;
29127db96d56Sopenharmony_ci    }
29137db96d56Sopenharmony_ci
29147db96d56Sopenharmony_ci    /* proto > 0:  write in batches of BATCHSIZE. */
29157db96d56Sopenharmony_ci    do {
29167db96d56Sopenharmony_ci        /* Get first item */
29177db96d56Sopenharmony_ci        firstitem = PyIter_Next(iter);
29187db96d56Sopenharmony_ci        if (firstitem == NULL) {
29197db96d56Sopenharmony_ci            if (PyErr_Occurred())
29207db96d56Sopenharmony_ci                goto error;
29217db96d56Sopenharmony_ci
29227db96d56Sopenharmony_ci            /* nothing more to add */
29237db96d56Sopenharmony_ci            break;
29247db96d56Sopenharmony_ci        }
29257db96d56Sopenharmony_ci
29267db96d56Sopenharmony_ci        /* Try to get a second item */
29277db96d56Sopenharmony_ci        obj = PyIter_Next(iter);
29287db96d56Sopenharmony_ci        if (obj == NULL) {
29297db96d56Sopenharmony_ci            if (PyErr_Occurred())
29307db96d56Sopenharmony_ci                goto error;
29317db96d56Sopenharmony_ci
29327db96d56Sopenharmony_ci            /* Only one item to write */
29337db96d56Sopenharmony_ci            if (save(self, firstitem, 0) < 0)
29347db96d56Sopenharmony_ci                goto error;
29357db96d56Sopenharmony_ci            if (_Pickler_Write(self, &append_op, 1) < 0)
29367db96d56Sopenharmony_ci                goto error;
29377db96d56Sopenharmony_ci            Py_CLEAR(firstitem);
29387db96d56Sopenharmony_ci            break;
29397db96d56Sopenharmony_ci        }
29407db96d56Sopenharmony_ci
29417db96d56Sopenharmony_ci        /* More than one item to write */
29427db96d56Sopenharmony_ci
29437db96d56Sopenharmony_ci        /* Pump out MARK, items, APPENDS. */
29447db96d56Sopenharmony_ci        if (_Pickler_Write(self, &mark_op, 1) < 0)
29457db96d56Sopenharmony_ci            goto error;
29467db96d56Sopenharmony_ci
29477db96d56Sopenharmony_ci        if (save(self, firstitem, 0) < 0)
29487db96d56Sopenharmony_ci            goto error;
29497db96d56Sopenharmony_ci        Py_CLEAR(firstitem);
29507db96d56Sopenharmony_ci        n = 1;
29517db96d56Sopenharmony_ci
29527db96d56Sopenharmony_ci        /* Fetch and save up to BATCHSIZE items */
29537db96d56Sopenharmony_ci        while (obj) {
29547db96d56Sopenharmony_ci            if (save(self, obj, 0) < 0)
29557db96d56Sopenharmony_ci                goto error;
29567db96d56Sopenharmony_ci            Py_CLEAR(obj);
29577db96d56Sopenharmony_ci            n += 1;
29587db96d56Sopenharmony_ci
29597db96d56Sopenharmony_ci            if (n == BATCHSIZE)
29607db96d56Sopenharmony_ci                break;
29617db96d56Sopenharmony_ci
29627db96d56Sopenharmony_ci            obj = PyIter_Next(iter);
29637db96d56Sopenharmony_ci            if (obj == NULL) {
29647db96d56Sopenharmony_ci                if (PyErr_Occurred())
29657db96d56Sopenharmony_ci                    goto error;
29667db96d56Sopenharmony_ci                break;
29677db96d56Sopenharmony_ci            }
29687db96d56Sopenharmony_ci        }
29697db96d56Sopenharmony_ci
29707db96d56Sopenharmony_ci        if (_Pickler_Write(self, &appends_op, 1) < 0)
29717db96d56Sopenharmony_ci            goto error;
29727db96d56Sopenharmony_ci
29737db96d56Sopenharmony_ci    } while (n == BATCHSIZE);
29747db96d56Sopenharmony_ci    return 0;
29757db96d56Sopenharmony_ci
29767db96d56Sopenharmony_ci  error:
29777db96d56Sopenharmony_ci    Py_XDECREF(firstitem);
29787db96d56Sopenharmony_ci    Py_XDECREF(obj);
29797db96d56Sopenharmony_ci    return -1;
29807db96d56Sopenharmony_ci}
29817db96d56Sopenharmony_ci
29827db96d56Sopenharmony_ci/* This is a variant of batch_list() above, specialized for lists (with no
29837db96d56Sopenharmony_ci * support for list subclasses). Like batch_list(), we batch up chunks of
29847db96d56Sopenharmony_ci *     MARK item item ... item APPENDS
29857db96d56Sopenharmony_ci * opcode sequences.  Calling code should have arranged to first create an
29867db96d56Sopenharmony_ci * empty list, or list-like object, for the APPENDS to operate on.
29877db96d56Sopenharmony_ci * Returns 0 on success, -1 on error.
29887db96d56Sopenharmony_ci *
29897db96d56Sopenharmony_ci * This version is considerably faster than batch_list(), if less general.
29907db96d56Sopenharmony_ci *
29917db96d56Sopenharmony_ci * Note that this only works for protocols > 0.
29927db96d56Sopenharmony_ci */
29937db96d56Sopenharmony_cistatic int
29947db96d56Sopenharmony_cibatch_list_exact(PicklerObject *self, PyObject *obj)
29957db96d56Sopenharmony_ci{
29967db96d56Sopenharmony_ci    PyObject *item = NULL;
29977db96d56Sopenharmony_ci    Py_ssize_t this_batch, total;
29987db96d56Sopenharmony_ci
29997db96d56Sopenharmony_ci    const char append_op = APPEND;
30007db96d56Sopenharmony_ci    const char appends_op = APPENDS;
30017db96d56Sopenharmony_ci    const char mark_op = MARK;
30027db96d56Sopenharmony_ci
30037db96d56Sopenharmony_ci    assert(obj != NULL);
30047db96d56Sopenharmony_ci    assert(self->proto > 0);
30057db96d56Sopenharmony_ci    assert(PyList_CheckExact(obj));
30067db96d56Sopenharmony_ci
30077db96d56Sopenharmony_ci    if (PyList_GET_SIZE(obj) == 1) {
30087db96d56Sopenharmony_ci        item = PyList_GET_ITEM(obj, 0);
30097db96d56Sopenharmony_ci        Py_INCREF(item);
30107db96d56Sopenharmony_ci        int err = save(self, item, 0);
30117db96d56Sopenharmony_ci        Py_DECREF(item);
30127db96d56Sopenharmony_ci        if (err < 0)
30137db96d56Sopenharmony_ci            return -1;
30147db96d56Sopenharmony_ci        if (_Pickler_Write(self, &append_op, 1) < 0)
30157db96d56Sopenharmony_ci            return -1;
30167db96d56Sopenharmony_ci        return 0;
30177db96d56Sopenharmony_ci    }
30187db96d56Sopenharmony_ci
30197db96d56Sopenharmony_ci    /* Write in batches of BATCHSIZE. */
30207db96d56Sopenharmony_ci    total = 0;
30217db96d56Sopenharmony_ci    do {
30227db96d56Sopenharmony_ci        this_batch = 0;
30237db96d56Sopenharmony_ci        if (_Pickler_Write(self, &mark_op, 1) < 0)
30247db96d56Sopenharmony_ci            return -1;
30257db96d56Sopenharmony_ci        while (total < PyList_GET_SIZE(obj)) {
30267db96d56Sopenharmony_ci            item = PyList_GET_ITEM(obj, total);
30277db96d56Sopenharmony_ci            Py_INCREF(item);
30287db96d56Sopenharmony_ci            int err = save(self, item, 0);
30297db96d56Sopenharmony_ci            Py_DECREF(item);
30307db96d56Sopenharmony_ci            if (err < 0)
30317db96d56Sopenharmony_ci                return -1;
30327db96d56Sopenharmony_ci            total++;
30337db96d56Sopenharmony_ci            if (++this_batch == BATCHSIZE)
30347db96d56Sopenharmony_ci                break;
30357db96d56Sopenharmony_ci        }
30367db96d56Sopenharmony_ci        if (_Pickler_Write(self, &appends_op, 1) < 0)
30377db96d56Sopenharmony_ci            return -1;
30387db96d56Sopenharmony_ci
30397db96d56Sopenharmony_ci    } while (total < PyList_GET_SIZE(obj));
30407db96d56Sopenharmony_ci
30417db96d56Sopenharmony_ci    return 0;
30427db96d56Sopenharmony_ci}
30437db96d56Sopenharmony_ci
30447db96d56Sopenharmony_cistatic int
30457db96d56Sopenharmony_cisave_list(PicklerObject *self, PyObject *obj)
30467db96d56Sopenharmony_ci{
30477db96d56Sopenharmony_ci    char header[3];
30487db96d56Sopenharmony_ci    Py_ssize_t len;
30497db96d56Sopenharmony_ci    int status = 0;
30507db96d56Sopenharmony_ci
30517db96d56Sopenharmony_ci    if (self->fast && !fast_save_enter(self, obj))
30527db96d56Sopenharmony_ci        goto error;
30537db96d56Sopenharmony_ci
30547db96d56Sopenharmony_ci    /* Create an empty list. */
30557db96d56Sopenharmony_ci    if (self->bin) {
30567db96d56Sopenharmony_ci        header[0] = EMPTY_LIST;
30577db96d56Sopenharmony_ci        len = 1;
30587db96d56Sopenharmony_ci    }
30597db96d56Sopenharmony_ci    else {
30607db96d56Sopenharmony_ci        header[0] = MARK;
30617db96d56Sopenharmony_ci        header[1] = LIST;
30627db96d56Sopenharmony_ci        len = 2;
30637db96d56Sopenharmony_ci    }
30647db96d56Sopenharmony_ci
30657db96d56Sopenharmony_ci    if (_Pickler_Write(self, header, len) < 0)
30667db96d56Sopenharmony_ci        goto error;
30677db96d56Sopenharmony_ci
30687db96d56Sopenharmony_ci    /* Get list length, and bow out early if empty. */
30697db96d56Sopenharmony_ci    if ((len = PyList_Size(obj)) < 0)
30707db96d56Sopenharmony_ci        goto error;
30717db96d56Sopenharmony_ci
30727db96d56Sopenharmony_ci    if (memo_put(self, obj) < 0)
30737db96d56Sopenharmony_ci        goto error;
30747db96d56Sopenharmony_ci
30757db96d56Sopenharmony_ci    if (len != 0) {
30767db96d56Sopenharmony_ci        /* Materialize the list elements. */
30777db96d56Sopenharmony_ci        if (PyList_CheckExact(obj) && self->proto > 0) {
30787db96d56Sopenharmony_ci            if (_Py_EnterRecursiveCall(" while pickling an object"))
30797db96d56Sopenharmony_ci                goto error;
30807db96d56Sopenharmony_ci            status = batch_list_exact(self, obj);
30817db96d56Sopenharmony_ci            _Py_LeaveRecursiveCall();
30827db96d56Sopenharmony_ci        } else {
30837db96d56Sopenharmony_ci            PyObject *iter = PyObject_GetIter(obj);
30847db96d56Sopenharmony_ci            if (iter == NULL)
30857db96d56Sopenharmony_ci                goto error;
30867db96d56Sopenharmony_ci
30877db96d56Sopenharmony_ci            if (_Py_EnterRecursiveCall(" while pickling an object")) {
30887db96d56Sopenharmony_ci                Py_DECREF(iter);
30897db96d56Sopenharmony_ci                goto error;
30907db96d56Sopenharmony_ci            }
30917db96d56Sopenharmony_ci            status = batch_list(self, iter);
30927db96d56Sopenharmony_ci            _Py_LeaveRecursiveCall();
30937db96d56Sopenharmony_ci            Py_DECREF(iter);
30947db96d56Sopenharmony_ci        }
30957db96d56Sopenharmony_ci    }
30967db96d56Sopenharmony_ci    if (0) {
30977db96d56Sopenharmony_ci  error:
30987db96d56Sopenharmony_ci        status = -1;
30997db96d56Sopenharmony_ci    }
31007db96d56Sopenharmony_ci
31017db96d56Sopenharmony_ci    if (self->fast && !fast_save_leave(self, obj))
31027db96d56Sopenharmony_ci        status = -1;
31037db96d56Sopenharmony_ci
31047db96d56Sopenharmony_ci    return status;
31057db96d56Sopenharmony_ci}
31067db96d56Sopenharmony_ci
31077db96d56Sopenharmony_ci/* iter is an iterator giving (key, value) pairs, and we batch up chunks of
31087db96d56Sopenharmony_ci *     MARK key value ... key value SETITEMS
31097db96d56Sopenharmony_ci * opcode sequences.  Calling code should have arranged to first create an
31107db96d56Sopenharmony_ci * empty dict, or dict-like object, for the SETITEMS to operate on.
31117db96d56Sopenharmony_ci * Returns 0 on success, <0 on error.
31127db96d56Sopenharmony_ci *
31137db96d56Sopenharmony_ci * This is very much like batch_list().  The difference between saving
31147db96d56Sopenharmony_ci * elements directly, and picking apart two-tuples, is so long-winded at
31157db96d56Sopenharmony_ci * the C level, though, that attempts to combine these routines were too
31167db96d56Sopenharmony_ci * ugly to bear.
31177db96d56Sopenharmony_ci */
31187db96d56Sopenharmony_cistatic int
31197db96d56Sopenharmony_cibatch_dict(PicklerObject *self, PyObject *iter)
31207db96d56Sopenharmony_ci{
31217db96d56Sopenharmony_ci    PyObject *obj = NULL;
31227db96d56Sopenharmony_ci    PyObject *firstitem = NULL;
31237db96d56Sopenharmony_ci    int i, n;
31247db96d56Sopenharmony_ci
31257db96d56Sopenharmony_ci    const char mark_op = MARK;
31267db96d56Sopenharmony_ci    const char setitem_op = SETITEM;
31277db96d56Sopenharmony_ci    const char setitems_op = SETITEMS;
31287db96d56Sopenharmony_ci
31297db96d56Sopenharmony_ci    assert(iter != NULL);
31307db96d56Sopenharmony_ci
31317db96d56Sopenharmony_ci    if (self->proto == 0) {
31327db96d56Sopenharmony_ci        /* SETITEMS isn't available; do one at a time. */
31337db96d56Sopenharmony_ci        for (;;) {
31347db96d56Sopenharmony_ci            obj = PyIter_Next(iter);
31357db96d56Sopenharmony_ci            if (obj == NULL) {
31367db96d56Sopenharmony_ci                if (PyErr_Occurred())
31377db96d56Sopenharmony_ci                    return -1;
31387db96d56Sopenharmony_ci                break;
31397db96d56Sopenharmony_ci            }
31407db96d56Sopenharmony_ci            if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 2) {
31417db96d56Sopenharmony_ci                PyErr_SetString(PyExc_TypeError, "dict items "
31427db96d56Sopenharmony_ci                                "iterator must return 2-tuples");
31437db96d56Sopenharmony_ci                return -1;
31447db96d56Sopenharmony_ci            }
31457db96d56Sopenharmony_ci            i = save(self, PyTuple_GET_ITEM(obj, 0), 0);
31467db96d56Sopenharmony_ci            if (i >= 0)
31477db96d56Sopenharmony_ci                i = save(self, PyTuple_GET_ITEM(obj, 1), 0);
31487db96d56Sopenharmony_ci            Py_DECREF(obj);
31497db96d56Sopenharmony_ci            if (i < 0)
31507db96d56Sopenharmony_ci                return -1;
31517db96d56Sopenharmony_ci            if (_Pickler_Write(self, &setitem_op, 1) < 0)
31527db96d56Sopenharmony_ci                return -1;
31537db96d56Sopenharmony_ci        }
31547db96d56Sopenharmony_ci        return 0;
31557db96d56Sopenharmony_ci    }
31567db96d56Sopenharmony_ci
31577db96d56Sopenharmony_ci    /* proto > 0:  write in batches of BATCHSIZE. */
31587db96d56Sopenharmony_ci    do {
31597db96d56Sopenharmony_ci        /* Get first item */
31607db96d56Sopenharmony_ci        firstitem = PyIter_Next(iter);
31617db96d56Sopenharmony_ci        if (firstitem == NULL) {
31627db96d56Sopenharmony_ci            if (PyErr_Occurred())
31637db96d56Sopenharmony_ci                goto error;
31647db96d56Sopenharmony_ci
31657db96d56Sopenharmony_ci            /* nothing more to add */
31667db96d56Sopenharmony_ci            break;
31677db96d56Sopenharmony_ci        }
31687db96d56Sopenharmony_ci        if (!PyTuple_Check(firstitem) || PyTuple_Size(firstitem) != 2) {
31697db96d56Sopenharmony_ci            PyErr_SetString(PyExc_TypeError, "dict items "
31707db96d56Sopenharmony_ci                                "iterator must return 2-tuples");
31717db96d56Sopenharmony_ci            goto error;
31727db96d56Sopenharmony_ci        }
31737db96d56Sopenharmony_ci
31747db96d56Sopenharmony_ci        /* Try to get a second item */
31757db96d56Sopenharmony_ci        obj = PyIter_Next(iter);
31767db96d56Sopenharmony_ci        if (obj == NULL) {
31777db96d56Sopenharmony_ci            if (PyErr_Occurred())
31787db96d56Sopenharmony_ci                goto error;
31797db96d56Sopenharmony_ci
31807db96d56Sopenharmony_ci            /* Only one item to write */
31817db96d56Sopenharmony_ci            if (save(self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0)
31827db96d56Sopenharmony_ci                goto error;
31837db96d56Sopenharmony_ci            if (save(self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0)
31847db96d56Sopenharmony_ci                goto error;
31857db96d56Sopenharmony_ci            if (_Pickler_Write(self, &setitem_op, 1) < 0)
31867db96d56Sopenharmony_ci                goto error;
31877db96d56Sopenharmony_ci            Py_CLEAR(firstitem);
31887db96d56Sopenharmony_ci            break;
31897db96d56Sopenharmony_ci        }
31907db96d56Sopenharmony_ci
31917db96d56Sopenharmony_ci        /* More than one item to write */
31927db96d56Sopenharmony_ci
31937db96d56Sopenharmony_ci        /* Pump out MARK, items, SETITEMS. */
31947db96d56Sopenharmony_ci        if (_Pickler_Write(self, &mark_op, 1) < 0)
31957db96d56Sopenharmony_ci            goto error;
31967db96d56Sopenharmony_ci
31977db96d56Sopenharmony_ci        if (save(self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0)
31987db96d56Sopenharmony_ci            goto error;
31997db96d56Sopenharmony_ci        if (save(self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0)
32007db96d56Sopenharmony_ci            goto error;
32017db96d56Sopenharmony_ci        Py_CLEAR(firstitem);
32027db96d56Sopenharmony_ci        n = 1;
32037db96d56Sopenharmony_ci
32047db96d56Sopenharmony_ci        /* Fetch and save up to BATCHSIZE items */
32057db96d56Sopenharmony_ci        while (obj) {
32067db96d56Sopenharmony_ci            if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 2) {
32077db96d56Sopenharmony_ci                PyErr_SetString(PyExc_TypeError, "dict items "
32087db96d56Sopenharmony_ci                    "iterator must return 2-tuples");
32097db96d56Sopenharmony_ci                goto error;
32107db96d56Sopenharmony_ci            }
32117db96d56Sopenharmony_ci            if (save(self, PyTuple_GET_ITEM(obj, 0), 0) < 0 ||
32127db96d56Sopenharmony_ci                save(self, PyTuple_GET_ITEM(obj, 1), 0) < 0)
32137db96d56Sopenharmony_ci                goto error;
32147db96d56Sopenharmony_ci            Py_CLEAR(obj);
32157db96d56Sopenharmony_ci            n += 1;
32167db96d56Sopenharmony_ci
32177db96d56Sopenharmony_ci            if (n == BATCHSIZE)
32187db96d56Sopenharmony_ci                break;
32197db96d56Sopenharmony_ci
32207db96d56Sopenharmony_ci            obj = PyIter_Next(iter);
32217db96d56Sopenharmony_ci            if (obj == NULL) {
32227db96d56Sopenharmony_ci                if (PyErr_Occurred())
32237db96d56Sopenharmony_ci                    goto error;
32247db96d56Sopenharmony_ci                break;
32257db96d56Sopenharmony_ci            }
32267db96d56Sopenharmony_ci        }
32277db96d56Sopenharmony_ci
32287db96d56Sopenharmony_ci        if (_Pickler_Write(self, &setitems_op, 1) < 0)
32297db96d56Sopenharmony_ci            goto error;
32307db96d56Sopenharmony_ci
32317db96d56Sopenharmony_ci    } while (n == BATCHSIZE);
32327db96d56Sopenharmony_ci    return 0;
32337db96d56Sopenharmony_ci
32347db96d56Sopenharmony_ci  error:
32357db96d56Sopenharmony_ci    Py_XDECREF(firstitem);
32367db96d56Sopenharmony_ci    Py_XDECREF(obj);
32377db96d56Sopenharmony_ci    return -1;
32387db96d56Sopenharmony_ci}
32397db96d56Sopenharmony_ci
32407db96d56Sopenharmony_ci/* This is a variant of batch_dict() above that specializes for dicts, with no
32417db96d56Sopenharmony_ci * support for dict subclasses. Like batch_dict(), we batch up chunks of
32427db96d56Sopenharmony_ci *     MARK key value ... key value SETITEMS
32437db96d56Sopenharmony_ci * opcode sequences.  Calling code should have arranged to first create an
32447db96d56Sopenharmony_ci * empty dict, or dict-like object, for the SETITEMS to operate on.
32457db96d56Sopenharmony_ci * Returns 0 on success, -1 on error.
32467db96d56Sopenharmony_ci *
32477db96d56Sopenharmony_ci * Note that this currently doesn't work for protocol 0.
32487db96d56Sopenharmony_ci */
32497db96d56Sopenharmony_cistatic int
32507db96d56Sopenharmony_cibatch_dict_exact(PicklerObject *self, PyObject *obj)
32517db96d56Sopenharmony_ci{
32527db96d56Sopenharmony_ci    PyObject *key = NULL, *value = NULL;
32537db96d56Sopenharmony_ci    int i;
32547db96d56Sopenharmony_ci    Py_ssize_t dict_size, ppos = 0;
32557db96d56Sopenharmony_ci
32567db96d56Sopenharmony_ci    const char mark_op = MARK;
32577db96d56Sopenharmony_ci    const char setitem_op = SETITEM;
32587db96d56Sopenharmony_ci    const char setitems_op = SETITEMS;
32597db96d56Sopenharmony_ci
32607db96d56Sopenharmony_ci    assert(obj != NULL && PyDict_CheckExact(obj));
32617db96d56Sopenharmony_ci    assert(self->proto > 0);
32627db96d56Sopenharmony_ci
32637db96d56Sopenharmony_ci    dict_size = PyDict_GET_SIZE(obj);
32647db96d56Sopenharmony_ci
32657db96d56Sopenharmony_ci    /* Special-case len(d) == 1 to save space. */
32667db96d56Sopenharmony_ci    if (dict_size == 1) {
32677db96d56Sopenharmony_ci        PyDict_Next(obj, &ppos, &key, &value);
32687db96d56Sopenharmony_ci        Py_INCREF(key);
32697db96d56Sopenharmony_ci        Py_INCREF(value);
32707db96d56Sopenharmony_ci        if (save(self, key, 0) < 0) {
32717db96d56Sopenharmony_ci            goto error;
32727db96d56Sopenharmony_ci        }
32737db96d56Sopenharmony_ci        if (save(self, value, 0) < 0) {
32747db96d56Sopenharmony_ci            goto error;
32757db96d56Sopenharmony_ci        }
32767db96d56Sopenharmony_ci        Py_CLEAR(key);
32777db96d56Sopenharmony_ci        Py_CLEAR(value);
32787db96d56Sopenharmony_ci        if (_Pickler_Write(self, &setitem_op, 1) < 0)
32797db96d56Sopenharmony_ci            return -1;
32807db96d56Sopenharmony_ci        return 0;
32817db96d56Sopenharmony_ci    }
32827db96d56Sopenharmony_ci
32837db96d56Sopenharmony_ci    /* Write in batches of BATCHSIZE. */
32847db96d56Sopenharmony_ci    do {
32857db96d56Sopenharmony_ci        i = 0;
32867db96d56Sopenharmony_ci        if (_Pickler_Write(self, &mark_op, 1) < 0)
32877db96d56Sopenharmony_ci            return -1;
32887db96d56Sopenharmony_ci        while (PyDict_Next(obj, &ppos, &key, &value)) {
32897db96d56Sopenharmony_ci            Py_INCREF(key);
32907db96d56Sopenharmony_ci            Py_INCREF(value);
32917db96d56Sopenharmony_ci            if (save(self, key, 0) < 0) {
32927db96d56Sopenharmony_ci                goto error;
32937db96d56Sopenharmony_ci            }
32947db96d56Sopenharmony_ci            if (save(self, value, 0) < 0) {
32957db96d56Sopenharmony_ci                goto error;
32967db96d56Sopenharmony_ci            }
32977db96d56Sopenharmony_ci            Py_CLEAR(key);
32987db96d56Sopenharmony_ci            Py_CLEAR(value);
32997db96d56Sopenharmony_ci            if (++i == BATCHSIZE)
33007db96d56Sopenharmony_ci                break;
33017db96d56Sopenharmony_ci        }
33027db96d56Sopenharmony_ci        if (_Pickler_Write(self, &setitems_op, 1) < 0)
33037db96d56Sopenharmony_ci            return -1;
33047db96d56Sopenharmony_ci        if (PyDict_GET_SIZE(obj) != dict_size) {
33057db96d56Sopenharmony_ci            PyErr_Format(
33067db96d56Sopenharmony_ci                PyExc_RuntimeError,
33077db96d56Sopenharmony_ci                "dictionary changed size during iteration");
33087db96d56Sopenharmony_ci            return -1;
33097db96d56Sopenharmony_ci        }
33107db96d56Sopenharmony_ci
33117db96d56Sopenharmony_ci    } while (i == BATCHSIZE);
33127db96d56Sopenharmony_ci    return 0;
33137db96d56Sopenharmony_cierror:
33147db96d56Sopenharmony_ci    Py_XDECREF(key);
33157db96d56Sopenharmony_ci    Py_XDECREF(value);
33167db96d56Sopenharmony_ci    return -1;
33177db96d56Sopenharmony_ci}
33187db96d56Sopenharmony_ci
33197db96d56Sopenharmony_cistatic int
33207db96d56Sopenharmony_cisave_dict(PicklerObject *self, PyObject *obj)
33217db96d56Sopenharmony_ci{
33227db96d56Sopenharmony_ci    PyObject *items, *iter;
33237db96d56Sopenharmony_ci    char header[3];
33247db96d56Sopenharmony_ci    Py_ssize_t len;
33257db96d56Sopenharmony_ci    int status = 0;
33267db96d56Sopenharmony_ci    assert(PyDict_Check(obj));
33277db96d56Sopenharmony_ci
33287db96d56Sopenharmony_ci    if (self->fast && !fast_save_enter(self, obj))
33297db96d56Sopenharmony_ci        goto error;
33307db96d56Sopenharmony_ci
33317db96d56Sopenharmony_ci    /* Create an empty dict. */
33327db96d56Sopenharmony_ci    if (self->bin) {
33337db96d56Sopenharmony_ci        header[0] = EMPTY_DICT;
33347db96d56Sopenharmony_ci        len = 1;
33357db96d56Sopenharmony_ci    }
33367db96d56Sopenharmony_ci    else {
33377db96d56Sopenharmony_ci        header[0] = MARK;
33387db96d56Sopenharmony_ci        header[1] = DICT;
33397db96d56Sopenharmony_ci        len = 2;
33407db96d56Sopenharmony_ci    }
33417db96d56Sopenharmony_ci
33427db96d56Sopenharmony_ci    if (_Pickler_Write(self, header, len) < 0)
33437db96d56Sopenharmony_ci        goto error;
33447db96d56Sopenharmony_ci
33457db96d56Sopenharmony_ci    if (memo_put(self, obj) < 0)
33467db96d56Sopenharmony_ci        goto error;
33477db96d56Sopenharmony_ci
33487db96d56Sopenharmony_ci    if (PyDict_GET_SIZE(obj)) {
33497db96d56Sopenharmony_ci        /* Save the dict items. */
33507db96d56Sopenharmony_ci        if (PyDict_CheckExact(obj) && self->proto > 0) {
33517db96d56Sopenharmony_ci            /* We can take certain shortcuts if we know this is a dict and
33527db96d56Sopenharmony_ci               not a dict subclass. */
33537db96d56Sopenharmony_ci            if (_Py_EnterRecursiveCall(" while pickling an object"))
33547db96d56Sopenharmony_ci                goto error;
33557db96d56Sopenharmony_ci            status = batch_dict_exact(self, obj);
33567db96d56Sopenharmony_ci            _Py_LeaveRecursiveCall();
33577db96d56Sopenharmony_ci        } else {
33587db96d56Sopenharmony_ci            items = PyObject_CallMethodNoArgs(obj, &_Py_ID(items));
33597db96d56Sopenharmony_ci            if (items == NULL)
33607db96d56Sopenharmony_ci                goto error;
33617db96d56Sopenharmony_ci            iter = PyObject_GetIter(items);
33627db96d56Sopenharmony_ci            Py_DECREF(items);
33637db96d56Sopenharmony_ci            if (iter == NULL)
33647db96d56Sopenharmony_ci                goto error;
33657db96d56Sopenharmony_ci            if (_Py_EnterRecursiveCall(" while pickling an object")) {
33667db96d56Sopenharmony_ci                Py_DECREF(iter);
33677db96d56Sopenharmony_ci                goto error;
33687db96d56Sopenharmony_ci            }
33697db96d56Sopenharmony_ci            status = batch_dict(self, iter);
33707db96d56Sopenharmony_ci            _Py_LeaveRecursiveCall();
33717db96d56Sopenharmony_ci            Py_DECREF(iter);
33727db96d56Sopenharmony_ci        }
33737db96d56Sopenharmony_ci    }
33747db96d56Sopenharmony_ci
33757db96d56Sopenharmony_ci    if (0) {
33767db96d56Sopenharmony_ci  error:
33777db96d56Sopenharmony_ci        status = -1;
33787db96d56Sopenharmony_ci    }
33797db96d56Sopenharmony_ci
33807db96d56Sopenharmony_ci    if (self->fast && !fast_save_leave(self, obj))
33817db96d56Sopenharmony_ci        status = -1;
33827db96d56Sopenharmony_ci
33837db96d56Sopenharmony_ci    return status;
33847db96d56Sopenharmony_ci}
33857db96d56Sopenharmony_ci
33867db96d56Sopenharmony_cistatic int
33877db96d56Sopenharmony_cisave_set(PicklerObject *self, PyObject *obj)
33887db96d56Sopenharmony_ci{
33897db96d56Sopenharmony_ci    PyObject *item;
33907db96d56Sopenharmony_ci    int i;
33917db96d56Sopenharmony_ci    Py_ssize_t set_size, ppos = 0;
33927db96d56Sopenharmony_ci    Py_hash_t hash;
33937db96d56Sopenharmony_ci
33947db96d56Sopenharmony_ci    const char empty_set_op = EMPTY_SET;
33957db96d56Sopenharmony_ci    const char mark_op = MARK;
33967db96d56Sopenharmony_ci    const char additems_op = ADDITEMS;
33977db96d56Sopenharmony_ci
33987db96d56Sopenharmony_ci    if (self->proto < 4) {
33997db96d56Sopenharmony_ci        PyObject *items;
34007db96d56Sopenharmony_ci        PyObject *reduce_value;
34017db96d56Sopenharmony_ci        int status;
34027db96d56Sopenharmony_ci
34037db96d56Sopenharmony_ci        items = PySequence_List(obj);
34047db96d56Sopenharmony_ci        if (items == NULL) {
34057db96d56Sopenharmony_ci            return -1;
34067db96d56Sopenharmony_ci        }
34077db96d56Sopenharmony_ci        reduce_value = Py_BuildValue("(O(O))", (PyObject*)&PySet_Type, items);
34087db96d56Sopenharmony_ci        Py_DECREF(items);
34097db96d56Sopenharmony_ci        if (reduce_value == NULL) {
34107db96d56Sopenharmony_ci            return -1;
34117db96d56Sopenharmony_ci        }
34127db96d56Sopenharmony_ci        /* save_reduce() will memoize the object automatically. */
34137db96d56Sopenharmony_ci        status = save_reduce(self, reduce_value, obj);
34147db96d56Sopenharmony_ci        Py_DECREF(reduce_value);
34157db96d56Sopenharmony_ci        return status;
34167db96d56Sopenharmony_ci    }
34177db96d56Sopenharmony_ci
34187db96d56Sopenharmony_ci    if (_Pickler_Write(self, &empty_set_op, 1) < 0)
34197db96d56Sopenharmony_ci        return -1;
34207db96d56Sopenharmony_ci
34217db96d56Sopenharmony_ci    if (memo_put(self, obj) < 0)
34227db96d56Sopenharmony_ci        return -1;
34237db96d56Sopenharmony_ci
34247db96d56Sopenharmony_ci    set_size = PySet_GET_SIZE(obj);
34257db96d56Sopenharmony_ci    if (set_size == 0)
34267db96d56Sopenharmony_ci        return 0;  /* nothing to do */
34277db96d56Sopenharmony_ci
34287db96d56Sopenharmony_ci    /* Write in batches of BATCHSIZE. */
34297db96d56Sopenharmony_ci    do {
34307db96d56Sopenharmony_ci        i = 0;
34317db96d56Sopenharmony_ci        if (_Pickler_Write(self, &mark_op, 1) < 0)
34327db96d56Sopenharmony_ci            return -1;
34337db96d56Sopenharmony_ci        while (_PySet_NextEntry(obj, &ppos, &item, &hash)) {
34347db96d56Sopenharmony_ci            Py_INCREF(item);
34357db96d56Sopenharmony_ci            int err = save(self, item, 0);
34367db96d56Sopenharmony_ci            Py_CLEAR(item);
34377db96d56Sopenharmony_ci            if (err < 0)
34387db96d56Sopenharmony_ci                return -1;
34397db96d56Sopenharmony_ci            if (++i == BATCHSIZE)
34407db96d56Sopenharmony_ci                break;
34417db96d56Sopenharmony_ci        }
34427db96d56Sopenharmony_ci        if (_Pickler_Write(self, &additems_op, 1) < 0)
34437db96d56Sopenharmony_ci            return -1;
34447db96d56Sopenharmony_ci        if (PySet_GET_SIZE(obj) != set_size) {
34457db96d56Sopenharmony_ci            PyErr_Format(
34467db96d56Sopenharmony_ci                PyExc_RuntimeError,
34477db96d56Sopenharmony_ci                "set changed size during iteration");
34487db96d56Sopenharmony_ci            return -1;
34497db96d56Sopenharmony_ci        }
34507db96d56Sopenharmony_ci    } while (i == BATCHSIZE);
34517db96d56Sopenharmony_ci
34527db96d56Sopenharmony_ci    return 0;
34537db96d56Sopenharmony_ci}
34547db96d56Sopenharmony_ci
34557db96d56Sopenharmony_cistatic int
34567db96d56Sopenharmony_cisave_frozenset(PicklerObject *self, PyObject *obj)
34577db96d56Sopenharmony_ci{
34587db96d56Sopenharmony_ci    PyObject *iter;
34597db96d56Sopenharmony_ci
34607db96d56Sopenharmony_ci    const char mark_op = MARK;
34617db96d56Sopenharmony_ci    const char frozenset_op = FROZENSET;
34627db96d56Sopenharmony_ci
34637db96d56Sopenharmony_ci    if (self->fast && !fast_save_enter(self, obj))
34647db96d56Sopenharmony_ci        return -1;
34657db96d56Sopenharmony_ci
34667db96d56Sopenharmony_ci    if (self->proto < 4) {
34677db96d56Sopenharmony_ci        PyObject *items;
34687db96d56Sopenharmony_ci        PyObject *reduce_value;
34697db96d56Sopenharmony_ci        int status;
34707db96d56Sopenharmony_ci
34717db96d56Sopenharmony_ci        items = PySequence_List(obj);
34727db96d56Sopenharmony_ci        if (items == NULL) {
34737db96d56Sopenharmony_ci            return -1;
34747db96d56Sopenharmony_ci        }
34757db96d56Sopenharmony_ci        reduce_value = Py_BuildValue("(O(O))", (PyObject*)&PyFrozenSet_Type,
34767db96d56Sopenharmony_ci                                     items);
34777db96d56Sopenharmony_ci        Py_DECREF(items);
34787db96d56Sopenharmony_ci        if (reduce_value == NULL) {
34797db96d56Sopenharmony_ci            return -1;
34807db96d56Sopenharmony_ci        }
34817db96d56Sopenharmony_ci        /* save_reduce() will memoize the object automatically. */
34827db96d56Sopenharmony_ci        status = save_reduce(self, reduce_value, obj);
34837db96d56Sopenharmony_ci        Py_DECREF(reduce_value);
34847db96d56Sopenharmony_ci        return status;
34857db96d56Sopenharmony_ci    }
34867db96d56Sopenharmony_ci
34877db96d56Sopenharmony_ci    if (_Pickler_Write(self, &mark_op, 1) < 0)
34887db96d56Sopenharmony_ci        return -1;
34897db96d56Sopenharmony_ci
34907db96d56Sopenharmony_ci    iter = PyObject_GetIter(obj);
34917db96d56Sopenharmony_ci    if (iter == NULL) {
34927db96d56Sopenharmony_ci        return -1;
34937db96d56Sopenharmony_ci    }
34947db96d56Sopenharmony_ci    for (;;) {
34957db96d56Sopenharmony_ci        PyObject *item;
34967db96d56Sopenharmony_ci
34977db96d56Sopenharmony_ci        item = PyIter_Next(iter);
34987db96d56Sopenharmony_ci        if (item == NULL) {
34997db96d56Sopenharmony_ci            if (PyErr_Occurred()) {
35007db96d56Sopenharmony_ci                Py_DECREF(iter);
35017db96d56Sopenharmony_ci                return -1;
35027db96d56Sopenharmony_ci            }
35037db96d56Sopenharmony_ci            break;
35047db96d56Sopenharmony_ci        }
35057db96d56Sopenharmony_ci        if (save(self, item, 0) < 0) {
35067db96d56Sopenharmony_ci            Py_DECREF(item);
35077db96d56Sopenharmony_ci            Py_DECREF(iter);
35087db96d56Sopenharmony_ci            return -1;
35097db96d56Sopenharmony_ci        }
35107db96d56Sopenharmony_ci        Py_DECREF(item);
35117db96d56Sopenharmony_ci    }
35127db96d56Sopenharmony_ci    Py_DECREF(iter);
35137db96d56Sopenharmony_ci
35147db96d56Sopenharmony_ci    /* If the object is already in the memo, this means it is
35157db96d56Sopenharmony_ci       recursive. In this case, throw away everything we put on the
35167db96d56Sopenharmony_ci       stack, and fetch the object back from the memo. */
35177db96d56Sopenharmony_ci    if (PyMemoTable_Get(self->memo, obj)) {
35187db96d56Sopenharmony_ci        const char pop_mark_op = POP_MARK;
35197db96d56Sopenharmony_ci
35207db96d56Sopenharmony_ci        if (_Pickler_Write(self, &pop_mark_op, 1) < 0)
35217db96d56Sopenharmony_ci            return -1;
35227db96d56Sopenharmony_ci        if (memo_get(self, obj) < 0)
35237db96d56Sopenharmony_ci            return -1;
35247db96d56Sopenharmony_ci        return 0;
35257db96d56Sopenharmony_ci    }
35267db96d56Sopenharmony_ci
35277db96d56Sopenharmony_ci    if (_Pickler_Write(self, &frozenset_op, 1) < 0)
35287db96d56Sopenharmony_ci        return -1;
35297db96d56Sopenharmony_ci    if (memo_put(self, obj) < 0)
35307db96d56Sopenharmony_ci        return -1;
35317db96d56Sopenharmony_ci
35327db96d56Sopenharmony_ci    return 0;
35337db96d56Sopenharmony_ci}
35347db96d56Sopenharmony_ci
35357db96d56Sopenharmony_cistatic int
35367db96d56Sopenharmony_cifix_imports(PyObject **module_name, PyObject **global_name)
35377db96d56Sopenharmony_ci{
35387db96d56Sopenharmony_ci    PyObject *key;
35397db96d56Sopenharmony_ci    PyObject *item;
35407db96d56Sopenharmony_ci    PickleState *st = _Pickle_GetGlobalState();
35417db96d56Sopenharmony_ci
35427db96d56Sopenharmony_ci    key = PyTuple_Pack(2, *module_name, *global_name);
35437db96d56Sopenharmony_ci    if (key == NULL)
35447db96d56Sopenharmony_ci        return -1;
35457db96d56Sopenharmony_ci    item = PyDict_GetItemWithError(st->name_mapping_3to2, key);
35467db96d56Sopenharmony_ci    Py_DECREF(key);
35477db96d56Sopenharmony_ci    if (item) {
35487db96d56Sopenharmony_ci        PyObject *fixed_module_name;
35497db96d56Sopenharmony_ci        PyObject *fixed_global_name;
35507db96d56Sopenharmony_ci
35517db96d56Sopenharmony_ci        if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) {
35527db96d56Sopenharmony_ci            PyErr_Format(PyExc_RuntimeError,
35537db96d56Sopenharmony_ci                         "_compat_pickle.REVERSE_NAME_MAPPING values "
35547db96d56Sopenharmony_ci                         "should be 2-tuples, not %.200s",
35557db96d56Sopenharmony_ci                         Py_TYPE(item)->tp_name);
35567db96d56Sopenharmony_ci            return -1;
35577db96d56Sopenharmony_ci        }
35587db96d56Sopenharmony_ci        fixed_module_name = PyTuple_GET_ITEM(item, 0);
35597db96d56Sopenharmony_ci        fixed_global_name = PyTuple_GET_ITEM(item, 1);
35607db96d56Sopenharmony_ci        if (!PyUnicode_Check(fixed_module_name) ||
35617db96d56Sopenharmony_ci            !PyUnicode_Check(fixed_global_name)) {
35627db96d56Sopenharmony_ci            PyErr_Format(PyExc_RuntimeError,
35637db96d56Sopenharmony_ci                         "_compat_pickle.REVERSE_NAME_MAPPING values "
35647db96d56Sopenharmony_ci                         "should be pairs of str, not (%.200s, %.200s)",
35657db96d56Sopenharmony_ci                         Py_TYPE(fixed_module_name)->tp_name,
35667db96d56Sopenharmony_ci                         Py_TYPE(fixed_global_name)->tp_name);
35677db96d56Sopenharmony_ci            return -1;
35687db96d56Sopenharmony_ci        }
35697db96d56Sopenharmony_ci
35707db96d56Sopenharmony_ci        Py_CLEAR(*module_name);
35717db96d56Sopenharmony_ci        Py_CLEAR(*global_name);
35727db96d56Sopenharmony_ci        Py_INCREF(fixed_module_name);
35737db96d56Sopenharmony_ci        Py_INCREF(fixed_global_name);
35747db96d56Sopenharmony_ci        *module_name = fixed_module_name;
35757db96d56Sopenharmony_ci        *global_name = fixed_global_name;
35767db96d56Sopenharmony_ci        return 0;
35777db96d56Sopenharmony_ci    }
35787db96d56Sopenharmony_ci    else if (PyErr_Occurred()) {
35797db96d56Sopenharmony_ci        return -1;
35807db96d56Sopenharmony_ci    }
35817db96d56Sopenharmony_ci
35827db96d56Sopenharmony_ci    item = PyDict_GetItemWithError(st->import_mapping_3to2, *module_name);
35837db96d56Sopenharmony_ci    if (item) {
35847db96d56Sopenharmony_ci        if (!PyUnicode_Check(item)) {
35857db96d56Sopenharmony_ci            PyErr_Format(PyExc_RuntimeError,
35867db96d56Sopenharmony_ci                         "_compat_pickle.REVERSE_IMPORT_MAPPING values "
35877db96d56Sopenharmony_ci                         "should be strings, not %.200s",
35887db96d56Sopenharmony_ci                         Py_TYPE(item)->tp_name);
35897db96d56Sopenharmony_ci            return -1;
35907db96d56Sopenharmony_ci        }
35917db96d56Sopenharmony_ci        Py_INCREF(item);
35927db96d56Sopenharmony_ci        Py_XSETREF(*module_name, item);
35937db96d56Sopenharmony_ci    }
35947db96d56Sopenharmony_ci    else if (PyErr_Occurred()) {
35957db96d56Sopenharmony_ci        return -1;
35967db96d56Sopenharmony_ci    }
35977db96d56Sopenharmony_ci
35987db96d56Sopenharmony_ci    return 0;
35997db96d56Sopenharmony_ci}
36007db96d56Sopenharmony_ci
36017db96d56Sopenharmony_cistatic int
36027db96d56Sopenharmony_cisave_global(PicklerObject *self, PyObject *obj, PyObject *name)
36037db96d56Sopenharmony_ci{
36047db96d56Sopenharmony_ci    PyObject *global_name = NULL;
36057db96d56Sopenharmony_ci    PyObject *module_name = NULL;
36067db96d56Sopenharmony_ci    PyObject *module = NULL;
36077db96d56Sopenharmony_ci    PyObject *parent = NULL;
36087db96d56Sopenharmony_ci    PyObject *dotted_path = NULL;
36097db96d56Sopenharmony_ci    PyObject *lastname = NULL;
36107db96d56Sopenharmony_ci    PyObject *cls;
36117db96d56Sopenharmony_ci    PickleState *st = _Pickle_GetGlobalState();
36127db96d56Sopenharmony_ci    int status = 0;
36137db96d56Sopenharmony_ci
36147db96d56Sopenharmony_ci    const char global_op = GLOBAL;
36157db96d56Sopenharmony_ci
36167db96d56Sopenharmony_ci    if (name) {
36177db96d56Sopenharmony_ci        Py_INCREF(name);
36187db96d56Sopenharmony_ci        global_name = name;
36197db96d56Sopenharmony_ci    }
36207db96d56Sopenharmony_ci    else {
36217db96d56Sopenharmony_ci        if (_PyObject_LookupAttr(obj, &_Py_ID(__qualname__), &global_name) < 0)
36227db96d56Sopenharmony_ci            goto error;
36237db96d56Sopenharmony_ci        if (global_name == NULL) {
36247db96d56Sopenharmony_ci            global_name = PyObject_GetAttr(obj, &_Py_ID(__name__));
36257db96d56Sopenharmony_ci            if (global_name == NULL)
36267db96d56Sopenharmony_ci                goto error;
36277db96d56Sopenharmony_ci        }
36287db96d56Sopenharmony_ci    }
36297db96d56Sopenharmony_ci
36307db96d56Sopenharmony_ci    dotted_path = get_dotted_path(module, global_name);
36317db96d56Sopenharmony_ci    if (dotted_path == NULL)
36327db96d56Sopenharmony_ci        goto error;
36337db96d56Sopenharmony_ci    module_name = whichmodule(obj, dotted_path);
36347db96d56Sopenharmony_ci    if (module_name == NULL)
36357db96d56Sopenharmony_ci        goto error;
36367db96d56Sopenharmony_ci
36377db96d56Sopenharmony_ci    /* XXX: Change to use the import C API directly with level=0 to disallow
36387db96d56Sopenharmony_ci       relative imports.
36397db96d56Sopenharmony_ci
36407db96d56Sopenharmony_ci       XXX: PyImport_ImportModuleLevel could be used. However, this bypasses
36417db96d56Sopenharmony_ci       builtins.__import__. Therefore, _pickle, unlike pickle.py, will ignore
36427db96d56Sopenharmony_ci       custom import functions (IMHO, this would be a nice security
36437db96d56Sopenharmony_ci       feature). The import C API would need to be extended to support the
36447db96d56Sopenharmony_ci       extra parameters of __import__ to fix that. */
36457db96d56Sopenharmony_ci    module = PyImport_Import(module_name);
36467db96d56Sopenharmony_ci    if (module == NULL) {
36477db96d56Sopenharmony_ci        PyErr_Format(st->PicklingError,
36487db96d56Sopenharmony_ci                     "Can't pickle %R: import of module %R failed",
36497db96d56Sopenharmony_ci                     obj, module_name);
36507db96d56Sopenharmony_ci        goto error;
36517db96d56Sopenharmony_ci    }
36527db96d56Sopenharmony_ci    lastname = PyList_GET_ITEM(dotted_path, PyList_GET_SIZE(dotted_path)-1);
36537db96d56Sopenharmony_ci    Py_INCREF(lastname);
36547db96d56Sopenharmony_ci    cls = get_deep_attribute(module, dotted_path, &parent);
36557db96d56Sopenharmony_ci    Py_CLEAR(dotted_path);
36567db96d56Sopenharmony_ci    if (cls == NULL) {
36577db96d56Sopenharmony_ci        PyErr_Format(st->PicklingError,
36587db96d56Sopenharmony_ci                     "Can't pickle %R: attribute lookup %S on %S failed",
36597db96d56Sopenharmony_ci                     obj, global_name, module_name);
36607db96d56Sopenharmony_ci        goto error;
36617db96d56Sopenharmony_ci    }
36627db96d56Sopenharmony_ci    if (cls != obj) {
36637db96d56Sopenharmony_ci        Py_DECREF(cls);
36647db96d56Sopenharmony_ci        PyErr_Format(st->PicklingError,
36657db96d56Sopenharmony_ci                     "Can't pickle %R: it's not the same object as %S.%S",
36667db96d56Sopenharmony_ci                     obj, module_name, global_name);
36677db96d56Sopenharmony_ci        goto error;
36687db96d56Sopenharmony_ci    }
36697db96d56Sopenharmony_ci    Py_DECREF(cls);
36707db96d56Sopenharmony_ci
36717db96d56Sopenharmony_ci    if (self->proto >= 2) {
36727db96d56Sopenharmony_ci        /* See whether this is in the extension registry, and if
36737db96d56Sopenharmony_ci         * so generate an EXT opcode.
36747db96d56Sopenharmony_ci         */
36757db96d56Sopenharmony_ci        PyObject *extension_key;
36767db96d56Sopenharmony_ci        PyObject *code_obj;      /* extension code as Python object */
36777db96d56Sopenharmony_ci        long code;               /* extension code as C value */
36787db96d56Sopenharmony_ci        char pdata[5];
36797db96d56Sopenharmony_ci        Py_ssize_t n;
36807db96d56Sopenharmony_ci
36817db96d56Sopenharmony_ci        extension_key = PyTuple_Pack(2, module_name, global_name);
36827db96d56Sopenharmony_ci        if (extension_key == NULL) {
36837db96d56Sopenharmony_ci            goto error;
36847db96d56Sopenharmony_ci        }
36857db96d56Sopenharmony_ci        code_obj = PyDict_GetItemWithError(st->extension_registry,
36867db96d56Sopenharmony_ci                                           extension_key);
36877db96d56Sopenharmony_ci        Py_DECREF(extension_key);
36887db96d56Sopenharmony_ci        /* The object is not registered in the extension registry.
36897db96d56Sopenharmony_ci           This is the most likely code path. */
36907db96d56Sopenharmony_ci        if (code_obj == NULL) {
36917db96d56Sopenharmony_ci            if (PyErr_Occurred()) {
36927db96d56Sopenharmony_ci                goto error;
36937db96d56Sopenharmony_ci            }
36947db96d56Sopenharmony_ci            goto gen_global;
36957db96d56Sopenharmony_ci        }
36967db96d56Sopenharmony_ci
36977db96d56Sopenharmony_ci        /* XXX: pickle.py doesn't check neither the type, nor the range
36987db96d56Sopenharmony_ci           of the value returned by the extension_registry. It should for
36997db96d56Sopenharmony_ci           consistency. */
37007db96d56Sopenharmony_ci
37017db96d56Sopenharmony_ci        /* Verify code_obj has the right type and value. */
37027db96d56Sopenharmony_ci        if (!PyLong_Check(code_obj)) {
37037db96d56Sopenharmony_ci            PyErr_Format(st->PicklingError,
37047db96d56Sopenharmony_ci                         "Can't pickle %R: extension code %R isn't an integer",
37057db96d56Sopenharmony_ci                         obj, code_obj);
37067db96d56Sopenharmony_ci            goto error;
37077db96d56Sopenharmony_ci        }
37087db96d56Sopenharmony_ci        code = PyLong_AS_LONG(code_obj);
37097db96d56Sopenharmony_ci        if (code <= 0 || code > 0x7fffffffL) {
37107db96d56Sopenharmony_ci            if (!PyErr_Occurred())
37117db96d56Sopenharmony_ci                PyErr_Format(st->PicklingError, "Can't pickle %R: extension "
37127db96d56Sopenharmony_ci                             "code %ld is out of range", obj, code);
37137db96d56Sopenharmony_ci            goto error;
37147db96d56Sopenharmony_ci        }
37157db96d56Sopenharmony_ci
37167db96d56Sopenharmony_ci        /* Generate an EXT opcode. */
37177db96d56Sopenharmony_ci        if (code <= 0xff) {
37187db96d56Sopenharmony_ci            pdata[0] = EXT1;
37197db96d56Sopenharmony_ci            pdata[1] = (unsigned char)code;
37207db96d56Sopenharmony_ci            n = 2;
37217db96d56Sopenharmony_ci        }
37227db96d56Sopenharmony_ci        else if (code <= 0xffff) {
37237db96d56Sopenharmony_ci            pdata[0] = EXT2;
37247db96d56Sopenharmony_ci            pdata[1] = (unsigned char)(code & 0xff);
37257db96d56Sopenharmony_ci            pdata[2] = (unsigned char)((code >> 8) & 0xff);
37267db96d56Sopenharmony_ci            n = 3;
37277db96d56Sopenharmony_ci        }
37287db96d56Sopenharmony_ci        else {
37297db96d56Sopenharmony_ci            pdata[0] = EXT4;
37307db96d56Sopenharmony_ci            pdata[1] = (unsigned char)(code & 0xff);
37317db96d56Sopenharmony_ci            pdata[2] = (unsigned char)((code >> 8) & 0xff);
37327db96d56Sopenharmony_ci            pdata[3] = (unsigned char)((code >> 16) & 0xff);
37337db96d56Sopenharmony_ci            pdata[4] = (unsigned char)((code >> 24) & 0xff);
37347db96d56Sopenharmony_ci            n = 5;
37357db96d56Sopenharmony_ci        }
37367db96d56Sopenharmony_ci
37377db96d56Sopenharmony_ci        if (_Pickler_Write(self, pdata, n) < 0)
37387db96d56Sopenharmony_ci            goto error;
37397db96d56Sopenharmony_ci    }
37407db96d56Sopenharmony_ci    else {
37417db96d56Sopenharmony_ci  gen_global:
37427db96d56Sopenharmony_ci        if (parent == module) {
37437db96d56Sopenharmony_ci            Py_INCREF(lastname);
37447db96d56Sopenharmony_ci            Py_DECREF(global_name);
37457db96d56Sopenharmony_ci            global_name = lastname;
37467db96d56Sopenharmony_ci        }
37477db96d56Sopenharmony_ci        if (self->proto >= 4) {
37487db96d56Sopenharmony_ci            const char stack_global_op = STACK_GLOBAL;
37497db96d56Sopenharmony_ci
37507db96d56Sopenharmony_ci            if (save(self, module_name, 0) < 0)
37517db96d56Sopenharmony_ci                goto error;
37527db96d56Sopenharmony_ci            if (save(self, global_name, 0) < 0)
37537db96d56Sopenharmony_ci                goto error;
37547db96d56Sopenharmony_ci
37557db96d56Sopenharmony_ci            if (_Pickler_Write(self, &stack_global_op, 1) < 0)
37567db96d56Sopenharmony_ci                goto error;
37577db96d56Sopenharmony_ci        }
37587db96d56Sopenharmony_ci        else if (parent != module) {
37597db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
37607db96d56Sopenharmony_ci            PyObject *reduce_value = Py_BuildValue("(O(OO))",
37617db96d56Sopenharmony_ci                                        st->getattr, parent, lastname);
37627db96d56Sopenharmony_ci            if (reduce_value == NULL)
37637db96d56Sopenharmony_ci                goto error;
37647db96d56Sopenharmony_ci            status = save_reduce(self, reduce_value, NULL);
37657db96d56Sopenharmony_ci            Py_DECREF(reduce_value);
37667db96d56Sopenharmony_ci            if (status < 0)
37677db96d56Sopenharmony_ci                goto error;
37687db96d56Sopenharmony_ci        }
37697db96d56Sopenharmony_ci        else {
37707db96d56Sopenharmony_ci            /* Generate a normal global opcode if we are using a pickle
37717db96d56Sopenharmony_ci               protocol < 4, or if the object is not registered in the
37727db96d56Sopenharmony_ci               extension registry. */
37737db96d56Sopenharmony_ci            PyObject *encoded;
37747db96d56Sopenharmony_ci            PyObject *(*unicode_encoder)(PyObject *);
37757db96d56Sopenharmony_ci
37767db96d56Sopenharmony_ci            if (_Pickler_Write(self, &global_op, 1) < 0)
37777db96d56Sopenharmony_ci                goto error;
37787db96d56Sopenharmony_ci
37797db96d56Sopenharmony_ci            /* For protocol < 3 and if the user didn't request against doing
37807db96d56Sopenharmony_ci               so, we convert module names to the old 2.x module names. */
37817db96d56Sopenharmony_ci            if (self->proto < 3 && self->fix_imports) {
37827db96d56Sopenharmony_ci                if (fix_imports(&module_name, &global_name) < 0) {
37837db96d56Sopenharmony_ci                    goto error;
37847db96d56Sopenharmony_ci                }
37857db96d56Sopenharmony_ci            }
37867db96d56Sopenharmony_ci
37877db96d56Sopenharmony_ci            /* Since Python 3.0 now supports non-ASCII identifiers, we encode
37887db96d56Sopenharmony_ci               both the module name and the global name using UTF-8. We do so
37897db96d56Sopenharmony_ci               only when we are using the pickle protocol newer than version
37907db96d56Sopenharmony_ci               3. This is to ensure compatibility with older Unpickler running
37917db96d56Sopenharmony_ci               on Python 2.x. */
37927db96d56Sopenharmony_ci            if (self->proto == 3) {
37937db96d56Sopenharmony_ci                unicode_encoder = PyUnicode_AsUTF8String;
37947db96d56Sopenharmony_ci            }
37957db96d56Sopenharmony_ci            else {
37967db96d56Sopenharmony_ci                unicode_encoder = PyUnicode_AsASCIIString;
37977db96d56Sopenharmony_ci            }
37987db96d56Sopenharmony_ci            encoded = unicode_encoder(module_name);
37997db96d56Sopenharmony_ci            if (encoded == NULL) {
38007db96d56Sopenharmony_ci                if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError))
38017db96d56Sopenharmony_ci                    PyErr_Format(st->PicklingError,
38027db96d56Sopenharmony_ci                                 "can't pickle module identifier '%S' using "
38037db96d56Sopenharmony_ci                                 "pickle protocol %i",
38047db96d56Sopenharmony_ci                                 module_name, self->proto);
38057db96d56Sopenharmony_ci                goto error;
38067db96d56Sopenharmony_ci            }
38077db96d56Sopenharmony_ci            if (_Pickler_Write(self, PyBytes_AS_STRING(encoded),
38087db96d56Sopenharmony_ci                               PyBytes_GET_SIZE(encoded)) < 0) {
38097db96d56Sopenharmony_ci                Py_DECREF(encoded);
38107db96d56Sopenharmony_ci                goto error;
38117db96d56Sopenharmony_ci            }
38127db96d56Sopenharmony_ci            Py_DECREF(encoded);
38137db96d56Sopenharmony_ci            if(_Pickler_Write(self, "\n", 1) < 0)
38147db96d56Sopenharmony_ci                goto error;
38157db96d56Sopenharmony_ci
38167db96d56Sopenharmony_ci            /* Save the name of the module. */
38177db96d56Sopenharmony_ci            encoded = unicode_encoder(global_name);
38187db96d56Sopenharmony_ci            if (encoded == NULL) {
38197db96d56Sopenharmony_ci                if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError))
38207db96d56Sopenharmony_ci                    PyErr_Format(st->PicklingError,
38217db96d56Sopenharmony_ci                                 "can't pickle global identifier '%S' using "
38227db96d56Sopenharmony_ci                                 "pickle protocol %i",
38237db96d56Sopenharmony_ci                                 global_name, self->proto);
38247db96d56Sopenharmony_ci                goto error;
38257db96d56Sopenharmony_ci            }
38267db96d56Sopenharmony_ci            if (_Pickler_Write(self, PyBytes_AS_STRING(encoded),
38277db96d56Sopenharmony_ci                               PyBytes_GET_SIZE(encoded)) < 0) {
38287db96d56Sopenharmony_ci                Py_DECREF(encoded);
38297db96d56Sopenharmony_ci                goto error;
38307db96d56Sopenharmony_ci            }
38317db96d56Sopenharmony_ci            Py_DECREF(encoded);
38327db96d56Sopenharmony_ci            if (_Pickler_Write(self, "\n", 1) < 0)
38337db96d56Sopenharmony_ci                goto error;
38347db96d56Sopenharmony_ci        }
38357db96d56Sopenharmony_ci        /* Memoize the object. */
38367db96d56Sopenharmony_ci        if (memo_put(self, obj) < 0)
38377db96d56Sopenharmony_ci            goto error;
38387db96d56Sopenharmony_ci    }
38397db96d56Sopenharmony_ci
38407db96d56Sopenharmony_ci    if (0) {
38417db96d56Sopenharmony_ci  error:
38427db96d56Sopenharmony_ci        status = -1;
38437db96d56Sopenharmony_ci    }
38447db96d56Sopenharmony_ci    Py_XDECREF(module_name);
38457db96d56Sopenharmony_ci    Py_XDECREF(global_name);
38467db96d56Sopenharmony_ci    Py_XDECREF(module);
38477db96d56Sopenharmony_ci    Py_XDECREF(parent);
38487db96d56Sopenharmony_ci    Py_XDECREF(dotted_path);
38497db96d56Sopenharmony_ci    Py_XDECREF(lastname);
38507db96d56Sopenharmony_ci
38517db96d56Sopenharmony_ci    return status;
38527db96d56Sopenharmony_ci}
38537db96d56Sopenharmony_ci
38547db96d56Sopenharmony_cistatic int
38557db96d56Sopenharmony_cisave_singleton_type(PicklerObject *self, PyObject *obj, PyObject *singleton)
38567db96d56Sopenharmony_ci{
38577db96d56Sopenharmony_ci    PyObject *reduce_value;
38587db96d56Sopenharmony_ci    int status;
38597db96d56Sopenharmony_ci
38607db96d56Sopenharmony_ci    reduce_value = Py_BuildValue("O(O)", &PyType_Type, singleton);
38617db96d56Sopenharmony_ci    if (reduce_value == NULL) {
38627db96d56Sopenharmony_ci        return -1;
38637db96d56Sopenharmony_ci    }
38647db96d56Sopenharmony_ci    status = save_reduce(self, reduce_value, obj);
38657db96d56Sopenharmony_ci    Py_DECREF(reduce_value);
38667db96d56Sopenharmony_ci    return status;
38677db96d56Sopenharmony_ci}
38687db96d56Sopenharmony_ci
38697db96d56Sopenharmony_cistatic int
38707db96d56Sopenharmony_cisave_type(PicklerObject *self, PyObject *obj)
38717db96d56Sopenharmony_ci{
38727db96d56Sopenharmony_ci    if (obj == (PyObject *)&_PyNone_Type) {
38737db96d56Sopenharmony_ci        return save_singleton_type(self, obj, Py_None);
38747db96d56Sopenharmony_ci    }
38757db96d56Sopenharmony_ci    else if (obj == (PyObject *)&PyEllipsis_Type) {
38767db96d56Sopenharmony_ci        return save_singleton_type(self, obj, Py_Ellipsis);
38777db96d56Sopenharmony_ci    }
38787db96d56Sopenharmony_ci    else if (obj == (PyObject *)&_PyNotImplemented_Type) {
38797db96d56Sopenharmony_ci        return save_singleton_type(self, obj, Py_NotImplemented);
38807db96d56Sopenharmony_ci    }
38817db96d56Sopenharmony_ci    return save_global(self, obj, NULL);
38827db96d56Sopenharmony_ci}
38837db96d56Sopenharmony_ci
38847db96d56Sopenharmony_cistatic int
38857db96d56Sopenharmony_cisave_pers(PicklerObject *self, PyObject *obj)
38867db96d56Sopenharmony_ci{
38877db96d56Sopenharmony_ci    PyObject *pid = NULL;
38887db96d56Sopenharmony_ci    int status = 0;
38897db96d56Sopenharmony_ci
38907db96d56Sopenharmony_ci    const char persid_op = PERSID;
38917db96d56Sopenharmony_ci    const char binpersid_op = BINPERSID;
38927db96d56Sopenharmony_ci
38937db96d56Sopenharmony_ci    pid = call_method(self->pers_func, self->pers_func_self, obj);
38947db96d56Sopenharmony_ci    if (pid == NULL)
38957db96d56Sopenharmony_ci        return -1;
38967db96d56Sopenharmony_ci
38977db96d56Sopenharmony_ci    if (pid != Py_None) {
38987db96d56Sopenharmony_ci        if (self->bin) {
38997db96d56Sopenharmony_ci            if (save(self, pid, 1) < 0 ||
39007db96d56Sopenharmony_ci                _Pickler_Write(self, &binpersid_op, 1) < 0)
39017db96d56Sopenharmony_ci                goto error;
39027db96d56Sopenharmony_ci        }
39037db96d56Sopenharmony_ci        else {
39047db96d56Sopenharmony_ci            PyObject *pid_str;
39057db96d56Sopenharmony_ci
39067db96d56Sopenharmony_ci            pid_str = PyObject_Str(pid);
39077db96d56Sopenharmony_ci            if (pid_str == NULL)
39087db96d56Sopenharmony_ci                goto error;
39097db96d56Sopenharmony_ci
39107db96d56Sopenharmony_ci            /* XXX: Should it check whether the pid contains embedded
39117db96d56Sopenharmony_ci               newlines? */
39127db96d56Sopenharmony_ci            if (!PyUnicode_IS_ASCII(pid_str)) {
39137db96d56Sopenharmony_ci                PyErr_SetString(_Pickle_GetGlobalState()->PicklingError,
39147db96d56Sopenharmony_ci                                "persistent IDs in protocol 0 must be "
39157db96d56Sopenharmony_ci                                "ASCII strings");
39167db96d56Sopenharmony_ci                Py_DECREF(pid_str);
39177db96d56Sopenharmony_ci                goto error;
39187db96d56Sopenharmony_ci            }
39197db96d56Sopenharmony_ci
39207db96d56Sopenharmony_ci            if (_Pickler_Write(self, &persid_op, 1) < 0 ||
39217db96d56Sopenharmony_ci                _Pickler_Write(self, PyUnicode_DATA(pid_str),
39227db96d56Sopenharmony_ci                               PyUnicode_GET_LENGTH(pid_str)) < 0 ||
39237db96d56Sopenharmony_ci                _Pickler_Write(self, "\n", 1) < 0) {
39247db96d56Sopenharmony_ci                Py_DECREF(pid_str);
39257db96d56Sopenharmony_ci                goto error;
39267db96d56Sopenharmony_ci            }
39277db96d56Sopenharmony_ci            Py_DECREF(pid_str);
39287db96d56Sopenharmony_ci        }
39297db96d56Sopenharmony_ci        status = 1;
39307db96d56Sopenharmony_ci    }
39317db96d56Sopenharmony_ci
39327db96d56Sopenharmony_ci    if (0) {
39337db96d56Sopenharmony_ci  error:
39347db96d56Sopenharmony_ci        status = -1;
39357db96d56Sopenharmony_ci    }
39367db96d56Sopenharmony_ci    Py_XDECREF(pid);
39377db96d56Sopenharmony_ci
39387db96d56Sopenharmony_ci    return status;
39397db96d56Sopenharmony_ci}
39407db96d56Sopenharmony_ci
39417db96d56Sopenharmony_cistatic PyObject *
39427db96d56Sopenharmony_ciget_class(PyObject *obj)
39437db96d56Sopenharmony_ci{
39447db96d56Sopenharmony_ci    PyObject *cls;
39457db96d56Sopenharmony_ci
39467db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(obj, &_Py_ID(__class__), &cls) == 0) {
39477db96d56Sopenharmony_ci        cls = (PyObject *) Py_TYPE(obj);
39487db96d56Sopenharmony_ci        Py_INCREF(cls);
39497db96d56Sopenharmony_ci    }
39507db96d56Sopenharmony_ci    return cls;
39517db96d56Sopenharmony_ci}
39527db96d56Sopenharmony_ci
39537db96d56Sopenharmony_ci/* We're saving obj, and args is the 2-thru-5 tuple returned by the
39547db96d56Sopenharmony_ci * appropriate __reduce__ method for obj.
39557db96d56Sopenharmony_ci */
39567db96d56Sopenharmony_cistatic int
39577db96d56Sopenharmony_cisave_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
39587db96d56Sopenharmony_ci{
39597db96d56Sopenharmony_ci    PyObject *callable;
39607db96d56Sopenharmony_ci    PyObject *argtup;
39617db96d56Sopenharmony_ci    PyObject *state = NULL;
39627db96d56Sopenharmony_ci    PyObject *listitems = Py_None;
39637db96d56Sopenharmony_ci    PyObject *dictitems = Py_None;
39647db96d56Sopenharmony_ci    PyObject *state_setter = Py_None;
39657db96d56Sopenharmony_ci    PickleState *st = _Pickle_GetGlobalState();
39667db96d56Sopenharmony_ci    Py_ssize_t size;
39677db96d56Sopenharmony_ci    int use_newobj = 0, use_newobj_ex = 0;
39687db96d56Sopenharmony_ci
39697db96d56Sopenharmony_ci    const char reduce_op = REDUCE;
39707db96d56Sopenharmony_ci    const char build_op = BUILD;
39717db96d56Sopenharmony_ci    const char newobj_op = NEWOBJ;
39727db96d56Sopenharmony_ci    const char newobj_ex_op = NEWOBJ_EX;
39737db96d56Sopenharmony_ci
39747db96d56Sopenharmony_ci    size = PyTuple_Size(args);
39757db96d56Sopenharmony_ci    if (size < 2 || size > 6) {
39767db96d56Sopenharmony_ci        PyErr_SetString(st->PicklingError, "tuple returned by "
39777db96d56Sopenharmony_ci                        "__reduce__ must contain 2 through 6 elements");
39787db96d56Sopenharmony_ci        return -1;
39797db96d56Sopenharmony_ci    }
39807db96d56Sopenharmony_ci
39817db96d56Sopenharmony_ci    if (!PyArg_UnpackTuple(args, "save_reduce", 2, 6,
39827db96d56Sopenharmony_ci                           &callable, &argtup, &state, &listitems, &dictitems,
39837db96d56Sopenharmony_ci                           &state_setter))
39847db96d56Sopenharmony_ci        return -1;
39857db96d56Sopenharmony_ci
39867db96d56Sopenharmony_ci    if (!PyCallable_Check(callable)) {
39877db96d56Sopenharmony_ci        PyErr_SetString(st->PicklingError, "first item of the tuple "
39887db96d56Sopenharmony_ci                        "returned by __reduce__ must be callable");
39897db96d56Sopenharmony_ci        return -1;
39907db96d56Sopenharmony_ci    }
39917db96d56Sopenharmony_ci    if (!PyTuple_Check(argtup)) {
39927db96d56Sopenharmony_ci        PyErr_SetString(st->PicklingError, "second item of the tuple "
39937db96d56Sopenharmony_ci                        "returned by __reduce__ must be a tuple");
39947db96d56Sopenharmony_ci        return -1;
39957db96d56Sopenharmony_ci    }
39967db96d56Sopenharmony_ci
39977db96d56Sopenharmony_ci    if (state == Py_None)
39987db96d56Sopenharmony_ci        state = NULL;
39997db96d56Sopenharmony_ci
40007db96d56Sopenharmony_ci    if (listitems == Py_None)
40017db96d56Sopenharmony_ci        listitems = NULL;
40027db96d56Sopenharmony_ci    else if (!PyIter_Check(listitems)) {
40037db96d56Sopenharmony_ci        PyErr_Format(st->PicklingError, "fourth element of the tuple "
40047db96d56Sopenharmony_ci                     "returned by __reduce__ must be an iterator, not %s",
40057db96d56Sopenharmony_ci                     Py_TYPE(listitems)->tp_name);
40067db96d56Sopenharmony_ci        return -1;
40077db96d56Sopenharmony_ci    }
40087db96d56Sopenharmony_ci
40097db96d56Sopenharmony_ci    if (dictitems == Py_None)
40107db96d56Sopenharmony_ci        dictitems = NULL;
40117db96d56Sopenharmony_ci    else if (!PyIter_Check(dictitems)) {
40127db96d56Sopenharmony_ci        PyErr_Format(st->PicklingError, "fifth element of the tuple "
40137db96d56Sopenharmony_ci                     "returned by __reduce__ must be an iterator, not %s",
40147db96d56Sopenharmony_ci                     Py_TYPE(dictitems)->tp_name);
40157db96d56Sopenharmony_ci        return -1;
40167db96d56Sopenharmony_ci    }
40177db96d56Sopenharmony_ci
40187db96d56Sopenharmony_ci    if (state_setter == Py_None)
40197db96d56Sopenharmony_ci        state_setter = NULL;
40207db96d56Sopenharmony_ci    else if (!PyCallable_Check(state_setter)) {
40217db96d56Sopenharmony_ci        PyErr_Format(st->PicklingError, "sixth element of the tuple "
40227db96d56Sopenharmony_ci                     "returned by __reduce__ must be a function, not %s",
40237db96d56Sopenharmony_ci                     Py_TYPE(state_setter)->tp_name);
40247db96d56Sopenharmony_ci        return -1;
40257db96d56Sopenharmony_ci    }
40267db96d56Sopenharmony_ci
40277db96d56Sopenharmony_ci    if (self->proto >= 2) {
40287db96d56Sopenharmony_ci        PyObject *name;
40297db96d56Sopenharmony_ci
40307db96d56Sopenharmony_ci        if (_PyObject_LookupAttr(callable, &_Py_ID(__name__), &name) < 0) {
40317db96d56Sopenharmony_ci            return -1;
40327db96d56Sopenharmony_ci        }
40337db96d56Sopenharmony_ci        if (name != NULL && PyUnicode_Check(name)) {
40347db96d56Sopenharmony_ci            use_newobj_ex = _PyUnicode_Equal(name, &_Py_ID(__newobj_ex__));
40357db96d56Sopenharmony_ci            if (!use_newobj_ex) {
40367db96d56Sopenharmony_ci                use_newobj = _PyUnicode_Equal(name, &_Py_ID(__newobj__));
40377db96d56Sopenharmony_ci            }
40387db96d56Sopenharmony_ci        }
40397db96d56Sopenharmony_ci        Py_XDECREF(name);
40407db96d56Sopenharmony_ci    }
40417db96d56Sopenharmony_ci
40427db96d56Sopenharmony_ci    if (use_newobj_ex) {
40437db96d56Sopenharmony_ci        PyObject *cls;
40447db96d56Sopenharmony_ci        PyObject *args;
40457db96d56Sopenharmony_ci        PyObject *kwargs;
40467db96d56Sopenharmony_ci
40477db96d56Sopenharmony_ci        if (PyTuple_GET_SIZE(argtup) != 3) {
40487db96d56Sopenharmony_ci            PyErr_Format(st->PicklingError,
40497db96d56Sopenharmony_ci                         "length of the NEWOBJ_EX argument tuple must be "
40507db96d56Sopenharmony_ci                         "exactly 3, not %zd", PyTuple_GET_SIZE(argtup));
40517db96d56Sopenharmony_ci            return -1;
40527db96d56Sopenharmony_ci        }
40537db96d56Sopenharmony_ci
40547db96d56Sopenharmony_ci        cls = PyTuple_GET_ITEM(argtup, 0);
40557db96d56Sopenharmony_ci        if (!PyType_Check(cls)) {
40567db96d56Sopenharmony_ci            PyErr_Format(st->PicklingError,
40577db96d56Sopenharmony_ci                         "first item from NEWOBJ_EX argument tuple must "
40587db96d56Sopenharmony_ci                         "be a class, not %.200s", Py_TYPE(cls)->tp_name);
40597db96d56Sopenharmony_ci            return -1;
40607db96d56Sopenharmony_ci        }
40617db96d56Sopenharmony_ci        args = PyTuple_GET_ITEM(argtup, 1);
40627db96d56Sopenharmony_ci        if (!PyTuple_Check(args)) {
40637db96d56Sopenharmony_ci            PyErr_Format(st->PicklingError,
40647db96d56Sopenharmony_ci                         "second item from NEWOBJ_EX argument tuple must "
40657db96d56Sopenharmony_ci                         "be a tuple, not %.200s", Py_TYPE(args)->tp_name);
40667db96d56Sopenharmony_ci            return -1;
40677db96d56Sopenharmony_ci        }
40687db96d56Sopenharmony_ci        kwargs = PyTuple_GET_ITEM(argtup, 2);
40697db96d56Sopenharmony_ci        if (!PyDict_Check(kwargs)) {
40707db96d56Sopenharmony_ci            PyErr_Format(st->PicklingError,
40717db96d56Sopenharmony_ci                         "third item from NEWOBJ_EX argument tuple must "
40727db96d56Sopenharmony_ci                         "be a dict, not %.200s", Py_TYPE(kwargs)->tp_name);
40737db96d56Sopenharmony_ci            return -1;
40747db96d56Sopenharmony_ci        }
40757db96d56Sopenharmony_ci
40767db96d56Sopenharmony_ci        if (self->proto >= 4) {
40777db96d56Sopenharmony_ci            if (save(self, cls, 0) < 0 ||
40787db96d56Sopenharmony_ci                save(self, args, 0) < 0 ||
40797db96d56Sopenharmony_ci                save(self, kwargs, 0) < 0 ||
40807db96d56Sopenharmony_ci                _Pickler_Write(self, &newobj_ex_op, 1) < 0) {
40817db96d56Sopenharmony_ci                return -1;
40827db96d56Sopenharmony_ci            }
40837db96d56Sopenharmony_ci        }
40847db96d56Sopenharmony_ci        else {
40857db96d56Sopenharmony_ci            PyObject *newargs;
40867db96d56Sopenharmony_ci            PyObject *cls_new;
40877db96d56Sopenharmony_ci            Py_ssize_t i;
40887db96d56Sopenharmony_ci
40897db96d56Sopenharmony_ci            newargs = PyTuple_New(PyTuple_GET_SIZE(args) + 2);
40907db96d56Sopenharmony_ci            if (newargs == NULL)
40917db96d56Sopenharmony_ci                return -1;
40927db96d56Sopenharmony_ci
40937db96d56Sopenharmony_ci            cls_new = PyObject_GetAttr(cls, &_Py_ID(__new__));
40947db96d56Sopenharmony_ci            if (cls_new == NULL) {
40957db96d56Sopenharmony_ci                Py_DECREF(newargs);
40967db96d56Sopenharmony_ci                return -1;
40977db96d56Sopenharmony_ci            }
40987db96d56Sopenharmony_ci            PyTuple_SET_ITEM(newargs, 0, cls_new);
40997db96d56Sopenharmony_ci            Py_INCREF(cls);
41007db96d56Sopenharmony_ci            PyTuple_SET_ITEM(newargs, 1, cls);
41017db96d56Sopenharmony_ci            for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
41027db96d56Sopenharmony_ci                PyObject *item = PyTuple_GET_ITEM(args, i);
41037db96d56Sopenharmony_ci                Py_INCREF(item);
41047db96d56Sopenharmony_ci                PyTuple_SET_ITEM(newargs, i + 2, item);
41057db96d56Sopenharmony_ci            }
41067db96d56Sopenharmony_ci
41077db96d56Sopenharmony_ci            callable = PyObject_Call(st->partial, newargs, kwargs);
41087db96d56Sopenharmony_ci            Py_DECREF(newargs);
41097db96d56Sopenharmony_ci            if (callable == NULL)
41107db96d56Sopenharmony_ci                return -1;
41117db96d56Sopenharmony_ci
41127db96d56Sopenharmony_ci            newargs = PyTuple_New(0);
41137db96d56Sopenharmony_ci            if (newargs == NULL) {
41147db96d56Sopenharmony_ci                Py_DECREF(callable);
41157db96d56Sopenharmony_ci                return -1;
41167db96d56Sopenharmony_ci            }
41177db96d56Sopenharmony_ci
41187db96d56Sopenharmony_ci            if (save(self, callable, 0) < 0 ||
41197db96d56Sopenharmony_ci                save(self, newargs, 0) < 0 ||
41207db96d56Sopenharmony_ci                _Pickler_Write(self, &reduce_op, 1) < 0) {
41217db96d56Sopenharmony_ci                Py_DECREF(newargs);
41227db96d56Sopenharmony_ci                Py_DECREF(callable);
41237db96d56Sopenharmony_ci                return -1;
41247db96d56Sopenharmony_ci            }
41257db96d56Sopenharmony_ci            Py_DECREF(newargs);
41267db96d56Sopenharmony_ci            Py_DECREF(callable);
41277db96d56Sopenharmony_ci        }
41287db96d56Sopenharmony_ci    }
41297db96d56Sopenharmony_ci    else if (use_newobj) {
41307db96d56Sopenharmony_ci        PyObject *cls;
41317db96d56Sopenharmony_ci        PyObject *newargtup;
41327db96d56Sopenharmony_ci        PyObject *obj_class;
41337db96d56Sopenharmony_ci        int p;
41347db96d56Sopenharmony_ci
41357db96d56Sopenharmony_ci        /* Sanity checks. */
41367db96d56Sopenharmony_ci        if (PyTuple_GET_SIZE(argtup) < 1) {
41377db96d56Sopenharmony_ci            PyErr_SetString(st->PicklingError, "__newobj__ arglist is empty");
41387db96d56Sopenharmony_ci            return -1;
41397db96d56Sopenharmony_ci        }
41407db96d56Sopenharmony_ci
41417db96d56Sopenharmony_ci        cls = PyTuple_GET_ITEM(argtup, 0);
41427db96d56Sopenharmony_ci        if (!PyType_Check(cls)) {
41437db96d56Sopenharmony_ci            PyErr_SetString(st->PicklingError, "args[0] from "
41447db96d56Sopenharmony_ci                            "__newobj__ args is not a type");
41457db96d56Sopenharmony_ci            return -1;
41467db96d56Sopenharmony_ci        }
41477db96d56Sopenharmony_ci
41487db96d56Sopenharmony_ci        if (obj != NULL) {
41497db96d56Sopenharmony_ci            obj_class = get_class(obj);
41507db96d56Sopenharmony_ci            if (obj_class == NULL) {
41517db96d56Sopenharmony_ci                return -1;
41527db96d56Sopenharmony_ci            }
41537db96d56Sopenharmony_ci            p = obj_class != cls;
41547db96d56Sopenharmony_ci            Py_DECREF(obj_class);
41557db96d56Sopenharmony_ci            if (p) {
41567db96d56Sopenharmony_ci                PyErr_SetString(st->PicklingError, "args[0] from "
41577db96d56Sopenharmony_ci                                "__newobj__ args has the wrong class");
41587db96d56Sopenharmony_ci                return -1;
41597db96d56Sopenharmony_ci            }
41607db96d56Sopenharmony_ci        }
41617db96d56Sopenharmony_ci        /* XXX: These calls save() are prone to infinite recursion. Imagine
41627db96d56Sopenharmony_ci           what happen if the value returned by the __reduce__() method of
41637db96d56Sopenharmony_ci           some extension type contains another object of the same type. Ouch!
41647db96d56Sopenharmony_ci
41657db96d56Sopenharmony_ci           Here is a quick example, that I ran into, to illustrate what I
41667db96d56Sopenharmony_ci           mean:
41677db96d56Sopenharmony_ci
41687db96d56Sopenharmony_ci             >>> import pickle, copyreg
41697db96d56Sopenharmony_ci             >>> copyreg.dispatch_table.pop(complex)
41707db96d56Sopenharmony_ci             >>> pickle.dumps(1+2j)
41717db96d56Sopenharmony_ci             Traceback (most recent call last):
41727db96d56Sopenharmony_ci               ...
41737db96d56Sopenharmony_ci             RecursionError: maximum recursion depth exceeded
41747db96d56Sopenharmony_ci
41757db96d56Sopenharmony_ci           Removing the complex class from copyreg.dispatch_table made the
41767db96d56Sopenharmony_ci           __reduce_ex__() method emit another complex object:
41777db96d56Sopenharmony_ci
41787db96d56Sopenharmony_ci             >>> (1+1j).__reduce_ex__(2)
41797db96d56Sopenharmony_ci             (<function __newobj__ at 0xb7b71c3c>,
41807db96d56Sopenharmony_ci               (<class 'complex'>, (1+1j)), None, None, None)
41817db96d56Sopenharmony_ci
41827db96d56Sopenharmony_ci           Thus when save() was called on newargstup (the 2nd item) recursion
41837db96d56Sopenharmony_ci           ensued. Of course, the bug was in the complex class which had a
41847db96d56Sopenharmony_ci           broken __getnewargs__() that emitted another complex object. But,
41857db96d56Sopenharmony_ci           the point, here, is it is quite easy to end up with a broken reduce
41867db96d56Sopenharmony_ci           function. */
41877db96d56Sopenharmony_ci
41887db96d56Sopenharmony_ci        /* Save the class and its __new__ arguments. */
41897db96d56Sopenharmony_ci        if (save(self, cls, 0) < 0)
41907db96d56Sopenharmony_ci            return -1;
41917db96d56Sopenharmony_ci
41927db96d56Sopenharmony_ci        newargtup = PyTuple_GetSlice(argtup, 1, PyTuple_GET_SIZE(argtup));
41937db96d56Sopenharmony_ci        if (newargtup == NULL)
41947db96d56Sopenharmony_ci            return -1;
41957db96d56Sopenharmony_ci
41967db96d56Sopenharmony_ci        p = save(self, newargtup, 0);
41977db96d56Sopenharmony_ci        Py_DECREF(newargtup);
41987db96d56Sopenharmony_ci        if (p < 0)
41997db96d56Sopenharmony_ci            return -1;
42007db96d56Sopenharmony_ci
42017db96d56Sopenharmony_ci        /* Add NEWOBJ opcode. */
42027db96d56Sopenharmony_ci        if (_Pickler_Write(self, &newobj_op, 1) < 0)
42037db96d56Sopenharmony_ci            return -1;
42047db96d56Sopenharmony_ci    }
42057db96d56Sopenharmony_ci    else { /* Not using NEWOBJ. */
42067db96d56Sopenharmony_ci        if (save(self, callable, 0) < 0 ||
42077db96d56Sopenharmony_ci            save(self, argtup, 0) < 0 ||
42087db96d56Sopenharmony_ci            _Pickler_Write(self, &reduce_op, 1) < 0)
42097db96d56Sopenharmony_ci            return -1;
42107db96d56Sopenharmony_ci    }
42117db96d56Sopenharmony_ci
42127db96d56Sopenharmony_ci    /* obj can be NULL when save_reduce() is used directly. A NULL obj means
42137db96d56Sopenharmony_ci       the caller do not want to memoize the object. Not particularly useful,
42147db96d56Sopenharmony_ci       but that is to mimic the behavior save_reduce() in pickle.py when
42157db96d56Sopenharmony_ci       obj is None. */
42167db96d56Sopenharmony_ci    if (obj != NULL) {
42177db96d56Sopenharmony_ci        /* If the object is already in the memo, this means it is
42187db96d56Sopenharmony_ci           recursive. In this case, throw away everything we put on the
42197db96d56Sopenharmony_ci           stack, and fetch the object back from the memo. */
42207db96d56Sopenharmony_ci        if (PyMemoTable_Get(self->memo, obj)) {
42217db96d56Sopenharmony_ci            const char pop_op = POP;
42227db96d56Sopenharmony_ci
42237db96d56Sopenharmony_ci            if (_Pickler_Write(self, &pop_op, 1) < 0)
42247db96d56Sopenharmony_ci                return -1;
42257db96d56Sopenharmony_ci            if (memo_get(self, obj) < 0)
42267db96d56Sopenharmony_ci                return -1;
42277db96d56Sopenharmony_ci
42287db96d56Sopenharmony_ci            return 0;
42297db96d56Sopenharmony_ci        }
42307db96d56Sopenharmony_ci        else if (memo_put(self, obj) < 0)
42317db96d56Sopenharmony_ci            return -1;
42327db96d56Sopenharmony_ci    }
42337db96d56Sopenharmony_ci
42347db96d56Sopenharmony_ci    if (listitems && batch_list(self, listitems) < 0)
42357db96d56Sopenharmony_ci        return -1;
42367db96d56Sopenharmony_ci
42377db96d56Sopenharmony_ci    if (dictitems && batch_dict(self, dictitems) < 0)
42387db96d56Sopenharmony_ci        return -1;
42397db96d56Sopenharmony_ci
42407db96d56Sopenharmony_ci    if (state) {
42417db96d56Sopenharmony_ci        if (state_setter == NULL) {
42427db96d56Sopenharmony_ci            if (save(self, state, 0) < 0 ||
42437db96d56Sopenharmony_ci                _Pickler_Write(self, &build_op, 1) < 0)
42447db96d56Sopenharmony_ci                return -1;
42457db96d56Sopenharmony_ci        }
42467db96d56Sopenharmony_ci        else {
42477db96d56Sopenharmony_ci
42487db96d56Sopenharmony_ci            /* If a state_setter is specified, call it instead of load_build to
42497db96d56Sopenharmony_ci             * update obj's with its previous state.
42507db96d56Sopenharmony_ci             * The first 4 save/write instructions push state_setter and its
42517db96d56Sopenharmony_ci             * tuple of expected arguments (obj, state) onto the stack. The
42527db96d56Sopenharmony_ci             * REDUCE opcode triggers the state_setter(obj, state) function
42537db96d56Sopenharmony_ci             * call. Finally, because state-updating routines only do in-place
42547db96d56Sopenharmony_ci             * modification, the whole operation has to be stack-transparent.
42557db96d56Sopenharmony_ci             * Thus, we finally pop the call's output from the stack.*/
42567db96d56Sopenharmony_ci
42577db96d56Sopenharmony_ci            const char tupletwo_op = TUPLE2;
42587db96d56Sopenharmony_ci            const char pop_op = POP;
42597db96d56Sopenharmony_ci            if (save(self, state_setter, 0) < 0 ||
42607db96d56Sopenharmony_ci                save(self, obj, 0) < 0 || save(self, state, 0) < 0 ||
42617db96d56Sopenharmony_ci                _Pickler_Write(self, &tupletwo_op, 1) < 0 ||
42627db96d56Sopenharmony_ci                _Pickler_Write(self, &reduce_op, 1) < 0 ||
42637db96d56Sopenharmony_ci                _Pickler_Write(self, &pop_op, 1) < 0)
42647db96d56Sopenharmony_ci                return -1;
42657db96d56Sopenharmony_ci        }
42667db96d56Sopenharmony_ci    }
42677db96d56Sopenharmony_ci    return 0;
42687db96d56Sopenharmony_ci}
42697db96d56Sopenharmony_ci
42707db96d56Sopenharmony_cistatic int
42717db96d56Sopenharmony_cisave(PicklerObject *self, PyObject *obj, int pers_save)
42727db96d56Sopenharmony_ci{
42737db96d56Sopenharmony_ci    PyTypeObject *type;
42747db96d56Sopenharmony_ci    PyObject *reduce_func = NULL;
42757db96d56Sopenharmony_ci    PyObject *reduce_value = NULL;
42767db96d56Sopenharmony_ci    int status = 0;
42777db96d56Sopenharmony_ci
42787db96d56Sopenharmony_ci    if (_Pickler_OpcodeBoundary(self) < 0)
42797db96d56Sopenharmony_ci        return -1;
42807db96d56Sopenharmony_ci
42817db96d56Sopenharmony_ci    /* The extra pers_save argument is necessary to avoid calling save_pers()
42827db96d56Sopenharmony_ci       on its returned object. */
42837db96d56Sopenharmony_ci    if (!pers_save && self->pers_func) {
42847db96d56Sopenharmony_ci        /* save_pers() returns:
42857db96d56Sopenharmony_ci            -1   to signal an error;
42867db96d56Sopenharmony_ci             0   if it did nothing successfully;
42877db96d56Sopenharmony_ci             1   if a persistent id was saved.
42887db96d56Sopenharmony_ci         */
42897db96d56Sopenharmony_ci        if ((status = save_pers(self, obj)) != 0)
42907db96d56Sopenharmony_ci            return status;
42917db96d56Sopenharmony_ci    }
42927db96d56Sopenharmony_ci
42937db96d56Sopenharmony_ci    type = Py_TYPE(obj);
42947db96d56Sopenharmony_ci
42957db96d56Sopenharmony_ci    /* The old cPickle had an optimization that used switch-case statement
42967db96d56Sopenharmony_ci       dispatching on the first letter of the type name.  This has was removed
42977db96d56Sopenharmony_ci       since benchmarks shown that this optimization was actually slowing
42987db96d56Sopenharmony_ci       things down. */
42997db96d56Sopenharmony_ci
43007db96d56Sopenharmony_ci    /* Atom types; these aren't memoized, so don't check the memo. */
43017db96d56Sopenharmony_ci
43027db96d56Sopenharmony_ci    if (obj == Py_None) {
43037db96d56Sopenharmony_ci        return save_none(self, obj);
43047db96d56Sopenharmony_ci    }
43057db96d56Sopenharmony_ci    else if (obj == Py_False || obj == Py_True) {
43067db96d56Sopenharmony_ci        return save_bool(self, obj);
43077db96d56Sopenharmony_ci    }
43087db96d56Sopenharmony_ci    else if (type == &PyLong_Type) {
43097db96d56Sopenharmony_ci        return save_long(self, obj);
43107db96d56Sopenharmony_ci    }
43117db96d56Sopenharmony_ci    else if (type == &PyFloat_Type) {
43127db96d56Sopenharmony_ci        return save_float(self, obj);
43137db96d56Sopenharmony_ci    }
43147db96d56Sopenharmony_ci
43157db96d56Sopenharmony_ci    /* Check the memo to see if it has the object. If so, generate
43167db96d56Sopenharmony_ci       a GET (or BINGET) opcode, instead of pickling the object
43177db96d56Sopenharmony_ci       once again. */
43187db96d56Sopenharmony_ci    if (PyMemoTable_Get(self->memo, obj)) {
43197db96d56Sopenharmony_ci        return memo_get(self, obj);
43207db96d56Sopenharmony_ci    }
43217db96d56Sopenharmony_ci
43227db96d56Sopenharmony_ci    if (type == &PyBytes_Type) {
43237db96d56Sopenharmony_ci        return save_bytes(self, obj);
43247db96d56Sopenharmony_ci    }
43257db96d56Sopenharmony_ci    else if (type == &PyUnicode_Type) {
43267db96d56Sopenharmony_ci        return save_unicode(self, obj);
43277db96d56Sopenharmony_ci    }
43287db96d56Sopenharmony_ci
43297db96d56Sopenharmony_ci    /* We're only calling _Py_EnterRecursiveCall here so that atomic
43307db96d56Sopenharmony_ci       types above are pickled faster. */
43317db96d56Sopenharmony_ci    if (_Py_EnterRecursiveCall(" while pickling an object")) {
43327db96d56Sopenharmony_ci        return -1;
43337db96d56Sopenharmony_ci    }
43347db96d56Sopenharmony_ci
43357db96d56Sopenharmony_ci    if (type == &PyDict_Type) {
43367db96d56Sopenharmony_ci        status = save_dict(self, obj);
43377db96d56Sopenharmony_ci        goto done;
43387db96d56Sopenharmony_ci    }
43397db96d56Sopenharmony_ci    else if (type == &PySet_Type) {
43407db96d56Sopenharmony_ci        status = save_set(self, obj);
43417db96d56Sopenharmony_ci        goto done;
43427db96d56Sopenharmony_ci    }
43437db96d56Sopenharmony_ci    else if (type == &PyFrozenSet_Type) {
43447db96d56Sopenharmony_ci        status = save_frozenset(self, obj);
43457db96d56Sopenharmony_ci        goto done;
43467db96d56Sopenharmony_ci    }
43477db96d56Sopenharmony_ci    else if (type == &PyList_Type) {
43487db96d56Sopenharmony_ci        status = save_list(self, obj);
43497db96d56Sopenharmony_ci        goto done;
43507db96d56Sopenharmony_ci    }
43517db96d56Sopenharmony_ci    else if (type == &PyTuple_Type) {
43527db96d56Sopenharmony_ci        status = save_tuple(self, obj);
43537db96d56Sopenharmony_ci        goto done;
43547db96d56Sopenharmony_ci    }
43557db96d56Sopenharmony_ci    else if (type == &PyByteArray_Type) {
43567db96d56Sopenharmony_ci        status = save_bytearray(self, obj);
43577db96d56Sopenharmony_ci        goto done;
43587db96d56Sopenharmony_ci    }
43597db96d56Sopenharmony_ci    else if (type == &PyPickleBuffer_Type) {
43607db96d56Sopenharmony_ci        status = save_picklebuffer(self, obj);
43617db96d56Sopenharmony_ci        goto done;
43627db96d56Sopenharmony_ci    }
43637db96d56Sopenharmony_ci
43647db96d56Sopenharmony_ci    /* Now, check reducer_override.  If it returns NotImplemented,
43657db96d56Sopenharmony_ci     * fallback to save_type or save_global, and then perhaps to the
43667db96d56Sopenharmony_ci     * regular reduction mechanism.
43677db96d56Sopenharmony_ci     */
43687db96d56Sopenharmony_ci    if (self->reducer_override != NULL) {
43697db96d56Sopenharmony_ci        reduce_value = PyObject_CallOneArg(self->reducer_override, obj);
43707db96d56Sopenharmony_ci        if (reduce_value == NULL) {
43717db96d56Sopenharmony_ci            goto error;
43727db96d56Sopenharmony_ci        }
43737db96d56Sopenharmony_ci        if (reduce_value != Py_NotImplemented) {
43747db96d56Sopenharmony_ci            goto reduce;
43757db96d56Sopenharmony_ci        }
43767db96d56Sopenharmony_ci        Py_DECREF(reduce_value);
43777db96d56Sopenharmony_ci        reduce_value = NULL;
43787db96d56Sopenharmony_ci    }
43797db96d56Sopenharmony_ci
43807db96d56Sopenharmony_ci    if (type == &PyType_Type) {
43817db96d56Sopenharmony_ci        status = save_type(self, obj);
43827db96d56Sopenharmony_ci        goto done;
43837db96d56Sopenharmony_ci    }
43847db96d56Sopenharmony_ci    else if (type == &PyFunction_Type) {
43857db96d56Sopenharmony_ci        status = save_global(self, obj, NULL);
43867db96d56Sopenharmony_ci        goto done;
43877db96d56Sopenharmony_ci    }
43887db96d56Sopenharmony_ci
43897db96d56Sopenharmony_ci    /* XXX: This part needs some unit tests. */
43907db96d56Sopenharmony_ci
43917db96d56Sopenharmony_ci    /* Get a reduction callable, and call it.  This may come from
43927db96d56Sopenharmony_ci     * self.dispatch_table, copyreg.dispatch_table, the object's
43937db96d56Sopenharmony_ci     * __reduce_ex__ method, or the object's __reduce__ method.
43947db96d56Sopenharmony_ci     */
43957db96d56Sopenharmony_ci    if (self->dispatch_table == NULL) {
43967db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
43977db96d56Sopenharmony_ci        reduce_func = PyDict_GetItemWithError(st->dispatch_table,
43987db96d56Sopenharmony_ci                                              (PyObject *)type);
43997db96d56Sopenharmony_ci        if (reduce_func == NULL) {
44007db96d56Sopenharmony_ci            if (PyErr_Occurred()) {
44017db96d56Sopenharmony_ci                goto error;
44027db96d56Sopenharmony_ci            }
44037db96d56Sopenharmony_ci        } else {
44047db96d56Sopenharmony_ci            /* PyDict_GetItemWithError() returns a borrowed reference.
44057db96d56Sopenharmony_ci               Increase the reference count to be consistent with
44067db96d56Sopenharmony_ci               PyObject_GetItem and _PyObject_GetAttrId used below. */
44077db96d56Sopenharmony_ci            Py_INCREF(reduce_func);
44087db96d56Sopenharmony_ci        }
44097db96d56Sopenharmony_ci    } else {
44107db96d56Sopenharmony_ci        reduce_func = PyObject_GetItem(self->dispatch_table,
44117db96d56Sopenharmony_ci                                       (PyObject *)type);
44127db96d56Sopenharmony_ci        if (reduce_func == NULL) {
44137db96d56Sopenharmony_ci            if (PyErr_ExceptionMatches(PyExc_KeyError))
44147db96d56Sopenharmony_ci                PyErr_Clear();
44157db96d56Sopenharmony_ci            else
44167db96d56Sopenharmony_ci                goto error;
44177db96d56Sopenharmony_ci        }
44187db96d56Sopenharmony_ci    }
44197db96d56Sopenharmony_ci    if (reduce_func != NULL) {
44207db96d56Sopenharmony_ci        Py_INCREF(obj);
44217db96d56Sopenharmony_ci        reduce_value = _Pickle_FastCall(reduce_func, obj);
44227db96d56Sopenharmony_ci    }
44237db96d56Sopenharmony_ci    else if (PyType_IsSubtype(type, &PyType_Type)) {
44247db96d56Sopenharmony_ci        status = save_global(self, obj, NULL);
44257db96d56Sopenharmony_ci        goto done;
44267db96d56Sopenharmony_ci    }
44277db96d56Sopenharmony_ci    else {
44287db96d56Sopenharmony_ci        /* XXX: If the __reduce__ method is defined, __reduce_ex__ is
44297db96d56Sopenharmony_ci           automatically defined as __reduce__. While this is convenient, this
44307db96d56Sopenharmony_ci           make it impossible to know which method was actually called. Of
44317db96d56Sopenharmony_ci           course, this is not a big deal. But still, it would be nice to let
44327db96d56Sopenharmony_ci           the user know which method was called when something go
44337db96d56Sopenharmony_ci           wrong. Incidentally, this means if __reduce_ex__ is not defined, we
44347db96d56Sopenharmony_ci           don't actually have to check for a __reduce__ method. */
44357db96d56Sopenharmony_ci
44367db96d56Sopenharmony_ci        /* Check for a __reduce_ex__ method. */
44377db96d56Sopenharmony_ci        if (_PyObject_LookupAttr(obj, &_Py_ID(__reduce_ex__), &reduce_func) < 0) {
44387db96d56Sopenharmony_ci            goto error;
44397db96d56Sopenharmony_ci        }
44407db96d56Sopenharmony_ci        if (reduce_func != NULL) {
44417db96d56Sopenharmony_ci            PyObject *proto;
44427db96d56Sopenharmony_ci            proto = PyLong_FromLong(self->proto);
44437db96d56Sopenharmony_ci            if (proto != NULL) {
44447db96d56Sopenharmony_ci                reduce_value = _Pickle_FastCall(reduce_func, proto);
44457db96d56Sopenharmony_ci            }
44467db96d56Sopenharmony_ci        }
44477db96d56Sopenharmony_ci        else {
44487db96d56Sopenharmony_ci            /* Check for a __reduce__ method. */
44497db96d56Sopenharmony_ci            if (_PyObject_LookupAttr(obj, &_Py_ID(__reduce__), &reduce_func) < 0) {
44507db96d56Sopenharmony_ci                goto error;
44517db96d56Sopenharmony_ci            }
44527db96d56Sopenharmony_ci            if (reduce_func != NULL) {
44537db96d56Sopenharmony_ci                reduce_value = PyObject_CallNoArgs(reduce_func);
44547db96d56Sopenharmony_ci            }
44557db96d56Sopenharmony_ci            else {
44567db96d56Sopenharmony_ci                PickleState *st = _Pickle_GetGlobalState();
44577db96d56Sopenharmony_ci                PyErr_Format(st->PicklingError,
44587db96d56Sopenharmony_ci                             "can't pickle '%.200s' object: %R",
44597db96d56Sopenharmony_ci                             type->tp_name, obj);
44607db96d56Sopenharmony_ci                goto error;
44617db96d56Sopenharmony_ci            }
44627db96d56Sopenharmony_ci        }
44637db96d56Sopenharmony_ci    }
44647db96d56Sopenharmony_ci
44657db96d56Sopenharmony_ci    if (reduce_value == NULL)
44667db96d56Sopenharmony_ci        goto error;
44677db96d56Sopenharmony_ci
44687db96d56Sopenharmony_ci  reduce:
44697db96d56Sopenharmony_ci    if (PyUnicode_Check(reduce_value)) {
44707db96d56Sopenharmony_ci        status = save_global(self, obj, reduce_value);
44717db96d56Sopenharmony_ci        goto done;
44727db96d56Sopenharmony_ci    }
44737db96d56Sopenharmony_ci
44747db96d56Sopenharmony_ci    if (!PyTuple_Check(reduce_value)) {
44757db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
44767db96d56Sopenharmony_ci        PyErr_SetString(st->PicklingError,
44777db96d56Sopenharmony_ci                        "__reduce__ must return a string or tuple");
44787db96d56Sopenharmony_ci        goto error;
44797db96d56Sopenharmony_ci    }
44807db96d56Sopenharmony_ci
44817db96d56Sopenharmony_ci    status = save_reduce(self, reduce_value, obj);
44827db96d56Sopenharmony_ci
44837db96d56Sopenharmony_ci    if (0) {
44847db96d56Sopenharmony_ci  error:
44857db96d56Sopenharmony_ci        status = -1;
44867db96d56Sopenharmony_ci    }
44877db96d56Sopenharmony_ci  done:
44887db96d56Sopenharmony_ci
44897db96d56Sopenharmony_ci    _Py_LeaveRecursiveCall();
44907db96d56Sopenharmony_ci    Py_XDECREF(reduce_func);
44917db96d56Sopenharmony_ci    Py_XDECREF(reduce_value);
44927db96d56Sopenharmony_ci
44937db96d56Sopenharmony_ci    return status;
44947db96d56Sopenharmony_ci}
44957db96d56Sopenharmony_ci
44967db96d56Sopenharmony_cistatic int
44977db96d56Sopenharmony_cidump(PicklerObject *self, PyObject *obj)
44987db96d56Sopenharmony_ci{
44997db96d56Sopenharmony_ci    const char stop_op = STOP;
45007db96d56Sopenharmony_ci    int status = -1;
45017db96d56Sopenharmony_ci    PyObject *tmp;
45027db96d56Sopenharmony_ci
45037db96d56Sopenharmony_ci    if (_PyObject_LookupAttr((PyObject *)self, &_Py_ID(reducer_override),
45047db96d56Sopenharmony_ci                             &tmp) < 0) {
45057db96d56Sopenharmony_ci      goto error;
45067db96d56Sopenharmony_ci    }
45077db96d56Sopenharmony_ci    /* Cache the reducer_override method, if it exists. */
45087db96d56Sopenharmony_ci    if (tmp != NULL) {
45097db96d56Sopenharmony_ci        Py_XSETREF(self->reducer_override, tmp);
45107db96d56Sopenharmony_ci    }
45117db96d56Sopenharmony_ci    else {
45127db96d56Sopenharmony_ci        Py_CLEAR(self->reducer_override);
45137db96d56Sopenharmony_ci    }
45147db96d56Sopenharmony_ci
45157db96d56Sopenharmony_ci    if (self->proto >= 2) {
45167db96d56Sopenharmony_ci        char header[2];
45177db96d56Sopenharmony_ci
45187db96d56Sopenharmony_ci        header[0] = PROTO;
45197db96d56Sopenharmony_ci        assert(self->proto >= 0 && self->proto < 256);
45207db96d56Sopenharmony_ci        header[1] = (unsigned char)self->proto;
45217db96d56Sopenharmony_ci        if (_Pickler_Write(self, header, 2) < 0)
45227db96d56Sopenharmony_ci            goto error;
45237db96d56Sopenharmony_ci        if (self->proto >= 4)
45247db96d56Sopenharmony_ci            self->framing = 1;
45257db96d56Sopenharmony_ci    }
45267db96d56Sopenharmony_ci
45277db96d56Sopenharmony_ci    if (save(self, obj, 0) < 0 ||
45287db96d56Sopenharmony_ci        _Pickler_Write(self, &stop_op, 1) < 0 ||
45297db96d56Sopenharmony_ci        _Pickler_CommitFrame(self) < 0)
45307db96d56Sopenharmony_ci        goto error;
45317db96d56Sopenharmony_ci
45327db96d56Sopenharmony_ci    // Success
45337db96d56Sopenharmony_ci    status = 0;
45347db96d56Sopenharmony_ci
45357db96d56Sopenharmony_ci  error:
45367db96d56Sopenharmony_ci    self->framing = 0;
45377db96d56Sopenharmony_ci
45387db96d56Sopenharmony_ci    /* Break the reference cycle we generated at the beginning this function
45397db96d56Sopenharmony_ci     * call when setting the reducer_override attribute of the Pickler instance
45407db96d56Sopenharmony_ci     * to a bound method of the same instance. This is important as the Pickler
45417db96d56Sopenharmony_ci     * instance holds a reference to each object it has pickled (through its
45427db96d56Sopenharmony_ci     * memo): thus, these objects won't be garbage-collected as long as the
45437db96d56Sopenharmony_ci     * Pickler itself is not collected. */
45447db96d56Sopenharmony_ci    Py_CLEAR(self->reducer_override);
45457db96d56Sopenharmony_ci    return status;
45467db96d56Sopenharmony_ci}
45477db96d56Sopenharmony_ci
45487db96d56Sopenharmony_ci/*[clinic input]
45497db96d56Sopenharmony_ci
45507db96d56Sopenharmony_ci_pickle.Pickler.clear_memo
45517db96d56Sopenharmony_ci
45527db96d56Sopenharmony_ciClears the pickler's "memo".
45537db96d56Sopenharmony_ci
45547db96d56Sopenharmony_ciThe memo is the data structure that remembers which objects the
45557db96d56Sopenharmony_cipickler has already seen, so that shared or recursive objects are
45567db96d56Sopenharmony_cipickled by reference and not by value.  This method is useful when
45577db96d56Sopenharmony_cire-using picklers.
45587db96d56Sopenharmony_ci[clinic start generated code]*/
45597db96d56Sopenharmony_ci
45607db96d56Sopenharmony_cistatic PyObject *
45617db96d56Sopenharmony_ci_pickle_Pickler_clear_memo_impl(PicklerObject *self)
45627db96d56Sopenharmony_ci/*[clinic end generated code: output=8665c8658aaa094b input=01bdad52f3d93e56]*/
45637db96d56Sopenharmony_ci{
45647db96d56Sopenharmony_ci    if (self->memo)
45657db96d56Sopenharmony_ci        PyMemoTable_Clear(self->memo);
45667db96d56Sopenharmony_ci
45677db96d56Sopenharmony_ci    Py_RETURN_NONE;
45687db96d56Sopenharmony_ci}
45697db96d56Sopenharmony_ci
45707db96d56Sopenharmony_ci/*[clinic input]
45717db96d56Sopenharmony_ci
45727db96d56Sopenharmony_ci_pickle.Pickler.dump
45737db96d56Sopenharmony_ci
45747db96d56Sopenharmony_ci  obj: object
45757db96d56Sopenharmony_ci  /
45767db96d56Sopenharmony_ci
45777db96d56Sopenharmony_ciWrite a pickled representation of the given object to the open file.
45787db96d56Sopenharmony_ci[clinic start generated code]*/
45797db96d56Sopenharmony_ci
45807db96d56Sopenharmony_cistatic PyObject *
45817db96d56Sopenharmony_ci_pickle_Pickler_dump(PicklerObject *self, PyObject *obj)
45827db96d56Sopenharmony_ci/*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/
45837db96d56Sopenharmony_ci{
45847db96d56Sopenharmony_ci    /* Check whether the Pickler was initialized correctly (issue3664).
45857db96d56Sopenharmony_ci       Developers often forget to call __init__() in their subclasses, which
45867db96d56Sopenharmony_ci       would trigger a segfault without this check. */
45877db96d56Sopenharmony_ci    if (self->write == NULL) {
45887db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
45897db96d56Sopenharmony_ci        PyErr_Format(st->PicklingError,
45907db96d56Sopenharmony_ci                     "Pickler.__init__() was not called by %s.__init__()",
45917db96d56Sopenharmony_ci                     Py_TYPE(self)->tp_name);
45927db96d56Sopenharmony_ci        return NULL;
45937db96d56Sopenharmony_ci    }
45947db96d56Sopenharmony_ci
45957db96d56Sopenharmony_ci    if (_Pickler_ClearBuffer(self) < 0)
45967db96d56Sopenharmony_ci        return NULL;
45977db96d56Sopenharmony_ci
45987db96d56Sopenharmony_ci    if (dump(self, obj) < 0)
45997db96d56Sopenharmony_ci        return NULL;
46007db96d56Sopenharmony_ci
46017db96d56Sopenharmony_ci    if (_Pickler_FlushToFile(self) < 0)
46027db96d56Sopenharmony_ci        return NULL;
46037db96d56Sopenharmony_ci
46047db96d56Sopenharmony_ci    Py_RETURN_NONE;
46057db96d56Sopenharmony_ci}
46067db96d56Sopenharmony_ci
46077db96d56Sopenharmony_ci/*[clinic input]
46087db96d56Sopenharmony_ci
46097db96d56Sopenharmony_ci_pickle.Pickler.__sizeof__ -> Py_ssize_t
46107db96d56Sopenharmony_ci
46117db96d56Sopenharmony_ciReturns size in memory, in bytes.
46127db96d56Sopenharmony_ci[clinic start generated code]*/
46137db96d56Sopenharmony_ci
46147db96d56Sopenharmony_cistatic Py_ssize_t
46157db96d56Sopenharmony_ci_pickle_Pickler___sizeof___impl(PicklerObject *self)
46167db96d56Sopenharmony_ci/*[clinic end generated code: output=106edb3123f332e1 input=8cbbec9bd5540d42]*/
46177db96d56Sopenharmony_ci{
46187db96d56Sopenharmony_ci    Py_ssize_t res, s;
46197db96d56Sopenharmony_ci
46207db96d56Sopenharmony_ci    res = _PyObject_SIZE(Py_TYPE(self));
46217db96d56Sopenharmony_ci    if (self->memo != NULL) {
46227db96d56Sopenharmony_ci        res += sizeof(PyMemoTable);
46237db96d56Sopenharmony_ci        res += self->memo->mt_allocated * sizeof(PyMemoEntry);
46247db96d56Sopenharmony_ci    }
46257db96d56Sopenharmony_ci    if (self->output_buffer != NULL) {
46267db96d56Sopenharmony_ci        s = _PySys_GetSizeOf(self->output_buffer);
46277db96d56Sopenharmony_ci        if (s == -1)
46287db96d56Sopenharmony_ci            return -1;
46297db96d56Sopenharmony_ci        res += s;
46307db96d56Sopenharmony_ci    }
46317db96d56Sopenharmony_ci    return res;
46327db96d56Sopenharmony_ci}
46337db96d56Sopenharmony_ci
46347db96d56Sopenharmony_cistatic struct PyMethodDef Pickler_methods[] = {
46357db96d56Sopenharmony_ci    _PICKLE_PICKLER_DUMP_METHODDEF
46367db96d56Sopenharmony_ci    _PICKLE_PICKLER_CLEAR_MEMO_METHODDEF
46377db96d56Sopenharmony_ci    _PICKLE_PICKLER___SIZEOF___METHODDEF
46387db96d56Sopenharmony_ci    {NULL, NULL}                /* sentinel */
46397db96d56Sopenharmony_ci};
46407db96d56Sopenharmony_ci
46417db96d56Sopenharmony_cistatic void
46427db96d56Sopenharmony_ciPickler_dealloc(PicklerObject *self)
46437db96d56Sopenharmony_ci{
46447db96d56Sopenharmony_ci    PyObject_GC_UnTrack(self);
46457db96d56Sopenharmony_ci
46467db96d56Sopenharmony_ci    Py_XDECREF(self->output_buffer);
46477db96d56Sopenharmony_ci    Py_XDECREF(self->write);
46487db96d56Sopenharmony_ci    Py_XDECREF(self->pers_func);
46497db96d56Sopenharmony_ci    Py_XDECREF(self->dispatch_table);
46507db96d56Sopenharmony_ci    Py_XDECREF(self->fast_memo);
46517db96d56Sopenharmony_ci    Py_XDECREF(self->reducer_override);
46527db96d56Sopenharmony_ci    Py_XDECREF(self->buffer_callback);
46537db96d56Sopenharmony_ci
46547db96d56Sopenharmony_ci    PyMemoTable_Del(self->memo);
46557db96d56Sopenharmony_ci
46567db96d56Sopenharmony_ci    Py_TYPE(self)->tp_free((PyObject *)self);
46577db96d56Sopenharmony_ci}
46587db96d56Sopenharmony_ci
46597db96d56Sopenharmony_cistatic int
46607db96d56Sopenharmony_ciPickler_traverse(PicklerObject *self, visitproc visit, void *arg)
46617db96d56Sopenharmony_ci{
46627db96d56Sopenharmony_ci    Py_VISIT(self->write);
46637db96d56Sopenharmony_ci    Py_VISIT(self->pers_func);
46647db96d56Sopenharmony_ci    Py_VISIT(self->dispatch_table);
46657db96d56Sopenharmony_ci    Py_VISIT(self->fast_memo);
46667db96d56Sopenharmony_ci    Py_VISIT(self->reducer_override);
46677db96d56Sopenharmony_ci    Py_VISIT(self->buffer_callback);
46687db96d56Sopenharmony_ci    return 0;
46697db96d56Sopenharmony_ci}
46707db96d56Sopenharmony_ci
46717db96d56Sopenharmony_cistatic int
46727db96d56Sopenharmony_ciPickler_clear(PicklerObject *self)
46737db96d56Sopenharmony_ci{
46747db96d56Sopenharmony_ci    Py_CLEAR(self->output_buffer);
46757db96d56Sopenharmony_ci    Py_CLEAR(self->write);
46767db96d56Sopenharmony_ci    Py_CLEAR(self->pers_func);
46777db96d56Sopenharmony_ci    Py_CLEAR(self->dispatch_table);
46787db96d56Sopenharmony_ci    Py_CLEAR(self->fast_memo);
46797db96d56Sopenharmony_ci    Py_CLEAR(self->reducer_override);
46807db96d56Sopenharmony_ci    Py_CLEAR(self->buffer_callback);
46817db96d56Sopenharmony_ci
46827db96d56Sopenharmony_ci    if (self->memo != NULL) {
46837db96d56Sopenharmony_ci        PyMemoTable *memo = self->memo;
46847db96d56Sopenharmony_ci        self->memo = NULL;
46857db96d56Sopenharmony_ci        PyMemoTable_Del(memo);
46867db96d56Sopenharmony_ci    }
46877db96d56Sopenharmony_ci    return 0;
46887db96d56Sopenharmony_ci}
46897db96d56Sopenharmony_ci
46907db96d56Sopenharmony_ci
46917db96d56Sopenharmony_ci/*[clinic input]
46927db96d56Sopenharmony_ci
46937db96d56Sopenharmony_ci_pickle.Pickler.__init__
46947db96d56Sopenharmony_ci
46957db96d56Sopenharmony_ci  file: object
46967db96d56Sopenharmony_ci  protocol: object = None
46977db96d56Sopenharmony_ci  fix_imports: bool = True
46987db96d56Sopenharmony_ci  buffer_callback: object = None
46997db96d56Sopenharmony_ci
47007db96d56Sopenharmony_ciThis takes a binary file for writing a pickle data stream.
47017db96d56Sopenharmony_ci
47027db96d56Sopenharmony_ciThe optional *protocol* argument tells the pickler to use the given
47037db96d56Sopenharmony_ciprotocol; supported protocols are 0, 1, 2, 3, 4 and 5.  The default
47047db96d56Sopenharmony_ciprotocol is 4. It was introduced in Python 3.4, and is incompatible
47057db96d56Sopenharmony_ciwith previous versions.
47067db96d56Sopenharmony_ci
47077db96d56Sopenharmony_ciSpecifying a negative protocol version selects the highest protocol
47087db96d56Sopenharmony_civersion supported.  The higher the protocol used, the more recent the
47097db96d56Sopenharmony_civersion of Python needed to read the pickle produced.
47107db96d56Sopenharmony_ci
47117db96d56Sopenharmony_ciThe *file* argument must have a write() method that accepts a single
47127db96d56Sopenharmony_cibytes argument. It can thus be a file object opened for binary
47137db96d56Sopenharmony_ciwriting, an io.BytesIO instance, or any other custom object that meets
47147db96d56Sopenharmony_cithis interface.
47157db96d56Sopenharmony_ci
47167db96d56Sopenharmony_ciIf *fix_imports* is True and protocol is less than 3, pickle will try
47177db96d56Sopenharmony_cito map the new Python 3 names to the old module names used in Python
47187db96d56Sopenharmony_ci2, so that the pickle data stream is readable with Python 2.
47197db96d56Sopenharmony_ci
47207db96d56Sopenharmony_ciIf *buffer_callback* is None (the default), buffer views are
47217db96d56Sopenharmony_ciserialized into *file* as part of the pickle stream.
47227db96d56Sopenharmony_ci
47237db96d56Sopenharmony_ciIf *buffer_callback* is not None, then it can be called any number
47247db96d56Sopenharmony_ciof times with a buffer view.  If the callback returns a false value
47257db96d56Sopenharmony_ci(such as None), the given buffer is out-of-band; otherwise the
47267db96d56Sopenharmony_cibuffer is serialized in-band, i.e. inside the pickle stream.
47277db96d56Sopenharmony_ci
47287db96d56Sopenharmony_ciIt is an error if *buffer_callback* is not None and *protocol*
47297db96d56Sopenharmony_ciis None or smaller than 5.
47307db96d56Sopenharmony_ci
47317db96d56Sopenharmony_ci[clinic start generated code]*/
47327db96d56Sopenharmony_ci
47337db96d56Sopenharmony_cistatic int
47347db96d56Sopenharmony_ci_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file,
47357db96d56Sopenharmony_ci                              PyObject *protocol, int fix_imports,
47367db96d56Sopenharmony_ci                              PyObject *buffer_callback)
47377db96d56Sopenharmony_ci/*[clinic end generated code: output=0abedc50590d259b input=a7c969699bf5dad3]*/
47387db96d56Sopenharmony_ci{
47397db96d56Sopenharmony_ci    /* In case of multiple __init__() calls, clear previous content. */
47407db96d56Sopenharmony_ci    if (self->write != NULL)
47417db96d56Sopenharmony_ci        (void)Pickler_clear(self);
47427db96d56Sopenharmony_ci
47437db96d56Sopenharmony_ci    if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0)
47447db96d56Sopenharmony_ci        return -1;
47457db96d56Sopenharmony_ci
47467db96d56Sopenharmony_ci    if (_Pickler_SetOutputStream(self, file) < 0)
47477db96d56Sopenharmony_ci        return -1;
47487db96d56Sopenharmony_ci
47497db96d56Sopenharmony_ci    if (_Pickler_SetBufferCallback(self, buffer_callback) < 0)
47507db96d56Sopenharmony_ci        return -1;
47517db96d56Sopenharmony_ci
47527db96d56Sopenharmony_ci    /* memo and output_buffer may have already been created in _Pickler_New */
47537db96d56Sopenharmony_ci    if (self->memo == NULL) {
47547db96d56Sopenharmony_ci        self->memo = PyMemoTable_New();
47557db96d56Sopenharmony_ci        if (self->memo == NULL)
47567db96d56Sopenharmony_ci            return -1;
47577db96d56Sopenharmony_ci    }
47587db96d56Sopenharmony_ci    self->output_len = 0;
47597db96d56Sopenharmony_ci    if (self->output_buffer == NULL) {
47607db96d56Sopenharmony_ci        self->max_output_len = WRITE_BUF_SIZE;
47617db96d56Sopenharmony_ci        self->output_buffer = PyBytes_FromStringAndSize(NULL,
47627db96d56Sopenharmony_ci                                                        self->max_output_len);
47637db96d56Sopenharmony_ci        if (self->output_buffer == NULL)
47647db96d56Sopenharmony_ci            return -1;
47657db96d56Sopenharmony_ci    }
47667db96d56Sopenharmony_ci
47677db96d56Sopenharmony_ci    self->fast = 0;
47687db96d56Sopenharmony_ci    self->fast_nesting = 0;
47697db96d56Sopenharmony_ci    self->fast_memo = NULL;
47707db96d56Sopenharmony_ci
47717db96d56Sopenharmony_ci    if (init_method_ref((PyObject *)self, &_Py_ID(persistent_id),
47727db96d56Sopenharmony_ci                        &self->pers_func, &self->pers_func_self) < 0)
47737db96d56Sopenharmony_ci    {
47747db96d56Sopenharmony_ci        return -1;
47757db96d56Sopenharmony_ci    }
47767db96d56Sopenharmony_ci    if (self->dispatch_table != NULL) {
47777db96d56Sopenharmony_ci        return 0;
47787db96d56Sopenharmony_ci    }
47797db96d56Sopenharmony_ci    if (_PyObject_LookupAttr((PyObject *)self, &_Py_ID(dispatch_table),
47807db96d56Sopenharmony_ci                             &self->dispatch_table) < 0) {
47817db96d56Sopenharmony_ci        return -1;
47827db96d56Sopenharmony_ci    }
47837db96d56Sopenharmony_ci
47847db96d56Sopenharmony_ci    return 0;
47857db96d56Sopenharmony_ci}
47867db96d56Sopenharmony_ci
47877db96d56Sopenharmony_ci
47887db96d56Sopenharmony_ci/* Define a proxy object for the Pickler's internal memo object. This is to
47897db96d56Sopenharmony_ci * avoid breaking code like:
47907db96d56Sopenharmony_ci *  pickler.memo.clear()
47917db96d56Sopenharmony_ci * and
47927db96d56Sopenharmony_ci *  pickler.memo = saved_memo
47937db96d56Sopenharmony_ci * Is this a good idea? Not really, but we don't want to break code that uses
47947db96d56Sopenharmony_ci * it. Note that we don't implement the entire mapping API here. This is
47957db96d56Sopenharmony_ci * intentional, as these should be treated as black-box implementation details.
47967db96d56Sopenharmony_ci */
47977db96d56Sopenharmony_ci
47987db96d56Sopenharmony_ci/*[clinic input]
47997db96d56Sopenharmony_ci_pickle.PicklerMemoProxy.clear
48007db96d56Sopenharmony_ci
48017db96d56Sopenharmony_ciRemove all items from memo.
48027db96d56Sopenharmony_ci[clinic start generated code]*/
48037db96d56Sopenharmony_ci
48047db96d56Sopenharmony_cistatic PyObject *
48057db96d56Sopenharmony_ci_pickle_PicklerMemoProxy_clear_impl(PicklerMemoProxyObject *self)
48067db96d56Sopenharmony_ci/*[clinic end generated code: output=5fb9370d48ae8b05 input=ccc186dacd0f1405]*/
48077db96d56Sopenharmony_ci{
48087db96d56Sopenharmony_ci    if (self->pickler->memo)
48097db96d56Sopenharmony_ci        PyMemoTable_Clear(self->pickler->memo);
48107db96d56Sopenharmony_ci    Py_RETURN_NONE;
48117db96d56Sopenharmony_ci}
48127db96d56Sopenharmony_ci
48137db96d56Sopenharmony_ci/*[clinic input]
48147db96d56Sopenharmony_ci_pickle.PicklerMemoProxy.copy
48157db96d56Sopenharmony_ci
48167db96d56Sopenharmony_ciCopy the memo to a new object.
48177db96d56Sopenharmony_ci[clinic start generated code]*/
48187db96d56Sopenharmony_ci
48197db96d56Sopenharmony_cistatic PyObject *
48207db96d56Sopenharmony_ci_pickle_PicklerMemoProxy_copy_impl(PicklerMemoProxyObject *self)
48217db96d56Sopenharmony_ci/*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
48227db96d56Sopenharmony_ci{
48237db96d56Sopenharmony_ci    PyMemoTable *memo;
48247db96d56Sopenharmony_ci    PyObject *new_memo = PyDict_New();
48257db96d56Sopenharmony_ci    if (new_memo == NULL)
48267db96d56Sopenharmony_ci        return NULL;
48277db96d56Sopenharmony_ci
48287db96d56Sopenharmony_ci    memo = self->pickler->memo;
48297db96d56Sopenharmony_ci    for (size_t i = 0; i < memo->mt_allocated; ++i) {
48307db96d56Sopenharmony_ci        PyMemoEntry entry = memo->mt_table[i];
48317db96d56Sopenharmony_ci        if (entry.me_key != NULL) {
48327db96d56Sopenharmony_ci            int status;
48337db96d56Sopenharmony_ci            PyObject *key, *value;
48347db96d56Sopenharmony_ci
48357db96d56Sopenharmony_ci            key = PyLong_FromVoidPtr(entry.me_key);
48367db96d56Sopenharmony_ci            value = Py_BuildValue("nO", entry.me_value, entry.me_key);
48377db96d56Sopenharmony_ci
48387db96d56Sopenharmony_ci            if (key == NULL || value == NULL) {
48397db96d56Sopenharmony_ci                Py_XDECREF(key);
48407db96d56Sopenharmony_ci                Py_XDECREF(value);
48417db96d56Sopenharmony_ci                goto error;
48427db96d56Sopenharmony_ci            }
48437db96d56Sopenharmony_ci            status = PyDict_SetItem(new_memo, key, value);
48447db96d56Sopenharmony_ci            Py_DECREF(key);
48457db96d56Sopenharmony_ci            Py_DECREF(value);
48467db96d56Sopenharmony_ci            if (status < 0)
48477db96d56Sopenharmony_ci                goto error;
48487db96d56Sopenharmony_ci        }
48497db96d56Sopenharmony_ci    }
48507db96d56Sopenharmony_ci    return new_memo;
48517db96d56Sopenharmony_ci
48527db96d56Sopenharmony_ci  error:
48537db96d56Sopenharmony_ci    Py_XDECREF(new_memo);
48547db96d56Sopenharmony_ci    return NULL;
48557db96d56Sopenharmony_ci}
48567db96d56Sopenharmony_ci
48577db96d56Sopenharmony_ci/*[clinic input]
48587db96d56Sopenharmony_ci_pickle.PicklerMemoProxy.__reduce__
48597db96d56Sopenharmony_ci
48607db96d56Sopenharmony_ciImplement pickle support.
48617db96d56Sopenharmony_ci[clinic start generated code]*/
48627db96d56Sopenharmony_ci
48637db96d56Sopenharmony_cistatic PyObject *
48647db96d56Sopenharmony_ci_pickle_PicklerMemoProxy___reduce___impl(PicklerMemoProxyObject *self)
48657db96d56Sopenharmony_ci/*[clinic end generated code: output=bebba1168863ab1d input=2f7c540e24b7aae4]*/
48667db96d56Sopenharmony_ci{
48677db96d56Sopenharmony_ci    PyObject *reduce_value, *dict_args;
48687db96d56Sopenharmony_ci    PyObject *contents = _pickle_PicklerMemoProxy_copy_impl(self);
48697db96d56Sopenharmony_ci    if (contents == NULL)
48707db96d56Sopenharmony_ci        return NULL;
48717db96d56Sopenharmony_ci
48727db96d56Sopenharmony_ci    reduce_value = PyTuple_New(2);
48737db96d56Sopenharmony_ci    if (reduce_value == NULL) {
48747db96d56Sopenharmony_ci        Py_DECREF(contents);
48757db96d56Sopenharmony_ci        return NULL;
48767db96d56Sopenharmony_ci    }
48777db96d56Sopenharmony_ci    dict_args = PyTuple_New(1);
48787db96d56Sopenharmony_ci    if (dict_args == NULL) {
48797db96d56Sopenharmony_ci        Py_DECREF(contents);
48807db96d56Sopenharmony_ci        Py_DECREF(reduce_value);
48817db96d56Sopenharmony_ci        return NULL;
48827db96d56Sopenharmony_ci    }
48837db96d56Sopenharmony_ci    PyTuple_SET_ITEM(dict_args, 0, contents);
48847db96d56Sopenharmony_ci    Py_INCREF((PyObject *)&PyDict_Type);
48857db96d56Sopenharmony_ci    PyTuple_SET_ITEM(reduce_value, 0, (PyObject *)&PyDict_Type);
48867db96d56Sopenharmony_ci    PyTuple_SET_ITEM(reduce_value, 1, dict_args);
48877db96d56Sopenharmony_ci    return reduce_value;
48887db96d56Sopenharmony_ci}
48897db96d56Sopenharmony_ci
48907db96d56Sopenharmony_cistatic PyMethodDef picklerproxy_methods[] = {
48917db96d56Sopenharmony_ci    _PICKLE_PICKLERMEMOPROXY_CLEAR_METHODDEF
48927db96d56Sopenharmony_ci    _PICKLE_PICKLERMEMOPROXY_COPY_METHODDEF
48937db96d56Sopenharmony_ci    _PICKLE_PICKLERMEMOPROXY___REDUCE___METHODDEF
48947db96d56Sopenharmony_ci    {NULL, NULL} /* sentinel */
48957db96d56Sopenharmony_ci};
48967db96d56Sopenharmony_ci
48977db96d56Sopenharmony_cistatic void
48987db96d56Sopenharmony_ciPicklerMemoProxy_dealloc(PicklerMemoProxyObject *self)
48997db96d56Sopenharmony_ci{
49007db96d56Sopenharmony_ci    PyObject_GC_UnTrack(self);
49017db96d56Sopenharmony_ci    Py_XDECREF(self->pickler);
49027db96d56Sopenharmony_ci    PyObject_GC_Del((PyObject *)self);
49037db96d56Sopenharmony_ci}
49047db96d56Sopenharmony_ci
49057db96d56Sopenharmony_cistatic int
49067db96d56Sopenharmony_ciPicklerMemoProxy_traverse(PicklerMemoProxyObject *self,
49077db96d56Sopenharmony_ci                          visitproc visit, void *arg)
49087db96d56Sopenharmony_ci{
49097db96d56Sopenharmony_ci    Py_VISIT(self->pickler);
49107db96d56Sopenharmony_ci    return 0;
49117db96d56Sopenharmony_ci}
49127db96d56Sopenharmony_ci
49137db96d56Sopenharmony_cistatic int
49147db96d56Sopenharmony_ciPicklerMemoProxy_clear(PicklerMemoProxyObject *self)
49157db96d56Sopenharmony_ci{
49167db96d56Sopenharmony_ci    Py_CLEAR(self->pickler);
49177db96d56Sopenharmony_ci    return 0;
49187db96d56Sopenharmony_ci}
49197db96d56Sopenharmony_ci
49207db96d56Sopenharmony_cistatic PyTypeObject PicklerMemoProxyType = {
49217db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(NULL, 0)
49227db96d56Sopenharmony_ci    "_pickle.PicklerMemoProxy",                 /*tp_name*/
49237db96d56Sopenharmony_ci    sizeof(PicklerMemoProxyObject),             /*tp_basicsize*/
49247db96d56Sopenharmony_ci    0,
49257db96d56Sopenharmony_ci    (destructor)PicklerMemoProxy_dealloc,       /* tp_dealloc */
49267db96d56Sopenharmony_ci    0,                                          /* tp_vectorcall_offset */
49277db96d56Sopenharmony_ci    0,                                          /* tp_getattr */
49287db96d56Sopenharmony_ci    0,                                          /* tp_setattr */
49297db96d56Sopenharmony_ci    0,                                          /* tp_as_async */
49307db96d56Sopenharmony_ci    0,                                          /* tp_repr */
49317db96d56Sopenharmony_ci    0,                                          /* tp_as_number */
49327db96d56Sopenharmony_ci    0,                                          /* tp_as_sequence */
49337db96d56Sopenharmony_ci    0,                                          /* tp_as_mapping */
49347db96d56Sopenharmony_ci    PyObject_HashNotImplemented,                /* tp_hash */
49357db96d56Sopenharmony_ci    0,                                          /* tp_call */
49367db96d56Sopenharmony_ci    0,                                          /* tp_str */
49377db96d56Sopenharmony_ci    PyObject_GenericGetAttr,                    /* tp_getattro */
49387db96d56Sopenharmony_ci    PyObject_GenericSetAttr,                    /* tp_setattro */
49397db96d56Sopenharmony_ci    0,                                          /* tp_as_buffer */
49407db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
49417db96d56Sopenharmony_ci    0,                                          /* tp_doc */
49427db96d56Sopenharmony_ci    (traverseproc)PicklerMemoProxy_traverse,    /* tp_traverse */
49437db96d56Sopenharmony_ci    (inquiry)PicklerMemoProxy_clear,            /* tp_clear */
49447db96d56Sopenharmony_ci    0,                                          /* tp_richcompare */
49457db96d56Sopenharmony_ci    0,                                          /* tp_weaklistoffset */
49467db96d56Sopenharmony_ci    0,                                          /* tp_iter */
49477db96d56Sopenharmony_ci    0,                                          /* tp_iternext */
49487db96d56Sopenharmony_ci    picklerproxy_methods,                       /* tp_methods */
49497db96d56Sopenharmony_ci};
49507db96d56Sopenharmony_ci
49517db96d56Sopenharmony_cistatic PyObject *
49527db96d56Sopenharmony_ciPicklerMemoProxy_New(PicklerObject *pickler)
49537db96d56Sopenharmony_ci{
49547db96d56Sopenharmony_ci    PicklerMemoProxyObject *self;
49557db96d56Sopenharmony_ci
49567db96d56Sopenharmony_ci    self = PyObject_GC_New(PicklerMemoProxyObject, &PicklerMemoProxyType);
49577db96d56Sopenharmony_ci    if (self == NULL)
49587db96d56Sopenharmony_ci        return NULL;
49597db96d56Sopenharmony_ci    Py_INCREF(pickler);
49607db96d56Sopenharmony_ci    self->pickler = pickler;
49617db96d56Sopenharmony_ci    PyObject_GC_Track(self);
49627db96d56Sopenharmony_ci    return (PyObject *)self;
49637db96d56Sopenharmony_ci}
49647db96d56Sopenharmony_ci
49657db96d56Sopenharmony_ci/*****************************************************************************/
49667db96d56Sopenharmony_ci
49677db96d56Sopenharmony_cistatic PyObject *
49687db96d56Sopenharmony_ciPickler_get_memo(PicklerObject *self, void *Py_UNUSED(ignored))
49697db96d56Sopenharmony_ci{
49707db96d56Sopenharmony_ci    return PicklerMemoProxy_New(self);
49717db96d56Sopenharmony_ci}
49727db96d56Sopenharmony_ci
49737db96d56Sopenharmony_cistatic int
49747db96d56Sopenharmony_ciPickler_set_memo(PicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored))
49757db96d56Sopenharmony_ci{
49767db96d56Sopenharmony_ci    PyMemoTable *new_memo = NULL;
49777db96d56Sopenharmony_ci
49787db96d56Sopenharmony_ci    if (obj == NULL) {
49797db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError,
49807db96d56Sopenharmony_ci                        "attribute deletion is not supported");
49817db96d56Sopenharmony_ci        return -1;
49827db96d56Sopenharmony_ci    }
49837db96d56Sopenharmony_ci
49847db96d56Sopenharmony_ci    if (Py_IS_TYPE(obj, &PicklerMemoProxyType)) {
49857db96d56Sopenharmony_ci        PicklerObject *pickler =
49867db96d56Sopenharmony_ci            ((PicklerMemoProxyObject *)obj)->pickler;
49877db96d56Sopenharmony_ci
49887db96d56Sopenharmony_ci        new_memo = PyMemoTable_Copy(pickler->memo);
49897db96d56Sopenharmony_ci        if (new_memo == NULL)
49907db96d56Sopenharmony_ci            return -1;
49917db96d56Sopenharmony_ci    }
49927db96d56Sopenharmony_ci    else if (PyDict_Check(obj)) {
49937db96d56Sopenharmony_ci        Py_ssize_t i = 0;
49947db96d56Sopenharmony_ci        PyObject *key, *value;
49957db96d56Sopenharmony_ci
49967db96d56Sopenharmony_ci        new_memo = PyMemoTable_New();
49977db96d56Sopenharmony_ci        if (new_memo == NULL)
49987db96d56Sopenharmony_ci            return -1;
49997db96d56Sopenharmony_ci
50007db96d56Sopenharmony_ci        while (PyDict_Next(obj, &i, &key, &value)) {
50017db96d56Sopenharmony_ci            Py_ssize_t memo_id;
50027db96d56Sopenharmony_ci            PyObject *memo_obj;
50037db96d56Sopenharmony_ci
50047db96d56Sopenharmony_ci            if (!PyTuple_Check(value) || PyTuple_GET_SIZE(value) != 2) {
50057db96d56Sopenharmony_ci                PyErr_SetString(PyExc_TypeError,
50067db96d56Sopenharmony_ci                                "'memo' values must be 2-item tuples");
50077db96d56Sopenharmony_ci                goto error;
50087db96d56Sopenharmony_ci            }
50097db96d56Sopenharmony_ci            memo_id = PyLong_AsSsize_t(PyTuple_GET_ITEM(value, 0));
50107db96d56Sopenharmony_ci            if (memo_id == -1 && PyErr_Occurred())
50117db96d56Sopenharmony_ci                goto error;
50127db96d56Sopenharmony_ci            memo_obj = PyTuple_GET_ITEM(value, 1);
50137db96d56Sopenharmony_ci            if (PyMemoTable_Set(new_memo, memo_obj, memo_id) < 0)
50147db96d56Sopenharmony_ci                goto error;
50157db96d56Sopenharmony_ci        }
50167db96d56Sopenharmony_ci    }
50177db96d56Sopenharmony_ci    else {
50187db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
50197db96d56Sopenharmony_ci                     "'memo' attribute must be a PicklerMemoProxy object "
50207db96d56Sopenharmony_ci                     "or dict, not %.200s", Py_TYPE(obj)->tp_name);
50217db96d56Sopenharmony_ci        return -1;
50227db96d56Sopenharmony_ci    }
50237db96d56Sopenharmony_ci
50247db96d56Sopenharmony_ci    PyMemoTable_Del(self->memo);
50257db96d56Sopenharmony_ci    self->memo = new_memo;
50267db96d56Sopenharmony_ci
50277db96d56Sopenharmony_ci    return 0;
50287db96d56Sopenharmony_ci
50297db96d56Sopenharmony_ci  error:
50307db96d56Sopenharmony_ci    if (new_memo)
50317db96d56Sopenharmony_ci        PyMemoTable_Del(new_memo);
50327db96d56Sopenharmony_ci    return -1;
50337db96d56Sopenharmony_ci}
50347db96d56Sopenharmony_ci
50357db96d56Sopenharmony_cistatic PyObject *
50367db96d56Sopenharmony_ciPickler_get_persid(PicklerObject *self, void *Py_UNUSED(ignored))
50377db96d56Sopenharmony_ci{
50387db96d56Sopenharmony_ci    if (self->pers_func == NULL) {
50397db96d56Sopenharmony_ci        PyErr_SetString(PyExc_AttributeError, "persistent_id");
50407db96d56Sopenharmony_ci        return NULL;
50417db96d56Sopenharmony_ci    }
50427db96d56Sopenharmony_ci    return reconstruct_method(self->pers_func, self->pers_func_self);
50437db96d56Sopenharmony_ci}
50447db96d56Sopenharmony_ci
50457db96d56Sopenharmony_cistatic int
50467db96d56Sopenharmony_ciPickler_set_persid(PicklerObject *self, PyObject *value, void *Py_UNUSED(ignored))
50477db96d56Sopenharmony_ci{
50487db96d56Sopenharmony_ci    if (value == NULL) {
50497db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError,
50507db96d56Sopenharmony_ci                        "attribute deletion is not supported");
50517db96d56Sopenharmony_ci        return -1;
50527db96d56Sopenharmony_ci    }
50537db96d56Sopenharmony_ci    if (!PyCallable_Check(value)) {
50547db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError,
50557db96d56Sopenharmony_ci                        "persistent_id must be a callable taking one argument");
50567db96d56Sopenharmony_ci        return -1;
50577db96d56Sopenharmony_ci    }
50587db96d56Sopenharmony_ci
50597db96d56Sopenharmony_ci    self->pers_func_self = NULL;
50607db96d56Sopenharmony_ci    Py_INCREF(value);
50617db96d56Sopenharmony_ci    Py_XSETREF(self->pers_func, value);
50627db96d56Sopenharmony_ci
50637db96d56Sopenharmony_ci    return 0;
50647db96d56Sopenharmony_ci}
50657db96d56Sopenharmony_ci
50667db96d56Sopenharmony_cistatic PyMemberDef Pickler_members[] = {
50677db96d56Sopenharmony_ci    {"bin", T_INT, offsetof(PicklerObject, bin)},
50687db96d56Sopenharmony_ci    {"fast", T_INT, offsetof(PicklerObject, fast)},
50697db96d56Sopenharmony_ci    {"dispatch_table", T_OBJECT_EX, offsetof(PicklerObject, dispatch_table)},
50707db96d56Sopenharmony_ci    {NULL}
50717db96d56Sopenharmony_ci};
50727db96d56Sopenharmony_ci
50737db96d56Sopenharmony_cistatic PyGetSetDef Pickler_getsets[] = {
50747db96d56Sopenharmony_ci    {"memo",          (getter)Pickler_get_memo,
50757db96d56Sopenharmony_ci                      (setter)Pickler_set_memo},
50767db96d56Sopenharmony_ci    {"persistent_id", (getter)Pickler_get_persid,
50777db96d56Sopenharmony_ci                      (setter)Pickler_set_persid},
50787db96d56Sopenharmony_ci    {NULL}
50797db96d56Sopenharmony_ci};
50807db96d56Sopenharmony_ci
50817db96d56Sopenharmony_cistatic PyTypeObject Pickler_Type = {
50827db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(NULL, 0)
50837db96d56Sopenharmony_ci    "_pickle.Pickler"  ,                /*tp_name*/
50847db96d56Sopenharmony_ci    sizeof(PicklerObject),              /*tp_basicsize*/
50857db96d56Sopenharmony_ci    0,                                  /*tp_itemsize*/
50867db96d56Sopenharmony_ci    (destructor)Pickler_dealloc,        /*tp_dealloc*/
50877db96d56Sopenharmony_ci    0,                                  /*tp_vectorcall_offset*/
50887db96d56Sopenharmony_ci    0,                                  /*tp_getattr*/
50897db96d56Sopenharmony_ci    0,                                  /*tp_setattr*/
50907db96d56Sopenharmony_ci    0,                                  /*tp_as_async*/
50917db96d56Sopenharmony_ci    0,                                  /*tp_repr*/
50927db96d56Sopenharmony_ci    0,                                  /*tp_as_number*/
50937db96d56Sopenharmony_ci    0,                                  /*tp_as_sequence*/
50947db96d56Sopenharmony_ci    0,                                  /*tp_as_mapping*/
50957db96d56Sopenharmony_ci    0,                                  /*tp_hash*/
50967db96d56Sopenharmony_ci    0,                                  /*tp_call*/
50977db96d56Sopenharmony_ci    0,                                  /*tp_str*/
50987db96d56Sopenharmony_ci    0,                                  /*tp_getattro*/
50997db96d56Sopenharmony_ci    0,                                  /*tp_setattro*/
51007db96d56Sopenharmony_ci    0,                                  /*tp_as_buffer*/
51017db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
51027db96d56Sopenharmony_ci    _pickle_Pickler___init____doc__,    /*tp_doc*/
51037db96d56Sopenharmony_ci    (traverseproc)Pickler_traverse,     /*tp_traverse*/
51047db96d56Sopenharmony_ci    (inquiry)Pickler_clear,             /*tp_clear*/
51057db96d56Sopenharmony_ci    0,                                  /*tp_richcompare*/
51067db96d56Sopenharmony_ci    0,                                  /*tp_weaklistoffset*/
51077db96d56Sopenharmony_ci    0,                                  /*tp_iter*/
51087db96d56Sopenharmony_ci    0,                                  /*tp_iternext*/
51097db96d56Sopenharmony_ci    Pickler_methods,                    /*tp_methods*/
51107db96d56Sopenharmony_ci    Pickler_members,                    /*tp_members*/
51117db96d56Sopenharmony_ci    Pickler_getsets,                    /*tp_getset*/
51127db96d56Sopenharmony_ci    0,                                  /*tp_base*/
51137db96d56Sopenharmony_ci    0,                                  /*tp_dict*/
51147db96d56Sopenharmony_ci    0,                                  /*tp_descr_get*/
51157db96d56Sopenharmony_ci    0,                                  /*tp_descr_set*/
51167db96d56Sopenharmony_ci    0,                                  /*tp_dictoffset*/
51177db96d56Sopenharmony_ci    _pickle_Pickler___init__,           /*tp_init*/
51187db96d56Sopenharmony_ci    PyType_GenericAlloc,                /*tp_alloc*/
51197db96d56Sopenharmony_ci    PyType_GenericNew,                  /*tp_new*/
51207db96d56Sopenharmony_ci    PyObject_GC_Del,                    /*tp_free*/
51217db96d56Sopenharmony_ci    0,                                  /*tp_is_gc*/
51227db96d56Sopenharmony_ci};
51237db96d56Sopenharmony_ci
51247db96d56Sopenharmony_ci/* Temporary helper for calling self.find_class().
51257db96d56Sopenharmony_ci
51267db96d56Sopenharmony_ci   XXX: It would be nice to able to avoid Python function call overhead, by
51277db96d56Sopenharmony_ci   using directly the C version of find_class(), when find_class() is not
51287db96d56Sopenharmony_ci   overridden by a subclass. Although, this could become rather hackish. A
51297db96d56Sopenharmony_ci   simpler optimization would be to call the C function when self is not a
51307db96d56Sopenharmony_ci   subclass instance. */
51317db96d56Sopenharmony_cistatic PyObject *
51327db96d56Sopenharmony_cifind_class(UnpicklerObject *self, PyObject *module_name, PyObject *global_name)
51337db96d56Sopenharmony_ci{
51347db96d56Sopenharmony_ci    return PyObject_CallMethodObjArgs((PyObject *)self, &_Py_ID(find_class),
51357db96d56Sopenharmony_ci                                      module_name, global_name, NULL);
51367db96d56Sopenharmony_ci}
51377db96d56Sopenharmony_ci
51387db96d56Sopenharmony_cistatic Py_ssize_t
51397db96d56Sopenharmony_cimarker(UnpicklerObject *self)
51407db96d56Sopenharmony_ci{
51417db96d56Sopenharmony_ci    Py_ssize_t mark;
51427db96d56Sopenharmony_ci
51437db96d56Sopenharmony_ci    if (self->num_marks < 1) {
51447db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
51457db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError, "could not find MARK");
51467db96d56Sopenharmony_ci        return -1;
51477db96d56Sopenharmony_ci    }
51487db96d56Sopenharmony_ci
51497db96d56Sopenharmony_ci    mark = self->marks[--self->num_marks];
51507db96d56Sopenharmony_ci    self->stack->mark_set = self->num_marks != 0;
51517db96d56Sopenharmony_ci    self->stack->fence = self->num_marks ?
51527db96d56Sopenharmony_ci            self->marks[self->num_marks - 1] : 0;
51537db96d56Sopenharmony_ci    return mark;
51547db96d56Sopenharmony_ci}
51557db96d56Sopenharmony_ci
51567db96d56Sopenharmony_cistatic int
51577db96d56Sopenharmony_ciload_none(UnpicklerObject *self)
51587db96d56Sopenharmony_ci{
51597db96d56Sopenharmony_ci    PDATA_APPEND(self->stack, Py_None, -1);
51607db96d56Sopenharmony_ci    return 0;
51617db96d56Sopenharmony_ci}
51627db96d56Sopenharmony_ci
51637db96d56Sopenharmony_cistatic int
51647db96d56Sopenharmony_ciload_int(UnpicklerObject *self)
51657db96d56Sopenharmony_ci{
51667db96d56Sopenharmony_ci    PyObject *value;
51677db96d56Sopenharmony_ci    char *endptr, *s;
51687db96d56Sopenharmony_ci    Py_ssize_t len;
51697db96d56Sopenharmony_ci    long x;
51707db96d56Sopenharmony_ci
51717db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) < 0)
51727db96d56Sopenharmony_ci        return -1;
51737db96d56Sopenharmony_ci    if (len < 2)
51747db96d56Sopenharmony_ci        return bad_readline();
51757db96d56Sopenharmony_ci
51767db96d56Sopenharmony_ci    errno = 0;
51777db96d56Sopenharmony_ci    /* XXX: Should the base argument of strtol() be explicitly set to 10?
51787db96d56Sopenharmony_ci       XXX(avassalotti): Should this uses PyOS_strtol()? */
51797db96d56Sopenharmony_ci    x = strtol(s, &endptr, 0);
51807db96d56Sopenharmony_ci
51817db96d56Sopenharmony_ci    if (errno || (*endptr != '\n' && *endptr != '\0')) {
51827db96d56Sopenharmony_ci        /* Hm, maybe we've got something long.  Let's try reading
51837db96d56Sopenharmony_ci         * it as a Python int object. */
51847db96d56Sopenharmony_ci        errno = 0;
51857db96d56Sopenharmony_ci        /* XXX: Same thing about the base here. */
51867db96d56Sopenharmony_ci        value = PyLong_FromString(s, NULL, 0);
51877db96d56Sopenharmony_ci        if (value == NULL) {
51887db96d56Sopenharmony_ci            PyErr_SetString(PyExc_ValueError,
51897db96d56Sopenharmony_ci                            "could not convert string to int");
51907db96d56Sopenharmony_ci            return -1;
51917db96d56Sopenharmony_ci        }
51927db96d56Sopenharmony_ci    }
51937db96d56Sopenharmony_ci    else {
51947db96d56Sopenharmony_ci        if (len == 3 && (x == 0 || x == 1)) {
51957db96d56Sopenharmony_ci            if ((value = PyBool_FromLong(x)) == NULL)
51967db96d56Sopenharmony_ci                return -1;
51977db96d56Sopenharmony_ci        }
51987db96d56Sopenharmony_ci        else {
51997db96d56Sopenharmony_ci            if ((value = PyLong_FromLong(x)) == NULL)
52007db96d56Sopenharmony_ci                return -1;
52017db96d56Sopenharmony_ci        }
52027db96d56Sopenharmony_ci    }
52037db96d56Sopenharmony_ci
52047db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, value, -1);
52057db96d56Sopenharmony_ci    return 0;
52067db96d56Sopenharmony_ci}
52077db96d56Sopenharmony_ci
52087db96d56Sopenharmony_cistatic int
52097db96d56Sopenharmony_ciload_bool(UnpicklerObject *self, PyObject *boolean)
52107db96d56Sopenharmony_ci{
52117db96d56Sopenharmony_ci    assert(boolean == Py_True || boolean == Py_False);
52127db96d56Sopenharmony_ci    PDATA_APPEND(self->stack, boolean, -1);
52137db96d56Sopenharmony_ci    return 0;
52147db96d56Sopenharmony_ci}
52157db96d56Sopenharmony_ci
52167db96d56Sopenharmony_ci/* s contains x bytes of an unsigned little-endian integer.  Return its value
52177db96d56Sopenharmony_ci * as a C Py_ssize_t, or -1 if it's higher than PY_SSIZE_T_MAX.
52187db96d56Sopenharmony_ci */
52197db96d56Sopenharmony_cistatic Py_ssize_t
52207db96d56Sopenharmony_cicalc_binsize(char *bytes, int nbytes)
52217db96d56Sopenharmony_ci{
52227db96d56Sopenharmony_ci    unsigned char *s = (unsigned char *)bytes;
52237db96d56Sopenharmony_ci    int i;
52247db96d56Sopenharmony_ci    size_t x = 0;
52257db96d56Sopenharmony_ci
52267db96d56Sopenharmony_ci    if (nbytes > (int)sizeof(size_t)) {
52277db96d56Sopenharmony_ci        /* Check for integer overflow.  BINBYTES8 and BINUNICODE8 opcodes
52287db96d56Sopenharmony_ci         * have 64-bit size that can't be represented on 32-bit platform.
52297db96d56Sopenharmony_ci         */
52307db96d56Sopenharmony_ci        for (i = (int)sizeof(size_t); i < nbytes; i++) {
52317db96d56Sopenharmony_ci            if (s[i])
52327db96d56Sopenharmony_ci                return -1;
52337db96d56Sopenharmony_ci        }
52347db96d56Sopenharmony_ci        nbytes = (int)sizeof(size_t);
52357db96d56Sopenharmony_ci    }
52367db96d56Sopenharmony_ci    for (i = 0; i < nbytes; i++) {
52377db96d56Sopenharmony_ci        x |= (size_t) s[i] << (8 * i);
52387db96d56Sopenharmony_ci    }
52397db96d56Sopenharmony_ci
52407db96d56Sopenharmony_ci    if (x > PY_SSIZE_T_MAX)
52417db96d56Sopenharmony_ci        return -1;
52427db96d56Sopenharmony_ci    else
52437db96d56Sopenharmony_ci        return (Py_ssize_t) x;
52447db96d56Sopenharmony_ci}
52457db96d56Sopenharmony_ci
52467db96d56Sopenharmony_ci/* s contains x bytes of a little-endian integer.  Return its value as a
52477db96d56Sopenharmony_ci * C int.  Obscure:  when x is 1 or 2, this is an unsigned little-endian
52487db96d56Sopenharmony_ci * int, but when x is 4 it's a signed one.  This is a historical source
52497db96d56Sopenharmony_ci * of x-platform bugs.
52507db96d56Sopenharmony_ci */
52517db96d56Sopenharmony_cistatic long
52527db96d56Sopenharmony_cicalc_binint(char *bytes, int nbytes)
52537db96d56Sopenharmony_ci{
52547db96d56Sopenharmony_ci    unsigned char *s = (unsigned char *)bytes;
52557db96d56Sopenharmony_ci    Py_ssize_t i;
52567db96d56Sopenharmony_ci    long x = 0;
52577db96d56Sopenharmony_ci
52587db96d56Sopenharmony_ci    for (i = 0; i < nbytes; i++) {
52597db96d56Sopenharmony_ci        x |= (long)s[i] << (8 * i);
52607db96d56Sopenharmony_ci    }
52617db96d56Sopenharmony_ci
52627db96d56Sopenharmony_ci    /* Unlike BININT1 and BININT2, BININT (more accurately BININT4)
52637db96d56Sopenharmony_ci     * is signed, so on a box with longs bigger than 4 bytes we need
52647db96d56Sopenharmony_ci     * to extend a BININT's sign bit to the full width.
52657db96d56Sopenharmony_ci     */
52667db96d56Sopenharmony_ci    if (SIZEOF_LONG > 4 && nbytes == 4) {
52677db96d56Sopenharmony_ci        x |= -(x & (1L << 31));
52687db96d56Sopenharmony_ci    }
52697db96d56Sopenharmony_ci
52707db96d56Sopenharmony_ci    return x;
52717db96d56Sopenharmony_ci}
52727db96d56Sopenharmony_ci
52737db96d56Sopenharmony_cistatic int
52747db96d56Sopenharmony_ciload_binintx(UnpicklerObject *self, char *s, int size)
52757db96d56Sopenharmony_ci{
52767db96d56Sopenharmony_ci    PyObject *value;
52777db96d56Sopenharmony_ci    long x;
52787db96d56Sopenharmony_ci
52797db96d56Sopenharmony_ci    x = calc_binint(s, size);
52807db96d56Sopenharmony_ci
52817db96d56Sopenharmony_ci    if ((value = PyLong_FromLong(x)) == NULL)
52827db96d56Sopenharmony_ci        return -1;
52837db96d56Sopenharmony_ci
52847db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, value, -1);
52857db96d56Sopenharmony_ci    return 0;
52867db96d56Sopenharmony_ci}
52877db96d56Sopenharmony_ci
52887db96d56Sopenharmony_cistatic int
52897db96d56Sopenharmony_ciload_binint(UnpicklerObject *self)
52907db96d56Sopenharmony_ci{
52917db96d56Sopenharmony_ci    char *s;
52927db96d56Sopenharmony_ci
52937db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 4) < 0)
52947db96d56Sopenharmony_ci        return -1;
52957db96d56Sopenharmony_ci
52967db96d56Sopenharmony_ci    return load_binintx(self, s, 4);
52977db96d56Sopenharmony_ci}
52987db96d56Sopenharmony_ci
52997db96d56Sopenharmony_cistatic int
53007db96d56Sopenharmony_ciload_binint1(UnpicklerObject *self)
53017db96d56Sopenharmony_ci{
53027db96d56Sopenharmony_ci    char *s;
53037db96d56Sopenharmony_ci
53047db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 1) < 0)
53057db96d56Sopenharmony_ci        return -1;
53067db96d56Sopenharmony_ci
53077db96d56Sopenharmony_ci    return load_binintx(self, s, 1);
53087db96d56Sopenharmony_ci}
53097db96d56Sopenharmony_ci
53107db96d56Sopenharmony_cistatic int
53117db96d56Sopenharmony_ciload_binint2(UnpicklerObject *self)
53127db96d56Sopenharmony_ci{
53137db96d56Sopenharmony_ci    char *s;
53147db96d56Sopenharmony_ci
53157db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 2) < 0)
53167db96d56Sopenharmony_ci        return -1;
53177db96d56Sopenharmony_ci
53187db96d56Sopenharmony_ci    return load_binintx(self, s, 2);
53197db96d56Sopenharmony_ci}
53207db96d56Sopenharmony_ci
53217db96d56Sopenharmony_cistatic int
53227db96d56Sopenharmony_ciload_long(UnpicklerObject *self)
53237db96d56Sopenharmony_ci{
53247db96d56Sopenharmony_ci    PyObject *value;
53257db96d56Sopenharmony_ci    char *s = NULL;
53267db96d56Sopenharmony_ci    Py_ssize_t len;
53277db96d56Sopenharmony_ci
53287db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) < 0)
53297db96d56Sopenharmony_ci        return -1;
53307db96d56Sopenharmony_ci    if (len < 2)
53317db96d56Sopenharmony_ci        return bad_readline();
53327db96d56Sopenharmony_ci
53337db96d56Sopenharmony_ci    /* s[len-2] will usually be 'L' (and s[len-1] is '\n'); we need to remove
53347db96d56Sopenharmony_ci       the 'L' before calling PyLong_FromString.  In order to maintain
53357db96d56Sopenharmony_ci       compatibility with Python 3.0.0, we don't actually *require*
53367db96d56Sopenharmony_ci       the 'L' to be present. */
53377db96d56Sopenharmony_ci    if (s[len-2] == 'L')
53387db96d56Sopenharmony_ci        s[len-2] = '\0';
53397db96d56Sopenharmony_ci    /* XXX: Should the base argument explicitly set to 10? */
53407db96d56Sopenharmony_ci    value = PyLong_FromString(s, NULL, 0);
53417db96d56Sopenharmony_ci    if (value == NULL)
53427db96d56Sopenharmony_ci        return -1;
53437db96d56Sopenharmony_ci
53447db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, value, -1);
53457db96d56Sopenharmony_ci    return 0;
53467db96d56Sopenharmony_ci}
53477db96d56Sopenharmony_ci
53487db96d56Sopenharmony_ci/* 'size' bytes contain the # of bytes of little-endian 256's-complement
53497db96d56Sopenharmony_ci * data following.
53507db96d56Sopenharmony_ci */
53517db96d56Sopenharmony_cistatic int
53527db96d56Sopenharmony_ciload_counted_long(UnpicklerObject *self, int size)
53537db96d56Sopenharmony_ci{
53547db96d56Sopenharmony_ci    PyObject *value;
53557db96d56Sopenharmony_ci    char *nbytes;
53567db96d56Sopenharmony_ci    char *pdata;
53577db96d56Sopenharmony_ci
53587db96d56Sopenharmony_ci    assert(size == 1 || size == 4);
53597db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &nbytes, size) < 0)
53607db96d56Sopenharmony_ci        return -1;
53617db96d56Sopenharmony_ci
53627db96d56Sopenharmony_ci    size = calc_binint(nbytes, size);
53637db96d56Sopenharmony_ci    if (size < 0) {
53647db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
53657db96d56Sopenharmony_ci        /* Corrupt or hostile pickle -- we never write one like this */
53667db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError,
53677db96d56Sopenharmony_ci                        "LONG pickle has negative byte count");
53687db96d56Sopenharmony_ci        return -1;
53697db96d56Sopenharmony_ci    }
53707db96d56Sopenharmony_ci
53717db96d56Sopenharmony_ci    if (size == 0)
53727db96d56Sopenharmony_ci        value = PyLong_FromLong(0L);
53737db96d56Sopenharmony_ci    else {
53747db96d56Sopenharmony_ci        /* Read the raw little-endian bytes and convert. */
53757db96d56Sopenharmony_ci        if (_Unpickler_Read(self, &pdata, size) < 0)
53767db96d56Sopenharmony_ci            return -1;
53777db96d56Sopenharmony_ci        value = _PyLong_FromByteArray((unsigned char *)pdata, (size_t)size,
53787db96d56Sopenharmony_ci                                      1 /* little endian */ , 1 /* signed */ );
53797db96d56Sopenharmony_ci    }
53807db96d56Sopenharmony_ci    if (value == NULL)
53817db96d56Sopenharmony_ci        return -1;
53827db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, value, -1);
53837db96d56Sopenharmony_ci    return 0;
53847db96d56Sopenharmony_ci}
53857db96d56Sopenharmony_ci
53867db96d56Sopenharmony_cistatic int
53877db96d56Sopenharmony_ciload_float(UnpicklerObject *self)
53887db96d56Sopenharmony_ci{
53897db96d56Sopenharmony_ci    PyObject *value;
53907db96d56Sopenharmony_ci    char *endptr, *s;
53917db96d56Sopenharmony_ci    Py_ssize_t len;
53927db96d56Sopenharmony_ci    double d;
53937db96d56Sopenharmony_ci
53947db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) < 0)
53957db96d56Sopenharmony_ci        return -1;
53967db96d56Sopenharmony_ci    if (len < 2)
53977db96d56Sopenharmony_ci        return bad_readline();
53987db96d56Sopenharmony_ci
53997db96d56Sopenharmony_ci    errno = 0;
54007db96d56Sopenharmony_ci    d = PyOS_string_to_double(s, &endptr, PyExc_OverflowError);
54017db96d56Sopenharmony_ci    if (d == -1.0 && PyErr_Occurred())
54027db96d56Sopenharmony_ci        return -1;
54037db96d56Sopenharmony_ci    if ((endptr[0] != '\n') && (endptr[0] != '\0')) {
54047db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "could not convert string to float");
54057db96d56Sopenharmony_ci        return -1;
54067db96d56Sopenharmony_ci    }
54077db96d56Sopenharmony_ci    value = PyFloat_FromDouble(d);
54087db96d56Sopenharmony_ci    if (value == NULL)
54097db96d56Sopenharmony_ci        return -1;
54107db96d56Sopenharmony_ci
54117db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, value, -1);
54127db96d56Sopenharmony_ci    return 0;
54137db96d56Sopenharmony_ci}
54147db96d56Sopenharmony_ci
54157db96d56Sopenharmony_cistatic int
54167db96d56Sopenharmony_ciload_binfloat(UnpicklerObject *self)
54177db96d56Sopenharmony_ci{
54187db96d56Sopenharmony_ci    PyObject *value;
54197db96d56Sopenharmony_ci    double x;
54207db96d56Sopenharmony_ci    char *s;
54217db96d56Sopenharmony_ci
54227db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 8) < 0)
54237db96d56Sopenharmony_ci        return -1;
54247db96d56Sopenharmony_ci
54257db96d56Sopenharmony_ci    x = PyFloat_Unpack8(s, 0);
54267db96d56Sopenharmony_ci    if (x == -1.0 && PyErr_Occurred())
54277db96d56Sopenharmony_ci        return -1;
54287db96d56Sopenharmony_ci
54297db96d56Sopenharmony_ci    if ((value = PyFloat_FromDouble(x)) == NULL)
54307db96d56Sopenharmony_ci        return -1;
54317db96d56Sopenharmony_ci
54327db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, value, -1);
54337db96d56Sopenharmony_ci    return 0;
54347db96d56Sopenharmony_ci}
54357db96d56Sopenharmony_ci
54367db96d56Sopenharmony_cistatic int
54377db96d56Sopenharmony_ciload_string(UnpicklerObject *self)
54387db96d56Sopenharmony_ci{
54397db96d56Sopenharmony_ci    PyObject *bytes;
54407db96d56Sopenharmony_ci    PyObject *obj;
54417db96d56Sopenharmony_ci    Py_ssize_t len;
54427db96d56Sopenharmony_ci    char *s, *p;
54437db96d56Sopenharmony_ci
54447db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) < 0)
54457db96d56Sopenharmony_ci        return -1;
54467db96d56Sopenharmony_ci    /* Strip the newline */
54477db96d56Sopenharmony_ci    len--;
54487db96d56Sopenharmony_ci    /* Strip outermost quotes */
54497db96d56Sopenharmony_ci    if (len >= 2 && s[0] == s[len - 1] && (s[0] == '\'' || s[0] == '"')) {
54507db96d56Sopenharmony_ci        p = s + 1;
54517db96d56Sopenharmony_ci        len -= 2;
54527db96d56Sopenharmony_ci    }
54537db96d56Sopenharmony_ci    else {
54547db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
54557db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError,
54567db96d56Sopenharmony_ci                        "the STRING opcode argument must be quoted");
54577db96d56Sopenharmony_ci        return -1;
54587db96d56Sopenharmony_ci    }
54597db96d56Sopenharmony_ci    assert(len >= 0);
54607db96d56Sopenharmony_ci
54617db96d56Sopenharmony_ci    /* Use the PyBytes API to decode the string, since that is what is used
54627db96d56Sopenharmony_ci       to encode, and then coerce the result to Unicode. */
54637db96d56Sopenharmony_ci    bytes = PyBytes_DecodeEscape(p, len, NULL, 0, NULL);
54647db96d56Sopenharmony_ci    if (bytes == NULL)
54657db96d56Sopenharmony_ci        return -1;
54667db96d56Sopenharmony_ci
54677db96d56Sopenharmony_ci    /* Leave the Python 2.x strings as bytes if the *encoding* given to the
54687db96d56Sopenharmony_ci       Unpickler was 'bytes'. Otherwise, convert them to unicode. */
54697db96d56Sopenharmony_ci    if (strcmp(self->encoding, "bytes") == 0) {
54707db96d56Sopenharmony_ci        obj = bytes;
54717db96d56Sopenharmony_ci    }
54727db96d56Sopenharmony_ci    else {
54737db96d56Sopenharmony_ci        obj = PyUnicode_FromEncodedObject(bytes, self->encoding, self->errors);
54747db96d56Sopenharmony_ci        Py_DECREF(bytes);
54757db96d56Sopenharmony_ci        if (obj == NULL) {
54767db96d56Sopenharmony_ci            return -1;
54777db96d56Sopenharmony_ci        }
54787db96d56Sopenharmony_ci    }
54797db96d56Sopenharmony_ci
54807db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, obj, -1);
54817db96d56Sopenharmony_ci    return 0;
54827db96d56Sopenharmony_ci}
54837db96d56Sopenharmony_ci
54847db96d56Sopenharmony_cistatic int
54857db96d56Sopenharmony_ciload_counted_binstring(UnpicklerObject *self, int nbytes)
54867db96d56Sopenharmony_ci{
54877db96d56Sopenharmony_ci    PyObject *obj;
54887db96d56Sopenharmony_ci    Py_ssize_t size;
54897db96d56Sopenharmony_ci    char *s;
54907db96d56Sopenharmony_ci
54917db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, nbytes) < 0)
54927db96d56Sopenharmony_ci        return -1;
54937db96d56Sopenharmony_ci
54947db96d56Sopenharmony_ci    size = calc_binsize(s, nbytes);
54957db96d56Sopenharmony_ci    if (size < 0) {
54967db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
54977db96d56Sopenharmony_ci        PyErr_Format(st->UnpicklingError,
54987db96d56Sopenharmony_ci                     "BINSTRING exceeds system's maximum size of %zd bytes",
54997db96d56Sopenharmony_ci                     PY_SSIZE_T_MAX);
55007db96d56Sopenharmony_ci        return -1;
55017db96d56Sopenharmony_ci    }
55027db96d56Sopenharmony_ci
55037db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, size) < 0)
55047db96d56Sopenharmony_ci        return -1;
55057db96d56Sopenharmony_ci
55067db96d56Sopenharmony_ci    /* Convert Python 2.x strings to bytes if the *encoding* given to the
55077db96d56Sopenharmony_ci       Unpickler was 'bytes'. Otherwise, convert them to unicode. */
55087db96d56Sopenharmony_ci    if (strcmp(self->encoding, "bytes") == 0) {
55097db96d56Sopenharmony_ci        obj = PyBytes_FromStringAndSize(s, size);
55107db96d56Sopenharmony_ci    }
55117db96d56Sopenharmony_ci    else {
55127db96d56Sopenharmony_ci        obj = PyUnicode_Decode(s, size, self->encoding, self->errors);
55137db96d56Sopenharmony_ci    }
55147db96d56Sopenharmony_ci    if (obj == NULL) {
55157db96d56Sopenharmony_ci        return -1;
55167db96d56Sopenharmony_ci    }
55177db96d56Sopenharmony_ci
55187db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, obj, -1);
55197db96d56Sopenharmony_ci    return 0;
55207db96d56Sopenharmony_ci}
55217db96d56Sopenharmony_ci
55227db96d56Sopenharmony_cistatic int
55237db96d56Sopenharmony_ciload_counted_binbytes(UnpicklerObject *self, int nbytes)
55247db96d56Sopenharmony_ci{
55257db96d56Sopenharmony_ci    PyObject *bytes;
55267db96d56Sopenharmony_ci    Py_ssize_t size;
55277db96d56Sopenharmony_ci    char *s;
55287db96d56Sopenharmony_ci
55297db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, nbytes) < 0)
55307db96d56Sopenharmony_ci        return -1;
55317db96d56Sopenharmony_ci
55327db96d56Sopenharmony_ci    size = calc_binsize(s, nbytes);
55337db96d56Sopenharmony_ci    if (size < 0) {
55347db96d56Sopenharmony_ci        PyErr_Format(PyExc_OverflowError,
55357db96d56Sopenharmony_ci                     "BINBYTES exceeds system's maximum size of %zd bytes",
55367db96d56Sopenharmony_ci                     PY_SSIZE_T_MAX);
55377db96d56Sopenharmony_ci        return -1;
55387db96d56Sopenharmony_ci    }
55397db96d56Sopenharmony_ci
55407db96d56Sopenharmony_ci    bytes = PyBytes_FromStringAndSize(NULL, size);
55417db96d56Sopenharmony_ci    if (bytes == NULL)
55427db96d56Sopenharmony_ci        return -1;
55437db96d56Sopenharmony_ci    if (_Unpickler_ReadInto(self, PyBytes_AS_STRING(bytes), size) < 0) {
55447db96d56Sopenharmony_ci        Py_DECREF(bytes);
55457db96d56Sopenharmony_ci        return -1;
55467db96d56Sopenharmony_ci    }
55477db96d56Sopenharmony_ci
55487db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, bytes, -1);
55497db96d56Sopenharmony_ci    return 0;
55507db96d56Sopenharmony_ci}
55517db96d56Sopenharmony_ci
55527db96d56Sopenharmony_cistatic int
55537db96d56Sopenharmony_ciload_counted_bytearray(UnpicklerObject *self)
55547db96d56Sopenharmony_ci{
55557db96d56Sopenharmony_ci    PyObject *bytearray;
55567db96d56Sopenharmony_ci    Py_ssize_t size;
55577db96d56Sopenharmony_ci    char *s;
55587db96d56Sopenharmony_ci
55597db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 8) < 0) {
55607db96d56Sopenharmony_ci        return -1;
55617db96d56Sopenharmony_ci    }
55627db96d56Sopenharmony_ci
55637db96d56Sopenharmony_ci    size = calc_binsize(s, 8);
55647db96d56Sopenharmony_ci    if (size < 0) {
55657db96d56Sopenharmony_ci        PyErr_Format(PyExc_OverflowError,
55667db96d56Sopenharmony_ci                     "BYTEARRAY8 exceeds system's maximum size of %zd bytes",
55677db96d56Sopenharmony_ci                     PY_SSIZE_T_MAX);
55687db96d56Sopenharmony_ci        return -1;
55697db96d56Sopenharmony_ci    }
55707db96d56Sopenharmony_ci
55717db96d56Sopenharmony_ci    bytearray = PyByteArray_FromStringAndSize(NULL, size);
55727db96d56Sopenharmony_ci    if (bytearray == NULL) {
55737db96d56Sopenharmony_ci        return -1;
55747db96d56Sopenharmony_ci    }
55757db96d56Sopenharmony_ci    if (_Unpickler_ReadInto(self, PyByteArray_AS_STRING(bytearray), size) < 0) {
55767db96d56Sopenharmony_ci        Py_DECREF(bytearray);
55777db96d56Sopenharmony_ci        return -1;
55787db96d56Sopenharmony_ci    }
55797db96d56Sopenharmony_ci
55807db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, bytearray, -1);
55817db96d56Sopenharmony_ci    return 0;
55827db96d56Sopenharmony_ci}
55837db96d56Sopenharmony_ci
55847db96d56Sopenharmony_cistatic int
55857db96d56Sopenharmony_ciload_next_buffer(UnpicklerObject *self)
55867db96d56Sopenharmony_ci{
55877db96d56Sopenharmony_ci    if (self->buffers == NULL) {
55887db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
55897db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError,
55907db96d56Sopenharmony_ci                        "pickle stream refers to out-of-band data "
55917db96d56Sopenharmony_ci                        "but no *buffers* argument was given");
55927db96d56Sopenharmony_ci        return -1;
55937db96d56Sopenharmony_ci    }
55947db96d56Sopenharmony_ci    PyObject *buf = PyIter_Next(self->buffers);
55957db96d56Sopenharmony_ci    if (buf == NULL) {
55967db96d56Sopenharmony_ci        if (!PyErr_Occurred()) {
55977db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
55987db96d56Sopenharmony_ci            PyErr_SetString(st->UnpicklingError,
55997db96d56Sopenharmony_ci                            "not enough out-of-band buffers");
56007db96d56Sopenharmony_ci        }
56017db96d56Sopenharmony_ci        return -1;
56027db96d56Sopenharmony_ci    }
56037db96d56Sopenharmony_ci
56047db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, buf, -1);
56057db96d56Sopenharmony_ci    return 0;
56067db96d56Sopenharmony_ci}
56077db96d56Sopenharmony_ci
56087db96d56Sopenharmony_cistatic int
56097db96d56Sopenharmony_ciload_readonly_buffer(UnpicklerObject *self)
56107db96d56Sopenharmony_ci{
56117db96d56Sopenharmony_ci    Py_ssize_t len = Py_SIZE(self->stack);
56127db96d56Sopenharmony_ci    if (len <= self->stack->fence) {
56137db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
56147db96d56Sopenharmony_ci    }
56157db96d56Sopenharmony_ci
56167db96d56Sopenharmony_ci    PyObject *obj = self->stack->data[len - 1];
56177db96d56Sopenharmony_ci    PyObject *view = PyMemoryView_FromObject(obj);
56187db96d56Sopenharmony_ci    if (view == NULL) {
56197db96d56Sopenharmony_ci        return -1;
56207db96d56Sopenharmony_ci    }
56217db96d56Sopenharmony_ci    if (!PyMemoryView_GET_BUFFER(view)->readonly) {
56227db96d56Sopenharmony_ci        /* Original object is writable */
56237db96d56Sopenharmony_ci        PyMemoryView_GET_BUFFER(view)->readonly = 1;
56247db96d56Sopenharmony_ci        self->stack->data[len - 1] = view;
56257db96d56Sopenharmony_ci        Py_DECREF(obj);
56267db96d56Sopenharmony_ci    }
56277db96d56Sopenharmony_ci    else {
56287db96d56Sopenharmony_ci        /* Original object is read-only, no need to replace it */
56297db96d56Sopenharmony_ci        Py_DECREF(view);
56307db96d56Sopenharmony_ci    }
56317db96d56Sopenharmony_ci    return 0;
56327db96d56Sopenharmony_ci}
56337db96d56Sopenharmony_ci
56347db96d56Sopenharmony_cistatic int
56357db96d56Sopenharmony_ciload_unicode(UnpicklerObject *self)
56367db96d56Sopenharmony_ci{
56377db96d56Sopenharmony_ci    PyObject *str;
56387db96d56Sopenharmony_ci    Py_ssize_t len;
56397db96d56Sopenharmony_ci    char *s = NULL;
56407db96d56Sopenharmony_ci
56417db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) < 0)
56427db96d56Sopenharmony_ci        return -1;
56437db96d56Sopenharmony_ci    if (len < 1)
56447db96d56Sopenharmony_ci        return bad_readline();
56457db96d56Sopenharmony_ci
56467db96d56Sopenharmony_ci    str = PyUnicode_DecodeRawUnicodeEscape(s, len - 1, NULL);
56477db96d56Sopenharmony_ci    if (str == NULL)
56487db96d56Sopenharmony_ci        return -1;
56497db96d56Sopenharmony_ci
56507db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, str, -1);
56517db96d56Sopenharmony_ci    return 0;
56527db96d56Sopenharmony_ci}
56537db96d56Sopenharmony_ci
56547db96d56Sopenharmony_cistatic int
56557db96d56Sopenharmony_ciload_counted_binunicode(UnpicklerObject *self, int nbytes)
56567db96d56Sopenharmony_ci{
56577db96d56Sopenharmony_ci    PyObject *str;
56587db96d56Sopenharmony_ci    Py_ssize_t size;
56597db96d56Sopenharmony_ci    char *s;
56607db96d56Sopenharmony_ci
56617db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, nbytes) < 0)
56627db96d56Sopenharmony_ci        return -1;
56637db96d56Sopenharmony_ci
56647db96d56Sopenharmony_ci    size = calc_binsize(s, nbytes);
56657db96d56Sopenharmony_ci    if (size < 0) {
56667db96d56Sopenharmony_ci        PyErr_Format(PyExc_OverflowError,
56677db96d56Sopenharmony_ci                     "BINUNICODE exceeds system's maximum size of %zd bytes",
56687db96d56Sopenharmony_ci                     PY_SSIZE_T_MAX);
56697db96d56Sopenharmony_ci        return -1;
56707db96d56Sopenharmony_ci    }
56717db96d56Sopenharmony_ci
56727db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, size) < 0)
56737db96d56Sopenharmony_ci        return -1;
56747db96d56Sopenharmony_ci
56757db96d56Sopenharmony_ci    str = PyUnicode_DecodeUTF8(s, size, "surrogatepass");
56767db96d56Sopenharmony_ci    if (str == NULL)
56777db96d56Sopenharmony_ci        return -1;
56787db96d56Sopenharmony_ci
56797db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, str, -1);
56807db96d56Sopenharmony_ci    return 0;
56817db96d56Sopenharmony_ci}
56827db96d56Sopenharmony_ci
56837db96d56Sopenharmony_cistatic int
56847db96d56Sopenharmony_ciload_counted_tuple(UnpicklerObject *self, Py_ssize_t len)
56857db96d56Sopenharmony_ci{
56867db96d56Sopenharmony_ci    PyObject *tuple;
56877db96d56Sopenharmony_ci
56887db96d56Sopenharmony_ci    if (Py_SIZE(self->stack) < len)
56897db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
56907db96d56Sopenharmony_ci
56917db96d56Sopenharmony_ci    tuple = Pdata_poptuple(self->stack, Py_SIZE(self->stack) - len);
56927db96d56Sopenharmony_ci    if (tuple == NULL)
56937db96d56Sopenharmony_ci        return -1;
56947db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, tuple, -1);
56957db96d56Sopenharmony_ci    return 0;
56967db96d56Sopenharmony_ci}
56977db96d56Sopenharmony_ci
56987db96d56Sopenharmony_cistatic int
56997db96d56Sopenharmony_ciload_tuple(UnpicklerObject *self)
57007db96d56Sopenharmony_ci{
57017db96d56Sopenharmony_ci    Py_ssize_t i;
57027db96d56Sopenharmony_ci
57037db96d56Sopenharmony_ci    if ((i = marker(self)) < 0)
57047db96d56Sopenharmony_ci        return -1;
57057db96d56Sopenharmony_ci
57067db96d56Sopenharmony_ci    return load_counted_tuple(self, Py_SIZE(self->stack) - i);
57077db96d56Sopenharmony_ci}
57087db96d56Sopenharmony_ci
57097db96d56Sopenharmony_cistatic int
57107db96d56Sopenharmony_ciload_empty_list(UnpicklerObject *self)
57117db96d56Sopenharmony_ci{
57127db96d56Sopenharmony_ci    PyObject *list;
57137db96d56Sopenharmony_ci
57147db96d56Sopenharmony_ci    if ((list = PyList_New(0)) == NULL)
57157db96d56Sopenharmony_ci        return -1;
57167db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, list, -1);
57177db96d56Sopenharmony_ci    return 0;
57187db96d56Sopenharmony_ci}
57197db96d56Sopenharmony_ci
57207db96d56Sopenharmony_cistatic int
57217db96d56Sopenharmony_ciload_empty_dict(UnpicklerObject *self)
57227db96d56Sopenharmony_ci{
57237db96d56Sopenharmony_ci    PyObject *dict;
57247db96d56Sopenharmony_ci
57257db96d56Sopenharmony_ci    if ((dict = PyDict_New()) == NULL)
57267db96d56Sopenharmony_ci        return -1;
57277db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, dict, -1);
57287db96d56Sopenharmony_ci    return 0;
57297db96d56Sopenharmony_ci}
57307db96d56Sopenharmony_ci
57317db96d56Sopenharmony_cistatic int
57327db96d56Sopenharmony_ciload_empty_set(UnpicklerObject *self)
57337db96d56Sopenharmony_ci{
57347db96d56Sopenharmony_ci    PyObject *set;
57357db96d56Sopenharmony_ci
57367db96d56Sopenharmony_ci    if ((set = PySet_New(NULL)) == NULL)
57377db96d56Sopenharmony_ci        return -1;
57387db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, set, -1);
57397db96d56Sopenharmony_ci    return 0;
57407db96d56Sopenharmony_ci}
57417db96d56Sopenharmony_ci
57427db96d56Sopenharmony_cistatic int
57437db96d56Sopenharmony_ciload_list(UnpicklerObject *self)
57447db96d56Sopenharmony_ci{
57457db96d56Sopenharmony_ci    PyObject *list;
57467db96d56Sopenharmony_ci    Py_ssize_t i;
57477db96d56Sopenharmony_ci
57487db96d56Sopenharmony_ci    if ((i = marker(self)) < 0)
57497db96d56Sopenharmony_ci        return -1;
57507db96d56Sopenharmony_ci
57517db96d56Sopenharmony_ci    list = Pdata_poplist(self->stack, i);
57527db96d56Sopenharmony_ci    if (list == NULL)
57537db96d56Sopenharmony_ci        return -1;
57547db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, list, -1);
57557db96d56Sopenharmony_ci    return 0;
57567db96d56Sopenharmony_ci}
57577db96d56Sopenharmony_ci
57587db96d56Sopenharmony_cistatic int
57597db96d56Sopenharmony_ciload_dict(UnpicklerObject *self)
57607db96d56Sopenharmony_ci{
57617db96d56Sopenharmony_ci    PyObject *dict, *key, *value;
57627db96d56Sopenharmony_ci    Py_ssize_t i, j, k;
57637db96d56Sopenharmony_ci
57647db96d56Sopenharmony_ci    if ((i = marker(self)) < 0)
57657db96d56Sopenharmony_ci        return -1;
57667db96d56Sopenharmony_ci    j = Py_SIZE(self->stack);
57677db96d56Sopenharmony_ci
57687db96d56Sopenharmony_ci    if ((dict = PyDict_New()) == NULL)
57697db96d56Sopenharmony_ci        return -1;
57707db96d56Sopenharmony_ci
57717db96d56Sopenharmony_ci    if ((j - i) % 2 != 0) {
57727db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
57737db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError, "odd number of items for DICT");
57747db96d56Sopenharmony_ci        Py_DECREF(dict);
57757db96d56Sopenharmony_ci        return -1;
57767db96d56Sopenharmony_ci    }
57777db96d56Sopenharmony_ci
57787db96d56Sopenharmony_ci    for (k = i + 1; k < j; k += 2) {
57797db96d56Sopenharmony_ci        key = self->stack->data[k - 1];
57807db96d56Sopenharmony_ci        value = self->stack->data[k];
57817db96d56Sopenharmony_ci        if (PyDict_SetItem(dict, key, value) < 0) {
57827db96d56Sopenharmony_ci            Py_DECREF(dict);
57837db96d56Sopenharmony_ci            return -1;
57847db96d56Sopenharmony_ci        }
57857db96d56Sopenharmony_ci    }
57867db96d56Sopenharmony_ci    Pdata_clear(self->stack, i);
57877db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, dict, -1);
57887db96d56Sopenharmony_ci    return 0;
57897db96d56Sopenharmony_ci}
57907db96d56Sopenharmony_ci
57917db96d56Sopenharmony_cistatic int
57927db96d56Sopenharmony_ciload_frozenset(UnpicklerObject *self)
57937db96d56Sopenharmony_ci{
57947db96d56Sopenharmony_ci    PyObject *items;
57957db96d56Sopenharmony_ci    PyObject *frozenset;
57967db96d56Sopenharmony_ci    Py_ssize_t i;
57977db96d56Sopenharmony_ci
57987db96d56Sopenharmony_ci    if ((i = marker(self)) < 0)
57997db96d56Sopenharmony_ci        return -1;
58007db96d56Sopenharmony_ci
58017db96d56Sopenharmony_ci    items = Pdata_poptuple(self->stack, i);
58027db96d56Sopenharmony_ci    if (items == NULL)
58037db96d56Sopenharmony_ci        return -1;
58047db96d56Sopenharmony_ci
58057db96d56Sopenharmony_ci    frozenset = PyFrozenSet_New(items);
58067db96d56Sopenharmony_ci    Py_DECREF(items);
58077db96d56Sopenharmony_ci    if (frozenset == NULL)
58087db96d56Sopenharmony_ci        return -1;
58097db96d56Sopenharmony_ci
58107db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, frozenset, -1);
58117db96d56Sopenharmony_ci    return 0;
58127db96d56Sopenharmony_ci}
58137db96d56Sopenharmony_ci
58147db96d56Sopenharmony_cistatic PyObject *
58157db96d56Sopenharmony_ciinstantiate(PyObject *cls, PyObject *args)
58167db96d56Sopenharmony_ci{
58177db96d56Sopenharmony_ci    /* Caller must assure args are a tuple.  Normally, args come from
58187db96d56Sopenharmony_ci       Pdata_poptuple which packs objects from the top of the stack
58197db96d56Sopenharmony_ci       into a newly created tuple. */
58207db96d56Sopenharmony_ci    assert(PyTuple_Check(args));
58217db96d56Sopenharmony_ci    if (!PyTuple_GET_SIZE(args) && PyType_Check(cls)) {
58227db96d56Sopenharmony_ci        PyObject *func;
58237db96d56Sopenharmony_ci        if (_PyObject_LookupAttr(cls, &_Py_ID(__getinitargs__), &func) < 0) {
58247db96d56Sopenharmony_ci            return NULL;
58257db96d56Sopenharmony_ci        }
58267db96d56Sopenharmony_ci        if (func == NULL) {
58277db96d56Sopenharmony_ci            return PyObject_CallMethodOneArg(cls, &_Py_ID(__new__), cls);
58287db96d56Sopenharmony_ci        }
58297db96d56Sopenharmony_ci        Py_DECREF(func);
58307db96d56Sopenharmony_ci    }
58317db96d56Sopenharmony_ci    return PyObject_CallObject(cls, args);
58327db96d56Sopenharmony_ci}
58337db96d56Sopenharmony_ci
58347db96d56Sopenharmony_cistatic int
58357db96d56Sopenharmony_ciload_obj(UnpicklerObject *self)
58367db96d56Sopenharmony_ci{
58377db96d56Sopenharmony_ci    PyObject *cls, *args, *obj = NULL;
58387db96d56Sopenharmony_ci    Py_ssize_t i;
58397db96d56Sopenharmony_ci
58407db96d56Sopenharmony_ci    if ((i = marker(self)) < 0)
58417db96d56Sopenharmony_ci        return -1;
58427db96d56Sopenharmony_ci
58437db96d56Sopenharmony_ci    if (Py_SIZE(self->stack) - i < 1)
58447db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
58457db96d56Sopenharmony_ci
58467db96d56Sopenharmony_ci    args = Pdata_poptuple(self->stack, i + 1);
58477db96d56Sopenharmony_ci    if (args == NULL)
58487db96d56Sopenharmony_ci        return -1;
58497db96d56Sopenharmony_ci
58507db96d56Sopenharmony_ci    PDATA_POP(self->stack, cls);
58517db96d56Sopenharmony_ci    if (cls) {
58527db96d56Sopenharmony_ci        obj = instantiate(cls, args);
58537db96d56Sopenharmony_ci        Py_DECREF(cls);
58547db96d56Sopenharmony_ci    }
58557db96d56Sopenharmony_ci    Py_DECREF(args);
58567db96d56Sopenharmony_ci    if (obj == NULL)
58577db96d56Sopenharmony_ci        return -1;
58587db96d56Sopenharmony_ci
58597db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, obj, -1);
58607db96d56Sopenharmony_ci    return 0;
58617db96d56Sopenharmony_ci}
58627db96d56Sopenharmony_ci
58637db96d56Sopenharmony_cistatic int
58647db96d56Sopenharmony_ciload_inst(UnpicklerObject *self)
58657db96d56Sopenharmony_ci{
58667db96d56Sopenharmony_ci    PyObject *cls = NULL;
58677db96d56Sopenharmony_ci    PyObject *args = NULL;
58687db96d56Sopenharmony_ci    PyObject *obj = NULL;
58697db96d56Sopenharmony_ci    PyObject *module_name;
58707db96d56Sopenharmony_ci    PyObject *class_name;
58717db96d56Sopenharmony_ci    Py_ssize_t len;
58727db96d56Sopenharmony_ci    Py_ssize_t i;
58737db96d56Sopenharmony_ci    char *s;
58747db96d56Sopenharmony_ci
58757db96d56Sopenharmony_ci    if ((i = marker(self)) < 0)
58767db96d56Sopenharmony_ci        return -1;
58777db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) < 0)
58787db96d56Sopenharmony_ci        return -1;
58797db96d56Sopenharmony_ci    if (len < 2)
58807db96d56Sopenharmony_ci        return bad_readline();
58817db96d56Sopenharmony_ci
58827db96d56Sopenharmony_ci    /* Here it is safe to use PyUnicode_DecodeASCII(), even though non-ASCII
58837db96d56Sopenharmony_ci       identifiers are permitted in Python 3.0, since the INST opcode is only
58847db96d56Sopenharmony_ci       supported by older protocols on Python 2.x. */
58857db96d56Sopenharmony_ci    module_name = PyUnicode_DecodeASCII(s, len - 1, "strict");
58867db96d56Sopenharmony_ci    if (module_name == NULL)
58877db96d56Sopenharmony_ci        return -1;
58887db96d56Sopenharmony_ci
58897db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) >= 0) {
58907db96d56Sopenharmony_ci        if (len < 2) {
58917db96d56Sopenharmony_ci            Py_DECREF(module_name);
58927db96d56Sopenharmony_ci            return bad_readline();
58937db96d56Sopenharmony_ci        }
58947db96d56Sopenharmony_ci        class_name = PyUnicode_DecodeASCII(s, len - 1, "strict");
58957db96d56Sopenharmony_ci        if (class_name != NULL) {
58967db96d56Sopenharmony_ci            cls = find_class(self, module_name, class_name);
58977db96d56Sopenharmony_ci            Py_DECREF(class_name);
58987db96d56Sopenharmony_ci        }
58997db96d56Sopenharmony_ci    }
59007db96d56Sopenharmony_ci    Py_DECREF(module_name);
59017db96d56Sopenharmony_ci
59027db96d56Sopenharmony_ci    if (cls == NULL)
59037db96d56Sopenharmony_ci        return -1;
59047db96d56Sopenharmony_ci
59057db96d56Sopenharmony_ci    if ((args = Pdata_poptuple(self->stack, i)) != NULL) {
59067db96d56Sopenharmony_ci        obj = instantiate(cls, args);
59077db96d56Sopenharmony_ci        Py_DECREF(args);
59087db96d56Sopenharmony_ci    }
59097db96d56Sopenharmony_ci    Py_DECREF(cls);
59107db96d56Sopenharmony_ci
59117db96d56Sopenharmony_ci    if (obj == NULL)
59127db96d56Sopenharmony_ci        return -1;
59137db96d56Sopenharmony_ci
59147db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, obj, -1);
59157db96d56Sopenharmony_ci    return 0;
59167db96d56Sopenharmony_ci}
59177db96d56Sopenharmony_ci
59187db96d56Sopenharmony_cistatic void
59197db96d56Sopenharmony_cinewobj_unpickling_error(const char * msg, int use_kwargs, PyObject *arg)
59207db96d56Sopenharmony_ci{
59217db96d56Sopenharmony_ci    PickleState *st = _Pickle_GetGlobalState();
59227db96d56Sopenharmony_ci    PyErr_Format(st->UnpicklingError, msg,
59237db96d56Sopenharmony_ci                 use_kwargs ? "NEWOBJ_EX" : "NEWOBJ",
59247db96d56Sopenharmony_ci                 Py_TYPE(arg)->tp_name);
59257db96d56Sopenharmony_ci}
59267db96d56Sopenharmony_ci
59277db96d56Sopenharmony_cistatic int
59287db96d56Sopenharmony_ciload_newobj(UnpicklerObject *self, int use_kwargs)
59297db96d56Sopenharmony_ci{
59307db96d56Sopenharmony_ci    PyObject *cls, *args, *kwargs = NULL;
59317db96d56Sopenharmony_ci    PyObject *obj;
59327db96d56Sopenharmony_ci
59337db96d56Sopenharmony_ci    /* Stack is ... cls args [kwargs], and we want to call
59347db96d56Sopenharmony_ci     * cls.__new__(cls, *args, **kwargs).
59357db96d56Sopenharmony_ci     */
59367db96d56Sopenharmony_ci    if (use_kwargs) {
59377db96d56Sopenharmony_ci        PDATA_POP(self->stack, kwargs);
59387db96d56Sopenharmony_ci        if (kwargs == NULL) {
59397db96d56Sopenharmony_ci            return -1;
59407db96d56Sopenharmony_ci        }
59417db96d56Sopenharmony_ci    }
59427db96d56Sopenharmony_ci    PDATA_POP(self->stack, args);
59437db96d56Sopenharmony_ci    if (args == NULL) {
59447db96d56Sopenharmony_ci        Py_XDECREF(kwargs);
59457db96d56Sopenharmony_ci        return -1;
59467db96d56Sopenharmony_ci    }
59477db96d56Sopenharmony_ci    PDATA_POP(self->stack, cls);
59487db96d56Sopenharmony_ci    if (cls == NULL) {
59497db96d56Sopenharmony_ci        Py_XDECREF(kwargs);
59507db96d56Sopenharmony_ci        Py_DECREF(args);
59517db96d56Sopenharmony_ci        return -1;
59527db96d56Sopenharmony_ci    }
59537db96d56Sopenharmony_ci
59547db96d56Sopenharmony_ci    if (!PyType_Check(cls)) {
59557db96d56Sopenharmony_ci        newobj_unpickling_error("%s class argument must be a type, not %.200s",
59567db96d56Sopenharmony_ci                                use_kwargs, cls);
59577db96d56Sopenharmony_ci        goto error;
59587db96d56Sopenharmony_ci    }
59597db96d56Sopenharmony_ci    if (((PyTypeObject *)cls)->tp_new == NULL) {
59607db96d56Sopenharmony_ci        newobj_unpickling_error("%s class argument '%.200s' doesn't have __new__",
59617db96d56Sopenharmony_ci                                use_kwargs, cls);
59627db96d56Sopenharmony_ci        goto error;
59637db96d56Sopenharmony_ci    }
59647db96d56Sopenharmony_ci    if (!PyTuple_Check(args)) {
59657db96d56Sopenharmony_ci        newobj_unpickling_error("%s args argument must be a tuple, not %.200s",
59667db96d56Sopenharmony_ci                                use_kwargs, args);
59677db96d56Sopenharmony_ci        goto error;
59687db96d56Sopenharmony_ci    }
59697db96d56Sopenharmony_ci    if (use_kwargs && !PyDict_Check(kwargs)) {
59707db96d56Sopenharmony_ci        newobj_unpickling_error("%s kwargs argument must be a dict, not %.200s",
59717db96d56Sopenharmony_ci                                use_kwargs, kwargs);
59727db96d56Sopenharmony_ci        goto error;
59737db96d56Sopenharmony_ci    }
59747db96d56Sopenharmony_ci
59757db96d56Sopenharmony_ci    obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
59767db96d56Sopenharmony_ci    if (obj == NULL) {
59777db96d56Sopenharmony_ci        goto error;
59787db96d56Sopenharmony_ci    }
59797db96d56Sopenharmony_ci    Py_XDECREF(kwargs);
59807db96d56Sopenharmony_ci    Py_DECREF(args);
59817db96d56Sopenharmony_ci    Py_DECREF(cls);
59827db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, obj, -1);
59837db96d56Sopenharmony_ci    return 0;
59847db96d56Sopenharmony_ci
59857db96d56Sopenharmony_cierror:
59867db96d56Sopenharmony_ci    Py_XDECREF(kwargs);
59877db96d56Sopenharmony_ci    Py_DECREF(args);
59887db96d56Sopenharmony_ci    Py_DECREF(cls);
59897db96d56Sopenharmony_ci    return -1;
59907db96d56Sopenharmony_ci}
59917db96d56Sopenharmony_ci
59927db96d56Sopenharmony_cistatic int
59937db96d56Sopenharmony_ciload_global(UnpicklerObject *self)
59947db96d56Sopenharmony_ci{
59957db96d56Sopenharmony_ci    PyObject *global = NULL;
59967db96d56Sopenharmony_ci    PyObject *module_name;
59977db96d56Sopenharmony_ci    PyObject *global_name;
59987db96d56Sopenharmony_ci    Py_ssize_t len;
59997db96d56Sopenharmony_ci    char *s;
60007db96d56Sopenharmony_ci
60017db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) < 0)
60027db96d56Sopenharmony_ci        return -1;
60037db96d56Sopenharmony_ci    if (len < 2)
60047db96d56Sopenharmony_ci        return bad_readline();
60057db96d56Sopenharmony_ci    module_name = PyUnicode_DecodeUTF8(s, len - 1, "strict");
60067db96d56Sopenharmony_ci    if (!module_name)
60077db96d56Sopenharmony_ci        return -1;
60087db96d56Sopenharmony_ci
60097db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) >= 0) {
60107db96d56Sopenharmony_ci        if (len < 2) {
60117db96d56Sopenharmony_ci            Py_DECREF(module_name);
60127db96d56Sopenharmony_ci            return bad_readline();
60137db96d56Sopenharmony_ci        }
60147db96d56Sopenharmony_ci        global_name = PyUnicode_DecodeUTF8(s, len - 1, "strict");
60157db96d56Sopenharmony_ci        if (global_name) {
60167db96d56Sopenharmony_ci            global = find_class(self, module_name, global_name);
60177db96d56Sopenharmony_ci            Py_DECREF(global_name);
60187db96d56Sopenharmony_ci        }
60197db96d56Sopenharmony_ci    }
60207db96d56Sopenharmony_ci    Py_DECREF(module_name);
60217db96d56Sopenharmony_ci
60227db96d56Sopenharmony_ci    if (global == NULL)
60237db96d56Sopenharmony_ci        return -1;
60247db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, global, -1);
60257db96d56Sopenharmony_ci    return 0;
60267db96d56Sopenharmony_ci}
60277db96d56Sopenharmony_ci
60287db96d56Sopenharmony_cistatic int
60297db96d56Sopenharmony_ciload_stack_global(UnpicklerObject *self)
60307db96d56Sopenharmony_ci{
60317db96d56Sopenharmony_ci    PyObject *global;
60327db96d56Sopenharmony_ci    PyObject *module_name;
60337db96d56Sopenharmony_ci    PyObject *global_name;
60347db96d56Sopenharmony_ci
60357db96d56Sopenharmony_ci    PDATA_POP(self->stack, global_name);
60367db96d56Sopenharmony_ci    PDATA_POP(self->stack, module_name);
60377db96d56Sopenharmony_ci    if (module_name == NULL || !PyUnicode_CheckExact(module_name) ||
60387db96d56Sopenharmony_ci        global_name == NULL || !PyUnicode_CheckExact(global_name)) {
60397db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
60407db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError, "STACK_GLOBAL requires str");
60417db96d56Sopenharmony_ci        Py_XDECREF(global_name);
60427db96d56Sopenharmony_ci        Py_XDECREF(module_name);
60437db96d56Sopenharmony_ci        return -1;
60447db96d56Sopenharmony_ci    }
60457db96d56Sopenharmony_ci    global = find_class(self, module_name, global_name);
60467db96d56Sopenharmony_ci    Py_DECREF(global_name);
60477db96d56Sopenharmony_ci    Py_DECREF(module_name);
60487db96d56Sopenharmony_ci    if (global == NULL)
60497db96d56Sopenharmony_ci        return -1;
60507db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, global, -1);
60517db96d56Sopenharmony_ci    return 0;
60527db96d56Sopenharmony_ci}
60537db96d56Sopenharmony_ci
60547db96d56Sopenharmony_cistatic int
60557db96d56Sopenharmony_ciload_persid(UnpicklerObject *self)
60567db96d56Sopenharmony_ci{
60577db96d56Sopenharmony_ci    PyObject *pid, *obj;
60587db96d56Sopenharmony_ci    Py_ssize_t len;
60597db96d56Sopenharmony_ci    char *s;
60607db96d56Sopenharmony_ci
60617db96d56Sopenharmony_ci    if (self->pers_func) {
60627db96d56Sopenharmony_ci        if ((len = _Unpickler_Readline(self, &s)) < 0)
60637db96d56Sopenharmony_ci            return -1;
60647db96d56Sopenharmony_ci        if (len < 1)
60657db96d56Sopenharmony_ci            return bad_readline();
60667db96d56Sopenharmony_ci
60677db96d56Sopenharmony_ci        pid = PyUnicode_DecodeASCII(s, len - 1, "strict");
60687db96d56Sopenharmony_ci        if (pid == NULL) {
60697db96d56Sopenharmony_ci            if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
60707db96d56Sopenharmony_ci                PyErr_SetString(_Pickle_GetGlobalState()->UnpicklingError,
60717db96d56Sopenharmony_ci                                "persistent IDs in protocol 0 must be "
60727db96d56Sopenharmony_ci                                "ASCII strings");
60737db96d56Sopenharmony_ci            }
60747db96d56Sopenharmony_ci            return -1;
60757db96d56Sopenharmony_ci        }
60767db96d56Sopenharmony_ci
60777db96d56Sopenharmony_ci        obj = call_method(self->pers_func, self->pers_func_self, pid);
60787db96d56Sopenharmony_ci        Py_DECREF(pid);
60797db96d56Sopenharmony_ci        if (obj == NULL)
60807db96d56Sopenharmony_ci            return -1;
60817db96d56Sopenharmony_ci
60827db96d56Sopenharmony_ci        PDATA_PUSH(self->stack, obj, -1);
60837db96d56Sopenharmony_ci        return 0;
60847db96d56Sopenharmony_ci    }
60857db96d56Sopenharmony_ci    else {
60867db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
60877db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError,
60887db96d56Sopenharmony_ci                        "A load persistent id instruction was encountered,\n"
60897db96d56Sopenharmony_ci                        "but no persistent_load function was specified.");
60907db96d56Sopenharmony_ci        return -1;
60917db96d56Sopenharmony_ci    }
60927db96d56Sopenharmony_ci}
60937db96d56Sopenharmony_ci
60947db96d56Sopenharmony_cistatic int
60957db96d56Sopenharmony_ciload_binpersid(UnpicklerObject *self)
60967db96d56Sopenharmony_ci{
60977db96d56Sopenharmony_ci    PyObject *pid, *obj;
60987db96d56Sopenharmony_ci
60997db96d56Sopenharmony_ci    if (self->pers_func) {
61007db96d56Sopenharmony_ci        PDATA_POP(self->stack, pid);
61017db96d56Sopenharmony_ci        if (pid == NULL)
61027db96d56Sopenharmony_ci            return -1;
61037db96d56Sopenharmony_ci
61047db96d56Sopenharmony_ci        obj = call_method(self->pers_func, self->pers_func_self, pid);
61057db96d56Sopenharmony_ci        Py_DECREF(pid);
61067db96d56Sopenharmony_ci        if (obj == NULL)
61077db96d56Sopenharmony_ci            return -1;
61087db96d56Sopenharmony_ci
61097db96d56Sopenharmony_ci        PDATA_PUSH(self->stack, obj, -1);
61107db96d56Sopenharmony_ci        return 0;
61117db96d56Sopenharmony_ci    }
61127db96d56Sopenharmony_ci    else {
61137db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
61147db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError,
61157db96d56Sopenharmony_ci                        "A load persistent id instruction was encountered,\n"
61167db96d56Sopenharmony_ci                        "but no persistent_load function was specified.");
61177db96d56Sopenharmony_ci        return -1;
61187db96d56Sopenharmony_ci    }
61197db96d56Sopenharmony_ci}
61207db96d56Sopenharmony_ci
61217db96d56Sopenharmony_cistatic int
61227db96d56Sopenharmony_ciload_pop(UnpicklerObject *self)
61237db96d56Sopenharmony_ci{
61247db96d56Sopenharmony_ci    Py_ssize_t len = Py_SIZE(self->stack);
61257db96d56Sopenharmony_ci
61267db96d56Sopenharmony_ci    /* Note that we split the (pickle.py) stack into two stacks,
61277db96d56Sopenharmony_ci     * an object stack and a mark stack. We have to be clever and
61287db96d56Sopenharmony_ci     * pop the right one. We do this by looking at the top of the
61297db96d56Sopenharmony_ci     * mark stack first, and only signalling a stack underflow if
61307db96d56Sopenharmony_ci     * the object stack is empty and the mark stack doesn't match
61317db96d56Sopenharmony_ci     * our expectations.
61327db96d56Sopenharmony_ci     */
61337db96d56Sopenharmony_ci    if (self->num_marks > 0 && self->marks[self->num_marks - 1] == len) {
61347db96d56Sopenharmony_ci        self->num_marks--;
61357db96d56Sopenharmony_ci        self->stack->mark_set = self->num_marks != 0;
61367db96d56Sopenharmony_ci        self->stack->fence = self->num_marks ?
61377db96d56Sopenharmony_ci                self->marks[self->num_marks - 1] : 0;
61387db96d56Sopenharmony_ci    } else if (len <= self->stack->fence)
61397db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
61407db96d56Sopenharmony_ci    else {
61417db96d56Sopenharmony_ci        len--;
61427db96d56Sopenharmony_ci        Py_DECREF(self->stack->data[len]);
61437db96d56Sopenharmony_ci        Py_SET_SIZE(self->stack, len);
61447db96d56Sopenharmony_ci    }
61457db96d56Sopenharmony_ci    return 0;
61467db96d56Sopenharmony_ci}
61477db96d56Sopenharmony_ci
61487db96d56Sopenharmony_cistatic int
61497db96d56Sopenharmony_ciload_pop_mark(UnpicklerObject *self)
61507db96d56Sopenharmony_ci{
61517db96d56Sopenharmony_ci    Py_ssize_t i;
61527db96d56Sopenharmony_ci
61537db96d56Sopenharmony_ci    if ((i = marker(self)) < 0)
61547db96d56Sopenharmony_ci        return -1;
61557db96d56Sopenharmony_ci
61567db96d56Sopenharmony_ci    Pdata_clear(self->stack, i);
61577db96d56Sopenharmony_ci
61587db96d56Sopenharmony_ci    return 0;
61597db96d56Sopenharmony_ci}
61607db96d56Sopenharmony_ci
61617db96d56Sopenharmony_cistatic int
61627db96d56Sopenharmony_ciload_dup(UnpicklerObject *self)
61637db96d56Sopenharmony_ci{
61647db96d56Sopenharmony_ci    PyObject *last;
61657db96d56Sopenharmony_ci    Py_ssize_t len = Py_SIZE(self->stack);
61667db96d56Sopenharmony_ci
61677db96d56Sopenharmony_ci    if (len <= self->stack->fence)
61687db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
61697db96d56Sopenharmony_ci    last = self->stack->data[len - 1];
61707db96d56Sopenharmony_ci    PDATA_APPEND(self->stack, last, -1);
61717db96d56Sopenharmony_ci    return 0;
61727db96d56Sopenharmony_ci}
61737db96d56Sopenharmony_ci
61747db96d56Sopenharmony_cistatic int
61757db96d56Sopenharmony_ciload_get(UnpicklerObject *self)
61767db96d56Sopenharmony_ci{
61777db96d56Sopenharmony_ci    PyObject *key, *value;
61787db96d56Sopenharmony_ci    Py_ssize_t idx;
61797db96d56Sopenharmony_ci    Py_ssize_t len;
61807db96d56Sopenharmony_ci    char *s;
61817db96d56Sopenharmony_ci
61827db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) < 0)
61837db96d56Sopenharmony_ci        return -1;
61847db96d56Sopenharmony_ci    if (len < 2)
61857db96d56Sopenharmony_ci        return bad_readline();
61867db96d56Sopenharmony_ci
61877db96d56Sopenharmony_ci    key = PyLong_FromString(s, NULL, 10);
61887db96d56Sopenharmony_ci    if (key == NULL)
61897db96d56Sopenharmony_ci        return -1;
61907db96d56Sopenharmony_ci    idx = PyLong_AsSsize_t(key);
61917db96d56Sopenharmony_ci    if (idx == -1 && PyErr_Occurred()) {
61927db96d56Sopenharmony_ci        Py_DECREF(key);
61937db96d56Sopenharmony_ci        return -1;
61947db96d56Sopenharmony_ci    }
61957db96d56Sopenharmony_ci
61967db96d56Sopenharmony_ci    value = _Unpickler_MemoGet(self, idx);
61977db96d56Sopenharmony_ci    if (value == NULL) {
61987db96d56Sopenharmony_ci        if (!PyErr_Occurred()) {
61997db96d56Sopenharmony_ci           PickleState *st = _Pickle_GetGlobalState();
62007db96d56Sopenharmony_ci           PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx);
62017db96d56Sopenharmony_ci        }
62027db96d56Sopenharmony_ci        Py_DECREF(key);
62037db96d56Sopenharmony_ci        return -1;
62047db96d56Sopenharmony_ci    }
62057db96d56Sopenharmony_ci    Py_DECREF(key);
62067db96d56Sopenharmony_ci
62077db96d56Sopenharmony_ci    PDATA_APPEND(self->stack, value, -1);
62087db96d56Sopenharmony_ci    return 0;
62097db96d56Sopenharmony_ci}
62107db96d56Sopenharmony_ci
62117db96d56Sopenharmony_cistatic int
62127db96d56Sopenharmony_ciload_binget(UnpicklerObject *self)
62137db96d56Sopenharmony_ci{
62147db96d56Sopenharmony_ci    PyObject *value;
62157db96d56Sopenharmony_ci    Py_ssize_t idx;
62167db96d56Sopenharmony_ci    char *s;
62177db96d56Sopenharmony_ci
62187db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 1) < 0)
62197db96d56Sopenharmony_ci        return -1;
62207db96d56Sopenharmony_ci
62217db96d56Sopenharmony_ci    idx = Py_CHARMASK(s[0]);
62227db96d56Sopenharmony_ci
62237db96d56Sopenharmony_ci    value = _Unpickler_MemoGet(self, idx);
62247db96d56Sopenharmony_ci    if (value == NULL) {
62257db96d56Sopenharmony_ci        PyObject *key = PyLong_FromSsize_t(idx);
62267db96d56Sopenharmony_ci        if (key != NULL) {
62277db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
62287db96d56Sopenharmony_ci            PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx);
62297db96d56Sopenharmony_ci            Py_DECREF(key);
62307db96d56Sopenharmony_ci        }
62317db96d56Sopenharmony_ci        return -1;
62327db96d56Sopenharmony_ci    }
62337db96d56Sopenharmony_ci
62347db96d56Sopenharmony_ci    PDATA_APPEND(self->stack, value, -1);
62357db96d56Sopenharmony_ci    return 0;
62367db96d56Sopenharmony_ci}
62377db96d56Sopenharmony_ci
62387db96d56Sopenharmony_cistatic int
62397db96d56Sopenharmony_ciload_long_binget(UnpicklerObject *self)
62407db96d56Sopenharmony_ci{
62417db96d56Sopenharmony_ci    PyObject *value;
62427db96d56Sopenharmony_ci    Py_ssize_t idx;
62437db96d56Sopenharmony_ci    char *s;
62447db96d56Sopenharmony_ci
62457db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 4) < 0)
62467db96d56Sopenharmony_ci        return -1;
62477db96d56Sopenharmony_ci
62487db96d56Sopenharmony_ci    idx = calc_binsize(s, 4);
62497db96d56Sopenharmony_ci
62507db96d56Sopenharmony_ci    value = _Unpickler_MemoGet(self, idx);
62517db96d56Sopenharmony_ci    if (value == NULL) {
62527db96d56Sopenharmony_ci        PyObject *key = PyLong_FromSsize_t(idx);
62537db96d56Sopenharmony_ci        if (key != NULL) {
62547db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
62557db96d56Sopenharmony_ci            PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx);
62567db96d56Sopenharmony_ci            Py_DECREF(key);
62577db96d56Sopenharmony_ci        }
62587db96d56Sopenharmony_ci        return -1;
62597db96d56Sopenharmony_ci    }
62607db96d56Sopenharmony_ci
62617db96d56Sopenharmony_ci    PDATA_APPEND(self->stack, value, -1);
62627db96d56Sopenharmony_ci    return 0;
62637db96d56Sopenharmony_ci}
62647db96d56Sopenharmony_ci
62657db96d56Sopenharmony_ci/* Push an object from the extension registry (EXT[124]).  nbytes is
62667db96d56Sopenharmony_ci * the number of bytes following the opcode, holding the index (code) value.
62677db96d56Sopenharmony_ci */
62687db96d56Sopenharmony_cistatic int
62697db96d56Sopenharmony_ciload_extension(UnpicklerObject *self, int nbytes)
62707db96d56Sopenharmony_ci{
62717db96d56Sopenharmony_ci    char *codebytes;            /* the nbytes bytes after the opcode */
62727db96d56Sopenharmony_ci    long code;                  /* calc_binint returns long */
62737db96d56Sopenharmony_ci    PyObject *py_code;          /* code as a Python int */
62747db96d56Sopenharmony_ci    PyObject *obj;              /* the object to push */
62757db96d56Sopenharmony_ci    PyObject *pair;             /* (module_name, class_name) */
62767db96d56Sopenharmony_ci    PyObject *module_name, *class_name;
62777db96d56Sopenharmony_ci    PickleState *st = _Pickle_GetGlobalState();
62787db96d56Sopenharmony_ci
62797db96d56Sopenharmony_ci    assert(nbytes == 1 || nbytes == 2 || nbytes == 4);
62807db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &codebytes, nbytes) < 0)
62817db96d56Sopenharmony_ci        return -1;
62827db96d56Sopenharmony_ci    code = calc_binint(codebytes, nbytes);
62837db96d56Sopenharmony_ci    if (code <= 0) {            /* note that 0 is forbidden */
62847db96d56Sopenharmony_ci        /* Corrupt or hostile pickle. */
62857db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError, "EXT specifies code <= 0");
62867db96d56Sopenharmony_ci        return -1;
62877db96d56Sopenharmony_ci    }
62887db96d56Sopenharmony_ci
62897db96d56Sopenharmony_ci    /* Look for the code in the cache. */
62907db96d56Sopenharmony_ci    py_code = PyLong_FromLong(code);
62917db96d56Sopenharmony_ci    if (py_code == NULL)
62927db96d56Sopenharmony_ci        return -1;
62937db96d56Sopenharmony_ci    obj = PyDict_GetItemWithError(st->extension_cache, py_code);
62947db96d56Sopenharmony_ci    if (obj != NULL) {
62957db96d56Sopenharmony_ci        /* Bingo. */
62967db96d56Sopenharmony_ci        Py_DECREF(py_code);
62977db96d56Sopenharmony_ci        PDATA_APPEND(self->stack, obj, -1);
62987db96d56Sopenharmony_ci        return 0;
62997db96d56Sopenharmony_ci    }
63007db96d56Sopenharmony_ci    if (PyErr_Occurred()) {
63017db96d56Sopenharmony_ci        Py_DECREF(py_code);
63027db96d56Sopenharmony_ci        return -1;
63037db96d56Sopenharmony_ci    }
63047db96d56Sopenharmony_ci
63057db96d56Sopenharmony_ci    /* Look up the (module_name, class_name) pair. */
63067db96d56Sopenharmony_ci    pair = PyDict_GetItemWithError(st->inverted_registry, py_code);
63077db96d56Sopenharmony_ci    if (pair == NULL) {
63087db96d56Sopenharmony_ci        Py_DECREF(py_code);
63097db96d56Sopenharmony_ci        if (!PyErr_Occurred()) {
63107db96d56Sopenharmony_ci            PyErr_Format(PyExc_ValueError, "unregistered extension "
63117db96d56Sopenharmony_ci                         "code %ld", code);
63127db96d56Sopenharmony_ci        }
63137db96d56Sopenharmony_ci        return -1;
63147db96d56Sopenharmony_ci    }
63157db96d56Sopenharmony_ci    /* Since the extension registry is manipulable via Python code,
63167db96d56Sopenharmony_ci     * confirm that pair is really a 2-tuple of strings.
63177db96d56Sopenharmony_ci     */
63187db96d56Sopenharmony_ci    if (!PyTuple_Check(pair) || PyTuple_Size(pair) != 2) {
63197db96d56Sopenharmony_ci        goto error;
63207db96d56Sopenharmony_ci    }
63217db96d56Sopenharmony_ci
63227db96d56Sopenharmony_ci    module_name = PyTuple_GET_ITEM(pair, 0);
63237db96d56Sopenharmony_ci    if (!PyUnicode_Check(module_name)) {
63247db96d56Sopenharmony_ci        goto error;
63257db96d56Sopenharmony_ci    }
63267db96d56Sopenharmony_ci
63277db96d56Sopenharmony_ci    class_name = PyTuple_GET_ITEM(pair, 1);
63287db96d56Sopenharmony_ci    if (!PyUnicode_Check(class_name)) {
63297db96d56Sopenharmony_ci        goto error;
63307db96d56Sopenharmony_ci    }
63317db96d56Sopenharmony_ci
63327db96d56Sopenharmony_ci    /* Load the object. */
63337db96d56Sopenharmony_ci    obj = find_class(self, module_name, class_name);
63347db96d56Sopenharmony_ci    if (obj == NULL) {
63357db96d56Sopenharmony_ci        Py_DECREF(py_code);
63367db96d56Sopenharmony_ci        return -1;
63377db96d56Sopenharmony_ci    }
63387db96d56Sopenharmony_ci    /* Cache code -> obj. */
63397db96d56Sopenharmony_ci    code = PyDict_SetItem(st->extension_cache, py_code, obj);
63407db96d56Sopenharmony_ci    Py_DECREF(py_code);
63417db96d56Sopenharmony_ci    if (code < 0) {
63427db96d56Sopenharmony_ci        Py_DECREF(obj);
63437db96d56Sopenharmony_ci        return -1;
63447db96d56Sopenharmony_ci    }
63457db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, obj, -1);
63467db96d56Sopenharmony_ci    return 0;
63477db96d56Sopenharmony_ci
63487db96d56Sopenharmony_cierror:
63497db96d56Sopenharmony_ci    Py_DECREF(py_code);
63507db96d56Sopenharmony_ci    PyErr_Format(PyExc_ValueError, "_inverted_registry[%ld] "
63517db96d56Sopenharmony_ci                 "isn't a 2-tuple of strings", code);
63527db96d56Sopenharmony_ci    return -1;
63537db96d56Sopenharmony_ci}
63547db96d56Sopenharmony_ci
63557db96d56Sopenharmony_cistatic int
63567db96d56Sopenharmony_ciload_put(UnpicklerObject *self)
63577db96d56Sopenharmony_ci{
63587db96d56Sopenharmony_ci    PyObject *key, *value;
63597db96d56Sopenharmony_ci    Py_ssize_t idx;
63607db96d56Sopenharmony_ci    Py_ssize_t len;
63617db96d56Sopenharmony_ci    char *s = NULL;
63627db96d56Sopenharmony_ci
63637db96d56Sopenharmony_ci    if ((len = _Unpickler_Readline(self, &s)) < 0)
63647db96d56Sopenharmony_ci        return -1;
63657db96d56Sopenharmony_ci    if (len < 2)
63667db96d56Sopenharmony_ci        return bad_readline();
63677db96d56Sopenharmony_ci    if (Py_SIZE(self->stack) <= self->stack->fence)
63687db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
63697db96d56Sopenharmony_ci    value = self->stack->data[Py_SIZE(self->stack) - 1];
63707db96d56Sopenharmony_ci
63717db96d56Sopenharmony_ci    key = PyLong_FromString(s, NULL, 10);
63727db96d56Sopenharmony_ci    if (key == NULL)
63737db96d56Sopenharmony_ci        return -1;
63747db96d56Sopenharmony_ci    idx = PyLong_AsSsize_t(key);
63757db96d56Sopenharmony_ci    Py_DECREF(key);
63767db96d56Sopenharmony_ci    if (idx < 0) {
63777db96d56Sopenharmony_ci        if (!PyErr_Occurred())
63787db96d56Sopenharmony_ci            PyErr_SetString(PyExc_ValueError,
63797db96d56Sopenharmony_ci                            "negative PUT argument");
63807db96d56Sopenharmony_ci        return -1;
63817db96d56Sopenharmony_ci    }
63827db96d56Sopenharmony_ci
63837db96d56Sopenharmony_ci    return _Unpickler_MemoPut(self, idx, value);
63847db96d56Sopenharmony_ci}
63857db96d56Sopenharmony_ci
63867db96d56Sopenharmony_cistatic int
63877db96d56Sopenharmony_ciload_binput(UnpicklerObject *self)
63887db96d56Sopenharmony_ci{
63897db96d56Sopenharmony_ci    PyObject *value;
63907db96d56Sopenharmony_ci    Py_ssize_t idx;
63917db96d56Sopenharmony_ci    char *s;
63927db96d56Sopenharmony_ci
63937db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 1) < 0)
63947db96d56Sopenharmony_ci        return -1;
63957db96d56Sopenharmony_ci
63967db96d56Sopenharmony_ci    if (Py_SIZE(self->stack) <= self->stack->fence)
63977db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
63987db96d56Sopenharmony_ci    value = self->stack->data[Py_SIZE(self->stack) - 1];
63997db96d56Sopenharmony_ci
64007db96d56Sopenharmony_ci    idx = Py_CHARMASK(s[0]);
64017db96d56Sopenharmony_ci
64027db96d56Sopenharmony_ci    return _Unpickler_MemoPut(self, idx, value);
64037db96d56Sopenharmony_ci}
64047db96d56Sopenharmony_ci
64057db96d56Sopenharmony_cistatic int
64067db96d56Sopenharmony_ciload_long_binput(UnpicklerObject *self)
64077db96d56Sopenharmony_ci{
64087db96d56Sopenharmony_ci    PyObject *value;
64097db96d56Sopenharmony_ci    Py_ssize_t idx;
64107db96d56Sopenharmony_ci    char *s;
64117db96d56Sopenharmony_ci
64127db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 4) < 0)
64137db96d56Sopenharmony_ci        return -1;
64147db96d56Sopenharmony_ci
64157db96d56Sopenharmony_ci    if (Py_SIZE(self->stack) <= self->stack->fence)
64167db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
64177db96d56Sopenharmony_ci    value = self->stack->data[Py_SIZE(self->stack) - 1];
64187db96d56Sopenharmony_ci
64197db96d56Sopenharmony_ci    idx = calc_binsize(s, 4);
64207db96d56Sopenharmony_ci    if (idx < 0) {
64217db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError,
64227db96d56Sopenharmony_ci                        "negative LONG_BINPUT argument");
64237db96d56Sopenharmony_ci        return -1;
64247db96d56Sopenharmony_ci    }
64257db96d56Sopenharmony_ci
64267db96d56Sopenharmony_ci    return _Unpickler_MemoPut(self, idx, value);
64277db96d56Sopenharmony_ci}
64287db96d56Sopenharmony_ci
64297db96d56Sopenharmony_cistatic int
64307db96d56Sopenharmony_ciload_memoize(UnpicklerObject *self)
64317db96d56Sopenharmony_ci{
64327db96d56Sopenharmony_ci    PyObject *value;
64337db96d56Sopenharmony_ci
64347db96d56Sopenharmony_ci    if (Py_SIZE(self->stack) <= self->stack->fence)
64357db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
64367db96d56Sopenharmony_ci    value = self->stack->data[Py_SIZE(self->stack) - 1];
64377db96d56Sopenharmony_ci
64387db96d56Sopenharmony_ci    return _Unpickler_MemoPut(self, self->memo_len, value);
64397db96d56Sopenharmony_ci}
64407db96d56Sopenharmony_ci
64417db96d56Sopenharmony_cistatic int
64427db96d56Sopenharmony_cido_append(UnpicklerObject *self, Py_ssize_t x)
64437db96d56Sopenharmony_ci{
64447db96d56Sopenharmony_ci    PyObject *value;
64457db96d56Sopenharmony_ci    PyObject *slice;
64467db96d56Sopenharmony_ci    PyObject *list;
64477db96d56Sopenharmony_ci    PyObject *result;
64487db96d56Sopenharmony_ci    Py_ssize_t len, i;
64497db96d56Sopenharmony_ci
64507db96d56Sopenharmony_ci    len = Py_SIZE(self->stack);
64517db96d56Sopenharmony_ci    if (x > len || x <= self->stack->fence)
64527db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
64537db96d56Sopenharmony_ci    if (len == x)  /* nothing to do */
64547db96d56Sopenharmony_ci        return 0;
64557db96d56Sopenharmony_ci
64567db96d56Sopenharmony_ci    list = self->stack->data[x - 1];
64577db96d56Sopenharmony_ci
64587db96d56Sopenharmony_ci    if (PyList_CheckExact(list)) {
64597db96d56Sopenharmony_ci        Py_ssize_t list_len;
64607db96d56Sopenharmony_ci        int ret;
64617db96d56Sopenharmony_ci
64627db96d56Sopenharmony_ci        slice = Pdata_poplist(self->stack, x);
64637db96d56Sopenharmony_ci        if (!slice)
64647db96d56Sopenharmony_ci            return -1;
64657db96d56Sopenharmony_ci        list_len = PyList_GET_SIZE(list);
64667db96d56Sopenharmony_ci        ret = PyList_SetSlice(list, list_len, list_len, slice);
64677db96d56Sopenharmony_ci        Py_DECREF(slice);
64687db96d56Sopenharmony_ci        return ret;
64697db96d56Sopenharmony_ci    }
64707db96d56Sopenharmony_ci    else {
64717db96d56Sopenharmony_ci        PyObject *extend_func;
64727db96d56Sopenharmony_ci
64737db96d56Sopenharmony_ci        if (_PyObject_LookupAttr(list, &_Py_ID(extend), &extend_func) < 0) {
64747db96d56Sopenharmony_ci            return -1;
64757db96d56Sopenharmony_ci        }
64767db96d56Sopenharmony_ci        if (extend_func != NULL) {
64777db96d56Sopenharmony_ci            slice = Pdata_poplist(self->stack, x);
64787db96d56Sopenharmony_ci            if (!slice) {
64797db96d56Sopenharmony_ci                Py_DECREF(extend_func);
64807db96d56Sopenharmony_ci                return -1;
64817db96d56Sopenharmony_ci            }
64827db96d56Sopenharmony_ci            result = _Pickle_FastCall(extend_func, slice);
64837db96d56Sopenharmony_ci            Py_DECREF(extend_func);
64847db96d56Sopenharmony_ci            if (result == NULL)
64857db96d56Sopenharmony_ci                return -1;
64867db96d56Sopenharmony_ci            Py_DECREF(result);
64877db96d56Sopenharmony_ci        }
64887db96d56Sopenharmony_ci        else {
64897db96d56Sopenharmony_ci            PyObject *append_func;
64907db96d56Sopenharmony_ci
64917db96d56Sopenharmony_ci            /* Even if the PEP 307 requires extend() and append() methods,
64927db96d56Sopenharmony_ci               fall back on append() if the object has no extend() method
64937db96d56Sopenharmony_ci               for backward compatibility. */
64947db96d56Sopenharmony_ci            append_func = PyObject_GetAttr(list, &_Py_ID(append));
64957db96d56Sopenharmony_ci            if (append_func == NULL)
64967db96d56Sopenharmony_ci                return -1;
64977db96d56Sopenharmony_ci            for (i = x; i < len; i++) {
64987db96d56Sopenharmony_ci                value = self->stack->data[i];
64997db96d56Sopenharmony_ci                result = _Pickle_FastCall(append_func, value);
65007db96d56Sopenharmony_ci                if (result == NULL) {
65017db96d56Sopenharmony_ci                    Pdata_clear(self->stack, i + 1);
65027db96d56Sopenharmony_ci                    Py_SET_SIZE(self->stack, x);
65037db96d56Sopenharmony_ci                    Py_DECREF(append_func);
65047db96d56Sopenharmony_ci                    return -1;
65057db96d56Sopenharmony_ci                }
65067db96d56Sopenharmony_ci                Py_DECREF(result);
65077db96d56Sopenharmony_ci            }
65087db96d56Sopenharmony_ci            Py_SET_SIZE(self->stack, x);
65097db96d56Sopenharmony_ci            Py_DECREF(append_func);
65107db96d56Sopenharmony_ci        }
65117db96d56Sopenharmony_ci    }
65127db96d56Sopenharmony_ci
65137db96d56Sopenharmony_ci    return 0;
65147db96d56Sopenharmony_ci}
65157db96d56Sopenharmony_ci
65167db96d56Sopenharmony_cistatic int
65177db96d56Sopenharmony_ciload_append(UnpicklerObject *self)
65187db96d56Sopenharmony_ci{
65197db96d56Sopenharmony_ci    if (Py_SIZE(self->stack) - 1 <= self->stack->fence)
65207db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
65217db96d56Sopenharmony_ci    return do_append(self, Py_SIZE(self->stack) - 1);
65227db96d56Sopenharmony_ci}
65237db96d56Sopenharmony_ci
65247db96d56Sopenharmony_cistatic int
65257db96d56Sopenharmony_ciload_appends(UnpicklerObject *self)
65267db96d56Sopenharmony_ci{
65277db96d56Sopenharmony_ci    Py_ssize_t i = marker(self);
65287db96d56Sopenharmony_ci    if (i < 0)
65297db96d56Sopenharmony_ci        return -1;
65307db96d56Sopenharmony_ci    return do_append(self, i);
65317db96d56Sopenharmony_ci}
65327db96d56Sopenharmony_ci
65337db96d56Sopenharmony_cistatic int
65347db96d56Sopenharmony_cido_setitems(UnpicklerObject *self, Py_ssize_t x)
65357db96d56Sopenharmony_ci{
65367db96d56Sopenharmony_ci    PyObject *value, *key;
65377db96d56Sopenharmony_ci    PyObject *dict;
65387db96d56Sopenharmony_ci    Py_ssize_t len, i;
65397db96d56Sopenharmony_ci    int status = 0;
65407db96d56Sopenharmony_ci
65417db96d56Sopenharmony_ci    len = Py_SIZE(self->stack);
65427db96d56Sopenharmony_ci    if (x > len || x <= self->stack->fence)
65437db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
65447db96d56Sopenharmony_ci    if (len == x)  /* nothing to do */
65457db96d56Sopenharmony_ci        return 0;
65467db96d56Sopenharmony_ci    if ((len - x) % 2 != 0) {
65477db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
65487db96d56Sopenharmony_ci        /* Corrupt or hostile pickle -- we never write one like this. */
65497db96d56Sopenharmony_ci        PyErr_SetString(st->UnpicklingError,
65507db96d56Sopenharmony_ci                        "odd number of items for SETITEMS");
65517db96d56Sopenharmony_ci        return -1;
65527db96d56Sopenharmony_ci    }
65537db96d56Sopenharmony_ci
65547db96d56Sopenharmony_ci    /* Here, dict does not actually need to be a PyDict; it could be anything
65557db96d56Sopenharmony_ci       that supports the __setitem__ attribute. */
65567db96d56Sopenharmony_ci    dict = self->stack->data[x - 1];
65577db96d56Sopenharmony_ci
65587db96d56Sopenharmony_ci    for (i = x + 1; i < len; i += 2) {
65597db96d56Sopenharmony_ci        key = self->stack->data[i - 1];
65607db96d56Sopenharmony_ci        value = self->stack->data[i];
65617db96d56Sopenharmony_ci        if (PyObject_SetItem(dict, key, value) < 0) {
65627db96d56Sopenharmony_ci            status = -1;
65637db96d56Sopenharmony_ci            break;
65647db96d56Sopenharmony_ci        }
65657db96d56Sopenharmony_ci    }
65667db96d56Sopenharmony_ci
65677db96d56Sopenharmony_ci    Pdata_clear(self->stack, x);
65687db96d56Sopenharmony_ci    return status;
65697db96d56Sopenharmony_ci}
65707db96d56Sopenharmony_ci
65717db96d56Sopenharmony_cistatic int
65727db96d56Sopenharmony_ciload_setitem(UnpicklerObject *self)
65737db96d56Sopenharmony_ci{
65747db96d56Sopenharmony_ci    return do_setitems(self, Py_SIZE(self->stack) - 2);
65757db96d56Sopenharmony_ci}
65767db96d56Sopenharmony_ci
65777db96d56Sopenharmony_cistatic int
65787db96d56Sopenharmony_ciload_setitems(UnpicklerObject *self)
65797db96d56Sopenharmony_ci{
65807db96d56Sopenharmony_ci    Py_ssize_t i = marker(self);
65817db96d56Sopenharmony_ci    if (i < 0)
65827db96d56Sopenharmony_ci        return -1;
65837db96d56Sopenharmony_ci    return do_setitems(self, i);
65847db96d56Sopenharmony_ci}
65857db96d56Sopenharmony_ci
65867db96d56Sopenharmony_cistatic int
65877db96d56Sopenharmony_ciload_additems(UnpicklerObject *self)
65887db96d56Sopenharmony_ci{
65897db96d56Sopenharmony_ci    PyObject *set;
65907db96d56Sopenharmony_ci    Py_ssize_t mark, len, i;
65917db96d56Sopenharmony_ci
65927db96d56Sopenharmony_ci    mark =  marker(self);
65937db96d56Sopenharmony_ci    if (mark < 0)
65947db96d56Sopenharmony_ci        return -1;
65957db96d56Sopenharmony_ci    len = Py_SIZE(self->stack);
65967db96d56Sopenharmony_ci    if (mark > len || mark <= self->stack->fence)
65977db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
65987db96d56Sopenharmony_ci    if (len == mark)  /* nothing to do */
65997db96d56Sopenharmony_ci        return 0;
66007db96d56Sopenharmony_ci
66017db96d56Sopenharmony_ci    set = self->stack->data[mark - 1];
66027db96d56Sopenharmony_ci
66037db96d56Sopenharmony_ci    if (PySet_Check(set)) {
66047db96d56Sopenharmony_ci        PyObject *items;
66057db96d56Sopenharmony_ci        int status;
66067db96d56Sopenharmony_ci
66077db96d56Sopenharmony_ci        items = Pdata_poptuple(self->stack, mark);
66087db96d56Sopenharmony_ci        if (items == NULL)
66097db96d56Sopenharmony_ci            return -1;
66107db96d56Sopenharmony_ci
66117db96d56Sopenharmony_ci        status = _PySet_Update(set, items);
66127db96d56Sopenharmony_ci        Py_DECREF(items);
66137db96d56Sopenharmony_ci        return status;
66147db96d56Sopenharmony_ci    }
66157db96d56Sopenharmony_ci    else {
66167db96d56Sopenharmony_ci        PyObject *add_func;
66177db96d56Sopenharmony_ci
66187db96d56Sopenharmony_ci        add_func = PyObject_GetAttr(set, &_Py_ID(add));
66197db96d56Sopenharmony_ci        if (add_func == NULL)
66207db96d56Sopenharmony_ci            return -1;
66217db96d56Sopenharmony_ci        for (i = mark; i < len; i++) {
66227db96d56Sopenharmony_ci            PyObject *result;
66237db96d56Sopenharmony_ci            PyObject *item;
66247db96d56Sopenharmony_ci
66257db96d56Sopenharmony_ci            item = self->stack->data[i];
66267db96d56Sopenharmony_ci            result = _Pickle_FastCall(add_func, item);
66277db96d56Sopenharmony_ci            if (result == NULL) {
66287db96d56Sopenharmony_ci                Pdata_clear(self->stack, i + 1);
66297db96d56Sopenharmony_ci                Py_SET_SIZE(self->stack, mark);
66307db96d56Sopenharmony_ci                return -1;
66317db96d56Sopenharmony_ci            }
66327db96d56Sopenharmony_ci            Py_DECREF(result);
66337db96d56Sopenharmony_ci        }
66347db96d56Sopenharmony_ci        Py_SET_SIZE(self->stack, mark);
66357db96d56Sopenharmony_ci    }
66367db96d56Sopenharmony_ci
66377db96d56Sopenharmony_ci    return 0;
66387db96d56Sopenharmony_ci}
66397db96d56Sopenharmony_ci
66407db96d56Sopenharmony_cistatic int
66417db96d56Sopenharmony_ciload_build(UnpicklerObject *self)
66427db96d56Sopenharmony_ci{
66437db96d56Sopenharmony_ci    PyObject *state, *inst, *slotstate;
66447db96d56Sopenharmony_ci    PyObject *setstate;
66457db96d56Sopenharmony_ci    int status = 0;
66467db96d56Sopenharmony_ci
66477db96d56Sopenharmony_ci    /* Stack is ... instance, state.  We want to leave instance at
66487db96d56Sopenharmony_ci     * the stack top, possibly mutated via instance.__setstate__(state).
66497db96d56Sopenharmony_ci     */
66507db96d56Sopenharmony_ci    if (Py_SIZE(self->stack) - 2 < self->stack->fence)
66517db96d56Sopenharmony_ci        return Pdata_stack_underflow(self->stack);
66527db96d56Sopenharmony_ci
66537db96d56Sopenharmony_ci    PDATA_POP(self->stack, state);
66547db96d56Sopenharmony_ci    if (state == NULL)
66557db96d56Sopenharmony_ci        return -1;
66567db96d56Sopenharmony_ci
66577db96d56Sopenharmony_ci    inst = self->stack->data[Py_SIZE(self->stack) - 1];
66587db96d56Sopenharmony_ci
66597db96d56Sopenharmony_ci    if (_PyObject_LookupAttr(inst, &_Py_ID(__setstate__), &setstate) < 0) {
66607db96d56Sopenharmony_ci        Py_DECREF(state);
66617db96d56Sopenharmony_ci        return -1;
66627db96d56Sopenharmony_ci    }
66637db96d56Sopenharmony_ci    if (setstate != NULL) {
66647db96d56Sopenharmony_ci        PyObject *result;
66657db96d56Sopenharmony_ci
66667db96d56Sopenharmony_ci        /* The explicit __setstate__ is responsible for everything. */
66677db96d56Sopenharmony_ci        result = _Pickle_FastCall(setstate, state);
66687db96d56Sopenharmony_ci        Py_DECREF(setstate);
66697db96d56Sopenharmony_ci        if (result == NULL)
66707db96d56Sopenharmony_ci            return -1;
66717db96d56Sopenharmony_ci        Py_DECREF(result);
66727db96d56Sopenharmony_ci        return 0;
66737db96d56Sopenharmony_ci    }
66747db96d56Sopenharmony_ci
66757db96d56Sopenharmony_ci    /* A default __setstate__.  First see whether state embeds a
66767db96d56Sopenharmony_ci     * slot state dict too (a proto 2 addition).
66777db96d56Sopenharmony_ci     */
66787db96d56Sopenharmony_ci    if (PyTuple_Check(state) && PyTuple_GET_SIZE(state) == 2) {
66797db96d56Sopenharmony_ci        PyObject *tmp = state;
66807db96d56Sopenharmony_ci
66817db96d56Sopenharmony_ci        state = PyTuple_GET_ITEM(tmp, 0);
66827db96d56Sopenharmony_ci        slotstate = PyTuple_GET_ITEM(tmp, 1);
66837db96d56Sopenharmony_ci        Py_INCREF(state);
66847db96d56Sopenharmony_ci        Py_INCREF(slotstate);
66857db96d56Sopenharmony_ci        Py_DECREF(tmp);
66867db96d56Sopenharmony_ci    }
66877db96d56Sopenharmony_ci    else
66887db96d56Sopenharmony_ci        slotstate = NULL;
66897db96d56Sopenharmony_ci
66907db96d56Sopenharmony_ci    /* Set inst.__dict__ from the state dict (if any). */
66917db96d56Sopenharmony_ci    if (state != Py_None) {
66927db96d56Sopenharmony_ci        PyObject *dict;
66937db96d56Sopenharmony_ci        PyObject *d_key, *d_value;
66947db96d56Sopenharmony_ci        Py_ssize_t i;
66957db96d56Sopenharmony_ci
66967db96d56Sopenharmony_ci        if (!PyDict_Check(state)) {
66977db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
66987db96d56Sopenharmony_ci            PyErr_SetString(st->UnpicklingError, "state is not a dictionary");
66997db96d56Sopenharmony_ci            goto error;
67007db96d56Sopenharmony_ci        }
67017db96d56Sopenharmony_ci        dict = PyObject_GetAttr(inst, &_Py_ID(__dict__));
67027db96d56Sopenharmony_ci        if (dict == NULL)
67037db96d56Sopenharmony_ci            goto error;
67047db96d56Sopenharmony_ci
67057db96d56Sopenharmony_ci        i = 0;
67067db96d56Sopenharmony_ci        while (PyDict_Next(state, &i, &d_key, &d_value)) {
67077db96d56Sopenharmony_ci            /* normally the keys for instance attributes are
67087db96d56Sopenharmony_ci               interned.  we should try to do that here. */
67097db96d56Sopenharmony_ci            Py_INCREF(d_key);
67107db96d56Sopenharmony_ci            if (PyUnicode_CheckExact(d_key))
67117db96d56Sopenharmony_ci                PyUnicode_InternInPlace(&d_key);
67127db96d56Sopenharmony_ci            if (PyObject_SetItem(dict, d_key, d_value) < 0) {
67137db96d56Sopenharmony_ci                Py_DECREF(d_key);
67147db96d56Sopenharmony_ci                goto error;
67157db96d56Sopenharmony_ci            }
67167db96d56Sopenharmony_ci            Py_DECREF(d_key);
67177db96d56Sopenharmony_ci        }
67187db96d56Sopenharmony_ci        Py_DECREF(dict);
67197db96d56Sopenharmony_ci    }
67207db96d56Sopenharmony_ci
67217db96d56Sopenharmony_ci    /* Also set instance attributes from the slotstate dict (if any). */
67227db96d56Sopenharmony_ci    if (slotstate != NULL) {
67237db96d56Sopenharmony_ci        PyObject *d_key, *d_value;
67247db96d56Sopenharmony_ci        Py_ssize_t i;
67257db96d56Sopenharmony_ci
67267db96d56Sopenharmony_ci        if (!PyDict_Check(slotstate)) {
67277db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
67287db96d56Sopenharmony_ci            PyErr_SetString(st->UnpicklingError,
67297db96d56Sopenharmony_ci                            "slot state is not a dictionary");
67307db96d56Sopenharmony_ci            goto error;
67317db96d56Sopenharmony_ci        }
67327db96d56Sopenharmony_ci        i = 0;
67337db96d56Sopenharmony_ci        while (PyDict_Next(slotstate, &i, &d_key, &d_value)) {
67347db96d56Sopenharmony_ci            if (PyObject_SetAttr(inst, d_key, d_value) < 0)
67357db96d56Sopenharmony_ci                goto error;
67367db96d56Sopenharmony_ci        }
67377db96d56Sopenharmony_ci    }
67387db96d56Sopenharmony_ci
67397db96d56Sopenharmony_ci    if (0) {
67407db96d56Sopenharmony_ci  error:
67417db96d56Sopenharmony_ci        status = -1;
67427db96d56Sopenharmony_ci    }
67437db96d56Sopenharmony_ci
67447db96d56Sopenharmony_ci    Py_DECREF(state);
67457db96d56Sopenharmony_ci    Py_XDECREF(slotstate);
67467db96d56Sopenharmony_ci    return status;
67477db96d56Sopenharmony_ci}
67487db96d56Sopenharmony_ci
67497db96d56Sopenharmony_cistatic int
67507db96d56Sopenharmony_ciload_mark(UnpicklerObject *self)
67517db96d56Sopenharmony_ci{
67527db96d56Sopenharmony_ci
67537db96d56Sopenharmony_ci    /* Note that we split the (pickle.py) stack into two stacks, an
67547db96d56Sopenharmony_ci     * object stack and a mark stack. Here we push a mark onto the
67557db96d56Sopenharmony_ci     * mark stack.
67567db96d56Sopenharmony_ci     */
67577db96d56Sopenharmony_ci
67587db96d56Sopenharmony_ci    if (self->num_marks >= self->marks_size) {
67597db96d56Sopenharmony_ci        size_t alloc = ((size_t)self->num_marks << 1) + 20;
67607db96d56Sopenharmony_ci        Py_ssize_t *marks_new = self->marks;
67617db96d56Sopenharmony_ci        PyMem_RESIZE(marks_new, Py_ssize_t, alloc);
67627db96d56Sopenharmony_ci        if (marks_new == NULL) {
67637db96d56Sopenharmony_ci            PyErr_NoMemory();
67647db96d56Sopenharmony_ci            return -1;
67657db96d56Sopenharmony_ci        }
67667db96d56Sopenharmony_ci        self->marks = marks_new;
67677db96d56Sopenharmony_ci        self->marks_size = (Py_ssize_t)alloc;
67687db96d56Sopenharmony_ci    }
67697db96d56Sopenharmony_ci
67707db96d56Sopenharmony_ci    self->stack->mark_set = 1;
67717db96d56Sopenharmony_ci    self->marks[self->num_marks++] = self->stack->fence = Py_SIZE(self->stack);
67727db96d56Sopenharmony_ci
67737db96d56Sopenharmony_ci    return 0;
67747db96d56Sopenharmony_ci}
67757db96d56Sopenharmony_ci
67767db96d56Sopenharmony_cistatic int
67777db96d56Sopenharmony_ciload_reduce(UnpicklerObject *self)
67787db96d56Sopenharmony_ci{
67797db96d56Sopenharmony_ci    PyObject *callable = NULL;
67807db96d56Sopenharmony_ci    PyObject *argtup = NULL;
67817db96d56Sopenharmony_ci    PyObject *obj = NULL;
67827db96d56Sopenharmony_ci
67837db96d56Sopenharmony_ci    PDATA_POP(self->stack, argtup);
67847db96d56Sopenharmony_ci    if (argtup == NULL)
67857db96d56Sopenharmony_ci        return -1;
67867db96d56Sopenharmony_ci    PDATA_POP(self->stack, callable);
67877db96d56Sopenharmony_ci    if (callable) {
67887db96d56Sopenharmony_ci        obj = PyObject_CallObject(callable, argtup);
67897db96d56Sopenharmony_ci        Py_DECREF(callable);
67907db96d56Sopenharmony_ci    }
67917db96d56Sopenharmony_ci    Py_DECREF(argtup);
67927db96d56Sopenharmony_ci
67937db96d56Sopenharmony_ci    if (obj == NULL)
67947db96d56Sopenharmony_ci        return -1;
67957db96d56Sopenharmony_ci
67967db96d56Sopenharmony_ci    PDATA_PUSH(self->stack, obj, -1);
67977db96d56Sopenharmony_ci    return 0;
67987db96d56Sopenharmony_ci}
67997db96d56Sopenharmony_ci
68007db96d56Sopenharmony_ci/* Just raises an error if we don't know the protocol specified.  PROTO
68017db96d56Sopenharmony_ci * is the first opcode for protocols >= 2.
68027db96d56Sopenharmony_ci */
68037db96d56Sopenharmony_cistatic int
68047db96d56Sopenharmony_ciload_proto(UnpicklerObject *self)
68057db96d56Sopenharmony_ci{
68067db96d56Sopenharmony_ci    char *s;
68077db96d56Sopenharmony_ci    int i;
68087db96d56Sopenharmony_ci
68097db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 1) < 0)
68107db96d56Sopenharmony_ci        return -1;
68117db96d56Sopenharmony_ci
68127db96d56Sopenharmony_ci    i = (unsigned char)s[0];
68137db96d56Sopenharmony_ci    if (i <= HIGHEST_PROTOCOL) {
68147db96d56Sopenharmony_ci        self->proto = i;
68157db96d56Sopenharmony_ci        return 0;
68167db96d56Sopenharmony_ci    }
68177db96d56Sopenharmony_ci
68187db96d56Sopenharmony_ci    PyErr_Format(PyExc_ValueError, "unsupported pickle protocol: %d", i);
68197db96d56Sopenharmony_ci    return -1;
68207db96d56Sopenharmony_ci}
68217db96d56Sopenharmony_ci
68227db96d56Sopenharmony_cistatic int
68237db96d56Sopenharmony_ciload_frame(UnpicklerObject *self)
68247db96d56Sopenharmony_ci{
68257db96d56Sopenharmony_ci    char *s;
68267db96d56Sopenharmony_ci    Py_ssize_t frame_len;
68277db96d56Sopenharmony_ci
68287db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, 8) < 0)
68297db96d56Sopenharmony_ci        return -1;
68307db96d56Sopenharmony_ci
68317db96d56Sopenharmony_ci    frame_len = calc_binsize(s, 8);
68327db96d56Sopenharmony_ci    if (frame_len < 0) {
68337db96d56Sopenharmony_ci        PyErr_Format(PyExc_OverflowError,
68347db96d56Sopenharmony_ci                     "FRAME length exceeds system's maximum of %zd bytes",
68357db96d56Sopenharmony_ci                     PY_SSIZE_T_MAX);
68367db96d56Sopenharmony_ci        return -1;
68377db96d56Sopenharmony_ci    }
68387db96d56Sopenharmony_ci
68397db96d56Sopenharmony_ci    if (_Unpickler_Read(self, &s, frame_len) < 0)
68407db96d56Sopenharmony_ci        return -1;
68417db96d56Sopenharmony_ci
68427db96d56Sopenharmony_ci    /* Rewind to start of frame */
68437db96d56Sopenharmony_ci    self->next_read_idx -= frame_len;
68447db96d56Sopenharmony_ci    return 0;
68457db96d56Sopenharmony_ci}
68467db96d56Sopenharmony_ci
68477db96d56Sopenharmony_cistatic PyObject *
68487db96d56Sopenharmony_ciload(UnpicklerObject *self)
68497db96d56Sopenharmony_ci{
68507db96d56Sopenharmony_ci    PyObject *value = NULL;
68517db96d56Sopenharmony_ci    char *s = NULL;
68527db96d56Sopenharmony_ci
68537db96d56Sopenharmony_ci    self->num_marks = 0;
68547db96d56Sopenharmony_ci    self->stack->mark_set = 0;
68557db96d56Sopenharmony_ci    self->stack->fence = 0;
68567db96d56Sopenharmony_ci    self->proto = 0;
68577db96d56Sopenharmony_ci    if (Py_SIZE(self->stack))
68587db96d56Sopenharmony_ci        Pdata_clear(self->stack, 0);
68597db96d56Sopenharmony_ci
68607db96d56Sopenharmony_ci    /* Convenient macros for the dispatch while-switch loop just below. */
68617db96d56Sopenharmony_ci#define OP(opcode, load_func) \
68627db96d56Sopenharmony_ci    case opcode: if (load_func(self) < 0) break; continue;
68637db96d56Sopenharmony_ci
68647db96d56Sopenharmony_ci#define OP_ARG(opcode, load_func, arg) \
68657db96d56Sopenharmony_ci    case opcode: if (load_func(self, (arg)) < 0) break; continue;
68667db96d56Sopenharmony_ci
68677db96d56Sopenharmony_ci    while (1) {
68687db96d56Sopenharmony_ci        if (_Unpickler_Read(self, &s, 1) < 0) {
68697db96d56Sopenharmony_ci            PickleState *st = _Pickle_GetGlobalState();
68707db96d56Sopenharmony_ci            if (PyErr_ExceptionMatches(st->UnpicklingError)) {
68717db96d56Sopenharmony_ci                PyErr_Format(PyExc_EOFError, "Ran out of input");
68727db96d56Sopenharmony_ci            }
68737db96d56Sopenharmony_ci            return NULL;
68747db96d56Sopenharmony_ci        }
68757db96d56Sopenharmony_ci
68767db96d56Sopenharmony_ci        switch ((enum opcode)s[0]) {
68777db96d56Sopenharmony_ci        OP(NONE, load_none)
68787db96d56Sopenharmony_ci        OP(BININT, load_binint)
68797db96d56Sopenharmony_ci        OP(BININT1, load_binint1)
68807db96d56Sopenharmony_ci        OP(BININT2, load_binint2)
68817db96d56Sopenharmony_ci        OP(INT, load_int)
68827db96d56Sopenharmony_ci        OP(LONG, load_long)
68837db96d56Sopenharmony_ci        OP_ARG(LONG1, load_counted_long, 1)
68847db96d56Sopenharmony_ci        OP_ARG(LONG4, load_counted_long, 4)
68857db96d56Sopenharmony_ci        OP(FLOAT, load_float)
68867db96d56Sopenharmony_ci        OP(BINFLOAT, load_binfloat)
68877db96d56Sopenharmony_ci        OP_ARG(SHORT_BINBYTES, load_counted_binbytes, 1)
68887db96d56Sopenharmony_ci        OP_ARG(BINBYTES, load_counted_binbytes, 4)
68897db96d56Sopenharmony_ci        OP_ARG(BINBYTES8, load_counted_binbytes, 8)
68907db96d56Sopenharmony_ci        OP(BYTEARRAY8, load_counted_bytearray)
68917db96d56Sopenharmony_ci        OP(NEXT_BUFFER, load_next_buffer)
68927db96d56Sopenharmony_ci        OP(READONLY_BUFFER, load_readonly_buffer)
68937db96d56Sopenharmony_ci        OP_ARG(SHORT_BINSTRING, load_counted_binstring, 1)
68947db96d56Sopenharmony_ci        OP_ARG(BINSTRING, load_counted_binstring, 4)
68957db96d56Sopenharmony_ci        OP(STRING, load_string)
68967db96d56Sopenharmony_ci        OP(UNICODE, load_unicode)
68977db96d56Sopenharmony_ci        OP_ARG(SHORT_BINUNICODE, load_counted_binunicode, 1)
68987db96d56Sopenharmony_ci        OP_ARG(BINUNICODE, load_counted_binunicode, 4)
68997db96d56Sopenharmony_ci        OP_ARG(BINUNICODE8, load_counted_binunicode, 8)
69007db96d56Sopenharmony_ci        OP_ARG(EMPTY_TUPLE, load_counted_tuple, 0)
69017db96d56Sopenharmony_ci        OP_ARG(TUPLE1, load_counted_tuple, 1)
69027db96d56Sopenharmony_ci        OP_ARG(TUPLE2, load_counted_tuple, 2)
69037db96d56Sopenharmony_ci        OP_ARG(TUPLE3, load_counted_tuple, 3)
69047db96d56Sopenharmony_ci        OP(TUPLE, load_tuple)
69057db96d56Sopenharmony_ci        OP(EMPTY_LIST, load_empty_list)
69067db96d56Sopenharmony_ci        OP(LIST, load_list)
69077db96d56Sopenharmony_ci        OP(EMPTY_DICT, load_empty_dict)
69087db96d56Sopenharmony_ci        OP(DICT, load_dict)
69097db96d56Sopenharmony_ci        OP(EMPTY_SET, load_empty_set)
69107db96d56Sopenharmony_ci        OP(ADDITEMS, load_additems)
69117db96d56Sopenharmony_ci        OP(FROZENSET, load_frozenset)
69127db96d56Sopenharmony_ci        OP(OBJ, load_obj)
69137db96d56Sopenharmony_ci        OP(INST, load_inst)
69147db96d56Sopenharmony_ci        OP_ARG(NEWOBJ, load_newobj, 0)
69157db96d56Sopenharmony_ci        OP_ARG(NEWOBJ_EX, load_newobj, 1)
69167db96d56Sopenharmony_ci        OP(GLOBAL, load_global)
69177db96d56Sopenharmony_ci        OP(STACK_GLOBAL, load_stack_global)
69187db96d56Sopenharmony_ci        OP(APPEND, load_append)
69197db96d56Sopenharmony_ci        OP(APPENDS, load_appends)
69207db96d56Sopenharmony_ci        OP(BUILD, load_build)
69217db96d56Sopenharmony_ci        OP(DUP, load_dup)
69227db96d56Sopenharmony_ci        OP(BINGET, load_binget)
69237db96d56Sopenharmony_ci        OP(LONG_BINGET, load_long_binget)
69247db96d56Sopenharmony_ci        OP(GET, load_get)
69257db96d56Sopenharmony_ci        OP(MARK, load_mark)
69267db96d56Sopenharmony_ci        OP(BINPUT, load_binput)
69277db96d56Sopenharmony_ci        OP(LONG_BINPUT, load_long_binput)
69287db96d56Sopenharmony_ci        OP(PUT, load_put)
69297db96d56Sopenharmony_ci        OP(MEMOIZE, load_memoize)
69307db96d56Sopenharmony_ci        OP(POP, load_pop)
69317db96d56Sopenharmony_ci        OP(POP_MARK, load_pop_mark)
69327db96d56Sopenharmony_ci        OP(SETITEM, load_setitem)
69337db96d56Sopenharmony_ci        OP(SETITEMS, load_setitems)
69347db96d56Sopenharmony_ci        OP(PERSID, load_persid)
69357db96d56Sopenharmony_ci        OP(BINPERSID, load_binpersid)
69367db96d56Sopenharmony_ci        OP(REDUCE, load_reduce)
69377db96d56Sopenharmony_ci        OP(PROTO, load_proto)
69387db96d56Sopenharmony_ci        OP(FRAME, load_frame)
69397db96d56Sopenharmony_ci        OP_ARG(EXT1, load_extension, 1)
69407db96d56Sopenharmony_ci        OP_ARG(EXT2, load_extension, 2)
69417db96d56Sopenharmony_ci        OP_ARG(EXT4, load_extension, 4)
69427db96d56Sopenharmony_ci        OP_ARG(NEWTRUE, load_bool, Py_True)
69437db96d56Sopenharmony_ci        OP_ARG(NEWFALSE, load_bool, Py_False)
69447db96d56Sopenharmony_ci
69457db96d56Sopenharmony_ci        case STOP:
69467db96d56Sopenharmony_ci            break;
69477db96d56Sopenharmony_ci
69487db96d56Sopenharmony_ci        default:
69497db96d56Sopenharmony_ci            {
69507db96d56Sopenharmony_ci                PickleState *st = _Pickle_GetGlobalState();
69517db96d56Sopenharmony_ci                unsigned char c = (unsigned char) *s;
69527db96d56Sopenharmony_ci                if (0x20 <= c && c <= 0x7e && c != '\'' && c != '\\') {
69537db96d56Sopenharmony_ci                    PyErr_Format(st->UnpicklingError,
69547db96d56Sopenharmony_ci                                 "invalid load key, '%c'.", c);
69557db96d56Sopenharmony_ci                }
69567db96d56Sopenharmony_ci                else {
69577db96d56Sopenharmony_ci                    PyErr_Format(st->UnpicklingError,
69587db96d56Sopenharmony_ci                                 "invalid load key, '\\x%02x'.", c);
69597db96d56Sopenharmony_ci                }
69607db96d56Sopenharmony_ci                return NULL;
69617db96d56Sopenharmony_ci            }
69627db96d56Sopenharmony_ci        }
69637db96d56Sopenharmony_ci
69647db96d56Sopenharmony_ci        break;                  /* and we are done! */
69657db96d56Sopenharmony_ci    }
69667db96d56Sopenharmony_ci
69677db96d56Sopenharmony_ci    if (PyErr_Occurred()) {
69687db96d56Sopenharmony_ci        return NULL;
69697db96d56Sopenharmony_ci    }
69707db96d56Sopenharmony_ci
69717db96d56Sopenharmony_ci    if (_Unpickler_SkipConsumed(self) < 0)
69727db96d56Sopenharmony_ci        return NULL;
69737db96d56Sopenharmony_ci
69747db96d56Sopenharmony_ci    PDATA_POP(self->stack, value);
69757db96d56Sopenharmony_ci    return value;
69767db96d56Sopenharmony_ci}
69777db96d56Sopenharmony_ci
69787db96d56Sopenharmony_ci/*[clinic input]
69797db96d56Sopenharmony_ci
69807db96d56Sopenharmony_ci_pickle.Unpickler.load
69817db96d56Sopenharmony_ci
69827db96d56Sopenharmony_ciLoad a pickle.
69837db96d56Sopenharmony_ci
69847db96d56Sopenharmony_ciRead a pickled object representation from the open file object given
69857db96d56Sopenharmony_ciin the constructor, and return the reconstituted object hierarchy
69867db96d56Sopenharmony_cispecified therein.
69877db96d56Sopenharmony_ci[clinic start generated code]*/
69887db96d56Sopenharmony_ci
69897db96d56Sopenharmony_cistatic PyObject *
69907db96d56Sopenharmony_ci_pickle_Unpickler_load_impl(UnpicklerObject *self)
69917db96d56Sopenharmony_ci/*[clinic end generated code: output=fdcc488aad675b14 input=acbb91a42fa9b7b9]*/
69927db96d56Sopenharmony_ci{
69937db96d56Sopenharmony_ci    UnpicklerObject *unpickler = (UnpicklerObject*)self;
69947db96d56Sopenharmony_ci
69957db96d56Sopenharmony_ci    /* Check whether the Unpickler was initialized correctly. This prevents
69967db96d56Sopenharmony_ci       segfaulting if a subclass overridden __init__ with a function that does
69977db96d56Sopenharmony_ci       not call Unpickler.__init__(). Here, we simply ensure that self->read
69987db96d56Sopenharmony_ci       is not NULL. */
69997db96d56Sopenharmony_ci    if (unpickler->read == NULL) {
70007db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
70017db96d56Sopenharmony_ci        PyErr_Format(st->UnpicklingError,
70027db96d56Sopenharmony_ci                     "Unpickler.__init__() was not called by %s.__init__()",
70037db96d56Sopenharmony_ci                     Py_TYPE(unpickler)->tp_name);
70047db96d56Sopenharmony_ci        return NULL;
70057db96d56Sopenharmony_ci    }
70067db96d56Sopenharmony_ci
70077db96d56Sopenharmony_ci    return load(unpickler);
70087db96d56Sopenharmony_ci}
70097db96d56Sopenharmony_ci
70107db96d56Sopenharmony_ci/* The name of find_class() is misleading. In newer pickle protocols, this
70117db96d56Sopenharmony_ci   function is used for loading any global (i.e., functions), not just
70127db96d56Sopenharmony_ci   classes. The name is kept only for backward compatibility. */
70137db96d56Sopenharmony_ci
70147db96d56Sopenharmony_ci/*[clinic input]
70157db96d56Sopenharmony_ci
70167db96d56Sopenharmony_ci_pickle.Unpickler.find_class
70177db96d56Sopenharmony_ci
70187db96d56Sopenharmony_ci  module_name: object
70197db96d56Sopenharmony_ci  global_name: object
70207db96d56Sopenharmony_ci  /
70217db96d56Sopenharmony_ci
70227db96d56Sopenharmony_ciReturn an object from a specified module.
70237db96d56Sopenharmony_ci
70247db96d56Sopenharmony_ciIf necessary, the module will be imported. Subclasses may override
70257db96d56Sopenharmony_cithis method (e.g. to restrict unpickling of arbitrary classes and
70267db96d56Sopenharmony_cifunctions).
70277db96d56Sopenharmony_ci
70287db96d56Sopenharmony_ciThis method is called whenever a class or a function object is
70297db96d56Sopenharmony_cineeded.  Both arguments passed are str objects.
70307db96d56Sopenharmony_ci[clinic start generated code]*/
70317db96d56Sopenharmony_ci
70327db96d56Sopenharmony_cistatic PyObject *
70337db96d56Sopenharmony_ci_pickle_Unpickler_find_class_impl(UnpicklerObject *self,
70347db96d56Sopenharmony_ci                                  PyObject *module_name,
70357db96d56Sopenharmony_ci                                  PyObject *global_name)
70367db96d56Sopenharmony_ci/*[clinic end generated code: output=becc08d7f9ed41e3 input=e2e6a865de093ef4]*/
70377db96d56Sopenharmony_ci{
70387db96d56Sopenharmony_ci    PyObject *global;
70397db96d56Sopenharmony_ci    PyObject *module;
70407db96d56Sopenharmony_ci
70417db96d56Sopenharmony_ci    if (PySys_Audit("pickle.find_class", "OO",
70427db96d56Sopenharmony_ci                    module_name, global_name) < 0) {
70437db96d56Sopenharmony_ci        return NULL;
70447db96d56Sopenharmony_ci    }
70457db96d56Sopenharmony_ci
70467db96d56Sopenharmony_ci    /* Try to map the old names used in Python 2.x to the new ones used in
70477db96d56Sopenharmony_ci       Python 3.x.  We do this only with old pickle protocols and when the
70487db96d56Sopenharmony_ci       user has not disabled the feature. */
70497db96d56Sopenharmony_ci    if (self->proto < 3 && self->fix_imports) {
70507db96d56Sopenharmony_ci        PyObject *key;
70517db96d56Sopenharmony_ci        PyObject *item;
70527db96d56Sopenharmony_ci        PickleState *st = _Pickle_GetGlobalState();
70537db96d56Sopenharmony_ci
70547db96d56Sopenharmony_ci        /* Check if the global (i.e., a function or a class) was renamed
70557db96d56Sopenharmony_ci           or moved to another module. */
70567db96d56Sopenharmony_ci        key = PyTuple_Pack(2, module_name, global_name);
70577db96d56Sopenharmony_ci        if (key == NULL)
70587db96d56Sopenharmony_ci            return NULL;
70597db96d56Sopenharmony_ci        item = PyDict_GetItemWithError(st->name_mapping_2to3, key);
70607db96d56Sopenharmony_ci        Py_DECREF(key);
70617db96d56Sopenharmony_ci        if (item) {
70627db96d56Sopenharmony_ci            if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) {
70637db96d56Sopenharmony_ci                PyErr_Format(PyExc_RuntimeError,
70647db96d56Sopenharmony_ci                             "_compat_pickle.NAME_MAPPING values should be "
70657db96d56Sopenharmony_ci                             "2-tuples, not %.200s", Py_TYPE(item)->tp_name);
70667db96d56Sopenharmony_ci                return NULL;
70677db96d56Sopenharmony_ci            }
70687db96d56Sopenharmony_ci            module_name = PyTuple_GET_ITEM(item, 0);
70697db96d56Sopenharmony_ci            global_name = PyTuple_GET_ITEM(item, 1);
70707db96d56Sopenharmony_ci            if (!PyUnicode_Check(module_name) ||
70717db96d56Sopenharmony_ci                !PyUnicode_Check(global_name)) {
70727db96d56Sopenharmony_ci                PyErr_Format(PyExc_RuntimeError,
70737db96d56Sopenharmony_ci                             "_compat_pickle.NAME_MAPPING values should be "
70747db96d56Sopenharmony_ci                             "pairs of str, not (%.200s, %.200s)",
70757db96d56Sopenharmony_ci                             Py_TYPE(module_name)->tp_name,
70767db96d56Sopenharmony_ci                             Py_TYPE(global_name)->tp_name);
70777db96d56Sopenharmony_ci                return NULL;
70787db96d56Sopenharmony_ci            }
70797db96d56Sopenharmony_ci        }
70807db96d56Sopenharmony_ci        else if (PyErr_Occurred()) {
70817db96d56Sopenharmony_ci            return NULL;
70827db96d56Sopenharmony_ci        }
70837db96d56Sopenharmony_ci        else {
70847db96d56Sopenharmony_ci            /* Check if the module was renamed. */
70857db96d56Sopenharmony_ci            item = PyDict_GetItemWithError(st->import_mapping_2to3, module_name);
70867db96d56Sopenharmony_ci            if (item) {
70877db96d56Sopenharmony_ci                if (!PyUnicode_Check(item)) {
70887db96d56Sopenharmony_ci                    PyErr_Format(PyExc_RuntimeError,
70897db96d56Sopenharmony_ci                                "_compat_pickle.IMPORT_MAPPING values should be "
70907db96d56Sopenharmony_ci                                "strings, not %.200s", Py_TYPE(item)->tp_name);
70917db96d56Sopenharmony_ci                    return NULL;
70927db96d56Sopenharmony_ci                }
70937db96d56Sopenharmony_ci                module_name = item;
70947db96d56Sopenharmony_ci            }
70957db96d56Sopenharmony_ci            else if (PyErr_Occurred()) {
70967db96d56Sopenharmony_ci                return NULL;
70977db96d56Sopenharmony_ci            }
70987db96d56Sopenharmony_ci        }
70997db96d56Sopenharmony_ci    }
71007db96d56Sopenharmony_ci
71017db96d56Sopenharmony_ci    /*
71027db96d56Sopenharmony_ci     * we don't use PyImport_GetModule here, because it can return partially-
71037db96d56Sopenharmony_ci     * initialised modules, which then cause the getattribute to fail.
71047db96d56Sopenharmony_ci     */
71057db96d56Sopenharmony_ci    module = PyImport_Import(module_name);
71067db96d56Sopenharmony_ci    if (module == NULL) {
71077db96d56Sopenharmony_ci        return NULL;
71087db96d56Sopenharmony_ci    }
71097db96d56Sopenharmony_ci    global = getattribute(module, global_name, self->proto >= 4);
71107db96d56Sopenharmony_ci    Py_DECREF(module);
71117db96d56Sopenharmony_ci    return global;
71127db96d56Sopenharmony_ci}
71137db96d56Sopenharmony_ci
71147db96d56Sopenharmony_ci/*[clinic input]
71157db96d56Sopenharmony_ci
71167db96d56Sopenharmony_ci_pickle.Unpickler.__sizeof__ -> Py_ssize_t
71177db96d56Sopenharmony_ci
71187db96d56Sopenharmony_ciReturns size in memory, in bytes.
71197db96d56Sopenharmony_ci[clinic start generated code]*/
71207db96d56Sopenharmony_ci
71217db96d56Sopenharmony_cistatic Py_ssize_t
71227db96d56Sopenharmony_ci_pickle_Unpickler___sizeof___impl(UnpicklerObject *self)
71237db96d56Sopenharmony_ci/*[clinic end generated code: output=119d9d03ad4c7651 input=13333471fdeedf5e]*/
71247db96d56Sopenharmony_ci{
71257db96d56Sopenharmony_ci    Py_ssize_t res;
71267db96d56Sopenharmony_ci
71277db96d56Sopenharmony_ci    res = _PyObject_SIZE(Py_TYPE(self));
71287db96d56Sopenharmony_ci    if (self->memo != NULL)
71297db96d56Sopenharmony_ci        res += self->memo_size * sizeof(PyObject *);
71307db96d56Sopenharmony_ci    if (self->marks != NULL)
71317db96d56Sopenharmony_ci        res += self->marks_size * sizeof(Py_ssize_t);
71327db96d56Sopenharmony_ci    if (self->input_line != NULL)
71337db96d56Sopenharmony_ci        res += strlen(self->input_line) + 1;
71347db96d56Sopenharmony_ci    if (self->encoding != NULL)
71357db96d56Sopenharmony_ci        res += strlen(self->encoding) + 1;
71367db96d56Sopenharmony_ci    if (self->errors != NULL)
71377db96d56Sopenharmony_ci        res += strlen(self->errors) + 1;
71387db96d56Sopenharmony_ci    return res;
71397db96d56Sopenharmony_ci}
71407db96d56Sopenharmony_ci
71417db96d56Sopenharmony_cistatic struct PyMethodDef Unpickler_methods[] = {
71427db96d56Sopenharmony_ci    _PICKLE_UNPICKLER_LOAD_METHODDEF
71437db96d56Sopenharmony_ci    _PICKLE_UNPICKLER_FIND_CLASS_METHODDEF
71447db96d56Sopenharmony_ci    _PICKLE_UNPICKLER___SIZEOF___METHODDEF
71457db96d56Sopenharmony_ci    {NULL, NULL}                /* sentinel */
71467db96d56Sopenharmony_ci};
71477db96d56Sopenharmony_ci
71487db96d56Sopenharmony_cistatic void
71497db96d56Sopenharmony_ciUnpickler_dealloc(UnpicklerObject *self)
71507db96d56Sopenharmony_ci{
71517db96d56Sopenharmony_ci    PyObject_GC_UnTrack((PyObject *)self);
71527db96d56Sopenharmony_ci    Py_XDECREF(self->readline);
71537db96d56Sopenharmony_ci    Py_XDECREF(self->readinto);
71547db96d56Sopenharmony_ci    Py_XDECREF(self->read);
71557db96d56Sopenharmony_ci    Py_XDECREF(self->peek);
71567db96d56Sopenharmony_ci    Py_XDECREF(self->stack);
71577db96d56Sopenharmony_ci    Py_XDECREF(self->pers_func);
71587db96d56Sopenharmony_ci    Py_XDECREF(self->buffers);
71597db96d56Sopenharmony_ci    if (self->buffer.buf != NULL) {
71607db96d56Sopenharmony_ci        PyBuffer_Release(&self->buffer);
71617db96d56Sopenharmony_ci        self->buffer.buf = NULL;
71627db96d56Sopenharmony_ci    }
71637db96d56Sopenharmony_ci
71647db96d56Sopenharmony_ci    _Unpickler_MemoCleanup(self);
71657db96d56Sopenharmony_ci    PyMem_Free(self->marks);
71667db96d56Sopenharmony_ci    PyMem_Free(self->input_line);
71677db96d56Sopenharmony_ci    PyMem_Free(self->encoding);
71687db96d56Sopenharmony_ci    PyMem_Free(self->errors);
71697db96d56Sopenharmony_ci
71707db96d56Sopenharmony_ci    Py_TYPE(self)->tp_free((PyObject *)self);
71717db96d56Sopenharmony_ci}
71727db96d56Sopenharmony_ci
71737db96d56Sopenharmony_cistatic int
71747db96d56Sopenharmony_ciUnpickler_traverse(UnpicklerObject *self, visitproc visit, void *arg)
71757db96d56Sopenharmony_ci{
71767db96d56Sopenharmony_ci    Py_VISIT(self->readline);
71777db96d56Sopenharmony_ci    Py_VISIT(self->readinto);
71787db96d56Sopenharmony_ci    Py_VISIT(self->read);
71797db96d56Sopenharmony_ci    Py_VISIT(self->peek);
71807db96d56Sopenharmony_ci    Py_VISIT(self->stack);
71817db96d56Sopenharmony_ci    Py_VISIT(self->pers_func);
71827db96d56Sopenharmony_ci    Py_VISIT(self->buffers);
71837db96d56Sopenharmony_ci    return 0;
71847db96d56Sopenharmony_ci}
71857db96d56Sopenharmony_ci
71867db96d56Sopenharmony_cistatic int
71877db96d56Sopenharmony_ciUnpickler_clear(UnpicklerObject *self)
71887db96d56Sopenharmony_ci{
71897db96d56Sopenharmony_ci    Py_CLEAR(self->readline);
71907db96d56Sopenharmony_ci    Py_CLEAR(self->readinto);
71917db96d56Sopenharmony_ci    Py_CLEAR(self->read);
71927db96d56Sopenharmony_ci    Py_CLEAR(self->peek);
71937db96d56Sopenharmony_ci    Py_CLEAR(self->stack);
71947db96d56Sopenharmony_ci    Py_CLEAR(self->pers_func);
71957db96d56Sopenharmony_ci    Py_CLEAR(self->buffers);
71967db96d56Sopenharmony_ci    if (self->buffer.buf != NULL) {
71977db96d56Sopenharmony_ci        PyBuffer_Release(&self->buffer);
71987db96d56Sopenharmony_ci        self->buffer.buf = NULL;
71997db96d56Sopenharmony_ci    }
72007db96d56Sopenharmony_ci
72017db96d56Sopenharmony_ci    _Unpickler_MemoCleanup(self);
72027db96d56Sopenharmony_ci    PyMem_Free(self->marks);
72037db96d56Sopenharmony_ci    self->marks = NULL;
72047db96d56Sopenharmony_ci    PyMem_Free(self->input_line);
72057db96d56Sopenharmony_ci    self->input_line = NULL;
72067db96d56Sopenharmony_ci    PyMem_Free(self->encoding);
72077db96d56Sopenharmony_ci    self->encoding = NULL;
72087db96d56Sopenharmony_ci    PyMem_Free(self->errors);
72097db96d56Sopenharmony_ci    self->errors = NULL;
72107db96d56Sopenharmony_ci
72117db96d56Sopenharmony_ci    return 0;
72127db96d56Sopenharmony_ci}
72137db96d56Sopenharmony_ci
72147db96d56Sopenharmony_ci/*[clinic input]
72157db96d56Sopenharmony_ci
72167db96d56Sopenharmony_ci_pickle.Unpickler.__init__
72177db96d56Sopenharmony_ci
72187db96d56Sopenharmony_ci  file: object
72197db96d56Sopenharmony_ci  *
72207db96d56Sopenharmony_ci  fix_imports: bool = True
72217db96d56Sopenharmony_ci  encoding: str = 'ASCII'
72227db96d56Sopenharmony_ci  errors: str = 'strict'
72237db96d56Sopenharmony_ci  buffers: object(c_default="NULL") = ()
72247db96d56Sopenharmony_ci
72257db96d56Sopenharmony_ciThis takes a binary file for reading a pickle data stream.
72267db96d56Sopenharmony_ci
72277db96d56Sopenharmony_ciThe protocol version of the pickle is detected automatically, so no
72287db96d56Sopenharmony_ciprotocol argument is needed.  Bytes past the pickled object's
72297db96d56Sopenharmony_cirepresentation are ignored.
72307db96d56Sopenharmony_ci
72317db96d56Sopenharmony_ciThe argument *file* must have two methods, a read() method that takes
72327db96d56Sopenharmony_cian integer argument, and a readline() method that requires no
72337db96d56Sopenharmony_ciarguments.  Both methods should return bytes.  Thus *file* can be a
72347db96d56Sopenharmony_cibinary file object opened for reading, an io.BytesIO object, or any
72357db96d56Sopenharmony_ciother custom object that meets this interface.
72367db96d56Sopenharmony_ci
72377db96d56Sopenharmony_ciOptional keyword arguments are *fix_imports*, *encoding* and *errors*,
72387db96d56Sopenharmony_ciwhich are used to control compatibility support for pickle stream
72397db96d56Sopenharmony_cigenerated by Python 2.  If *fix_imports* is True, pickle will try to
72407db96d56Sopenharmony_cimap the old Python 2 names to the new names used in Python 3.  The
72417db96d56Sopenharmony_ci*encoding* and *errors* tell pickle how to decode 8-bit string
72427db96d56Sopenharmony_ciinstances pickled by Python 2; these default to 'ASCII' and 'strict',
72437db96d56Sopenharmony_cirespectively.  The *encoding* can be 'bytes' to read these 8-bit
72447db96d56Sopenharmony_cistring instances as bytes objects.
72457db96d56Sopenharmony_ci[clinic start generated code]*/
72467db96d56Sopenharmony_ci
72477db96d56Sopenharmony_cistatic int
72487db96d56Sopenharmony_ci_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file,
72497db96d56Sopenharmony_ci                                int fix_imports, const char *encoding,
72507db96d56Sopenharmony_ci                                const char *errors, PyObject *buffers)
72517db96d56Sopenharmony_ci/*[clinic end generated code: output=09f0192649ea3f85 input=ca4c1faea9553121]*/
72527db96d56Sopenharmony_ci{
72537db96d56Sopenharmony_ci    /* In case of multiple __init__() calls, clear previous content. */
72547db96d56Sopenharmony_ci    if (self->read != NULL)
72557db96d56Sopenharmony_ci        (void)Unpickler_clear(self);
72567db96d56Sopenharmony_ci
72577db96d56Sopenharmony_ci    if (_Unpickler_SetInputStream(self, file) < 0)
72587db96d56Sopenharmony_ci        return -1;
72597db96d56Sopenharmony_ci
72607db96d56Sopenharmony_ci    if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0)
72617db96d56Sopenharmony_ci        return -1;
72627db96d56Sopenharmony_ci
72637db96d56Sopenharmony_ci    if (_Unpickler_SetBuffers(self, buffers) < 0)
72647db96d56Sopenharmony_ci        return -1;
72657db96d56Sopenharmony_ci
72667db96d56Sopenharmony_ci    self->fix_imports = fix_imports;
72677db96d56Sopenharmony_ci
72687db96d56Sopenharmony_ci    if (init_method_ref((PyObject *)self, &_Py_ID(persistent_load),
72697db96d56Sopenharmony_ci                        &self->pers_func, &self->pers_func_self) < 0)
72707db96d56Sopenharmony_ci    {
72717db96d56Sopenharmony_ci        return -1;
72727db96d56Sopenharmony_ci    }
72737db96d56Sopenharmony_ci
72747db96d56Sopenharmony_ci    self->stack = (Pdata *)Pdata_New();
72757db96d56Sopenharmony_ci    if (self->stack == NULL)
72767db96d56Sopenharmony_ci        return -1;
72777db96d56Sopenharmony_ci
72787db96d56Sopenharmony_ci    self->memo_size = 32;
72797db96d56Sopenharmony_ci    self->memo = _Unpickler_NewMemo(self->memo_size);
72807db96d56Sopenharmony_ci    if (self->memo == NULL)
72817db96d56Sopenharmony_ci        return -1;
72827db96d56Sopenharmony_ci
72837db96d56Sopenharmony_ci    self->proto = 0;
72847db96d56Sopenharmony_ci
72857db96d56Sopenharmony_ci    return 0;
72867db96d56Sopenharmony_ci}
72877db96d56Sopenharmony_ci
72887db96d56Sopenharmony_ci
72897db96d56Sopenharmony_ci/* Define a proxy object for the Unpickler's internal memo object. This is to
72907db96d56Sopenharmony_ci * avoid breaking code like:
72917db96d56Sopenharmony_ci *  unpickler.memo.clear()
72927db96d56Sopenharmony_ci * and
72937db96d56Sopenharmony_ci *  unpickler.memo = saved_memo
72947db96d56Sopenharmony_ci * Is this a good idea? Not really, but we don't want to break code that uses
72957db96d56Sopenharmony_ci * it. Note that we don't implement the entire mapping API here. This is
72967db96d56Sopenharmony_ci * intentional, as these should be treated as black-box implementation details.
72977db96d56Sopenharmony_ci *
72987db96d56Sopenharmony_ci * We do, however, have to implement pickling/unpickling support because of
72997db96d56Sopenharmony_ci * real-world code like cvs2svn.
73007db96d56Sopenharmony_ci */
73017db96d56Sopenharmony_ci
73027db96d56Sopenharmony_ci/*[clinic input]
73037db96d56Sopenharmony_ci_pickle.UnpicklerMemoProxy.clear
73047db96d56Sopenharmony_ci
73057db96d56Sopenharmony_ciRemove all items from memo.
73067db96d56Sopenharmony_ci[clinic start generated code]*/
73077db96d56Sopenharmony_ci
73087db96d56Sopenharmony_cistatic PyObject *
73097db96d56Sopenharmony_ci_pickle_UnpicklerMemoProxy_clear_impl(UnpicklerMemoProxyObject *self)
73107db96d56Sopenharmony_ci/*[clinic end generated code: output=d20cd43f4ba1fb1f input=b1df7c52e7afd9bd]*/
73117db96d56Sopenharmony_ci{
73127db96d56Sopenharmony_ci    _Unpickler_MemoCleanup(self->unpickler);
73137db96d56Sopenharmony_ci    self->unpickler->memo = _Unpickler_NewMemo(self->unpickler->memo_size);
73147db96d56Sopenharmony_ci    if (self->unpickler->memo == NULL)
73157db96d56Sopenharmony_ci        return NULL;
73167db96d56Sopenharmony_ci    Py_RETURN_NONE;
73177db96d56Sopenharmony_ci}
73187db96d56Sopenharmony_ci
73197db96d56Sopenharmony_ci/*[clinic input]
73207db96d56Sopenharmony_ci_pickle.UnpicklerMemoProxy.copy
73217db96d56Sopenharmony_ci
73227db96d56Sopenharmony_ciCopy the memo to a new object.
73237db96d56Sopenharmony_ci[clinic start generated code]*/
73247db96d56Sopenharmony_ci
73257db96d56Sopenharmony_cistatic PyObject *
73267db96d56Sopenharmony_ci_pickle_UnpicklerMemoProxy_copy_impl(UnpicklerMemoProxyObject *self)
73277db96d56Sopenharmony_ci/*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
73287db96d56Sopenharmony_ci{
73297db96d56Sopenharmony_ci    size_t i;
73307db96d56Sopenharmony_ci    PyObject *new_memo = PyDict_New();
73317db96d56Sopenharmony_ci    if (new_memo == NULL)
73327db96d56Sopenharmony_ci        return NULL;
73337db96d56Sopenharmony_ci
73347db96d56Sopenharmony_ci    for (i = 0; i < self->unpickler->memo_size; i++) {
73357db96d56Sopenharmony_ci        int status;
73367db96d56Sopenharmony_ci        PyObject *key, *value;
73377db96d56Sopenharmony_ci
73387db96d56Sopenharmony_ci        value = self->unpickler->memo[i];
73397db96d56Sopenharmony_ci        if (value == NULL)
73407db96d56Sopenharmony_ci            continue;
73417db96d56Sopenharmony_ci
73427db96d56Sopenharmony_ci        key = PyLong_FromSsize_t(i);
73437db96d56Sopenharmony_ci        if (key == NULL)
73447db96d56Sopenharmony_ci            goto error;
73457db96d56Sopenharmony_ci        status = PyDict_SetItem(new_memo, key, value);
73467db96d56Sopenharmony_ci        Py_DECREF(key);
73477db96d56Sopenharmony_ci        if (status < 0)
73487db96d56Sopenharmony_ci            goto error;
73497db96d56Sopenharmony_ci    }
73507db96d56Sopenharmony_ci    return new_memo;
73517db96d56Sopenharmony_ci
73527db96d56Sopenharmony_cierror:
73537db96d56Sopenharmony_ci    Py_DECREF(new_memo);
73547db96d56Sopenharmony_ci    return NULL;
73557db96d56Sopenharmony_ci}
73567db96d56Sopenharmony_ci
73577db96d56Sopenharmony_ci/*[clinic input]
73587db96d56Sopenharmony_ci_pickle.UnpicklerMemoProxy.__reduce__
73597db96d56Sopenharmony_ci
73607db96d56Sopenharmony_ciImplement pickling support.
73617db96d56Sopenharmony_ci[clinic start generated code]*/
73627db96d56Sopenharmony_ci
73637db96d56Sopenharmony_cistatic PyObject *
73647db96d56Sopenharmony_ci_pickle_UnpicklerMemoProxy___reduce___impl(UnpicklerMemoProxyObject *self)
73657db96d56Sopenharmony_ci/*[clinic end generated code: output=6da34ac048d94cca input=6920862413407199]*/
73667db96d56Sopenharmony_ci{
73677db96d56Sopenharmony_ci    PyObject *reduce_value;
73687db96d56Sopenharmony_ci    PyObject *constructor_args;
73697db96d56Sopenharmony_ci    PyObject *contents = _pickle_UnpicklerMemoProxy_copy_impl(self);
73707db96d56Sopenharmony_ci    if (contents == NULL)
73717db96d56Sopenharmony_ci        return NULL;
73727db96d56Sopenharmony_ci
73737db96d56Sopenharmony_ci    reduce_value = PyTuple_New(2);
73747db96d56Sopenharmony_ci    if (reduce_value == NULL) {
73757db96d56Sopenharmony_ci        Py_DECREF(contents);
73767db96d56Sopenharmony_ci        return NULL;
73777db96d56Sopenharmony_ci    }
73787db96d56Sopenharmony_ci    constructor_args = PyTuple_New(1);
73797db96d56Sopenharmony_ci    if (constructor_args == NULL) {
73807db96d56Sopenharmony_ci        Py_DECREF(contents);
73817db96d56Sopenharmony_ci        Py_DECREF(reduce_value);
73827db96d56Sopenharmony_ci        return NULL;
73837db96d56Sopenharmony_ci    }
73847db96d56Sopenharmony_ci    PyTuple_SET_ITEM(constructor_args, 0, contents);
73857db96d56Sopenharmony_ci    Py_INCREF((PyObject *)&PyDict_Type);
73867db96d56Sopenharmony_ci    PyTuple_SET_ITEM(reduce_value, 0, (PyObject *)&PyDict_Type);
73877db96d56Sopenharmony_ci    PyTuple_SET_ITEM(reduce_value, 1, constructor_args);
73887db96d56Sopenharmony_ci    return reduce_value;
73897db96d56Sopenharmony_ci}
73907db96d56Sopenharmony_ci
73917db96d56Sopenharmony_cistatic PyMethodDef unpicklerproxy_methods[] = {
73927db96d56Sopenharmony_ci    _PICKLE_UNPICKLERMEMOPROXY_CLEAR_METHODDEF
73937db96d56Sopenharmony_ci    _PICKLE_UNPICKLERMEMOPROXY_COPY_METHODDEF
73947db96d56Sopenharmony_ci    _PICKLE_UNPICKLERMEMOPROXY___REDUCE___METHODDEF
73957db96d56Sopenharmony_ci    {NULL, NULL}    /* sentinel */
73967db96d56Sopenharmony_ci};
73977db96d56Sopenharmony_ci
73987db96d56Sopenharmony_cistatic void
73997db96d56Sopenharmony_ciUnpicklerMemoProxy_dealloc(UnpicklerMemoProxyObject *self)
74007db96d56Sopenharmony_ci{
74017db96d56Sopenharmony_ci    PyObject_GC_UnTrack(self);
74027db96d56Sopenharmony_ci    Py_XDECREF(self->unpickler);
74037db96d56Sopenharmony_ci    PyObject_GC_Del((PyObject *)self);
74047db96d56Sopenharmony_ci}
74057db96d56Sopenharmony_ci
74067db96d56Sopenharmony_cistatic int
74077db96d56Sopenharmony_ciUnpicklerMemoProxy_traverse(UnpicklerMemoProxyObject *self,
74087db96d56Sopenharmony_ci                            visitproc visit, void *arg)
74097db96d56Sopenharmony_ci{
74107db96d56Sopenharmony_ci    Py_VISIT(self->unpickler);
74117db96d56Sopenharmony_ci    return 0;
74127db96d56Sopenharmony_ci}
74137db96d56Sopenharmony_ci
74147db96d56Sopenharmony_cistatic int
74157db96d56Sopenharmony_ciUnpicklerMemoProxy_clear(UnpicklerMemoProxyObject *self)
74167db96d56Sopenharmony_ci{
74177db96d56Sopenharmony_ci    Py_CLEAR(self->unpickler);
74187db96d56Sopenharmony_ci    return 0;
74197db96d56Sopenharmony_ci}
74207db96d56Sopenharmony_ci
74217db96d56Sopenharmony_cistatic PyTypeObject UnpicklerMemoProxyType = {
74227db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(NULL, 0)
74237db96d56Sopenharmony_ci    "_pickle.UnpicklerMemoProxy",               /*tp_name*/
74247db96d56Sopenharmony_ci    sizeof(UnpicklerMemoProxyObject),           /*tp_basicsize*/
74257db96d56Sopenharmony_ci    0,
74267db96d56Sopenharmony_ci    (destructor)UnpicklerMemoProxy_dealloc,     /* tp_dealloc */
74277db96d56Sopenharmony_ci    0,                                          /* tp_vectorcall_offset */
74287db96d56Sopenharmony_ci    0,                                          /* tp_getattr */
74297db96d56Sopenharmony_ci    0,                                          /* tp_setattr */
74307db96d56Sopenharmony_ci    0,                                          /* tp_as_async */
74317db96d56Sopenharmony_ci    0,                                          /* tp_repr */
74327db96d56Sopenharmony_ci    0,                                          /* tp_as_number */
74337db96d56Sopenharmony_ci    0,                                          /* tp_as_sequence */
74347db96d56Sopenharmony_ci    0,                                          /* tp_as_mapping */
74357db96d56Sopenharmony_ci    PyObject_HashNotImplemented,                /* tp_hash */
74367db96d56Sopenharmony_ci    0,                                          /* tp_call */
74377db96d56Sopenharmony_ci    0,                                          /* tp_str */
74387db96d56Sopenharmony_ci    PyObject_GenericGetAttr,                    /* tp_getattro */
74397db96d56Sopenharmony_ci    PyObject_GenericSetAttr,                    /* tp_setattro */
74407db96d56Sopenharmony_ci    0,                                          /* tp_as_buffer */
74417db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
74427db96d56Sopenharmony_ci    0,                                          /* tp_doc */
74437db96d56Sopenharmony_ci    (traverseproc)UnpicklerMemoProxy_traverse,  /* tp_traverse */
74447db96d56Sopenharmony_ci    (inquiry)UnpicklerMemoProxy_clear,          /* tp_clear */
74457db96d56Sopenharmony_ci    0,                                          /* tp_richcompare */
74467db96d56Sopenharmony_ci    0,                                          /* tp_weaklistoffset */
74477db96d56Sopenharmony_ci    0,                                          /* tp_iter */
74487db96d56Sopenharmony_ci    0,                                          /* tp_iternext */
74497db96d56Sopenharmony_ci    unpicklerproxy_methods,                     /* tp_methods */
74507db96d56Sopenharmony_ci};
74517db96d56Sopenharmony_ci
74527db96d56Sopenharmony_cistatic PyObject *
74537db96d56Sopenharmony_ciUnpicklerMemoProxy_New(UnpicklerObject *unpickler)
74547db96d56Sopenharmony_ci{
74557db96d56Sopenharmony_ci    UnpicklerMemoProxyObject *self;
74567db96d56Sopenharmony_ci
74577db96d56Sopenharmony_ci    self = PyObject_GC_New(UnpicklerMemoProxyObject,
74587db96d56Sopenharmony_ci                           &UnpicklerMemoProxyType);
74597db96d56Sopenharmony_ci    if (self == NULL)
74607db96d56Sopenharmony_ci        return NULL;
74617db96d56Sopenharmony_ci    Py_INCREF(unpickler);
74627db96d56Sopenharmony_ci    self->unpickler = unpickler;
74637db96d56Sopenharmony_ci    PyObject_GC_Track(self);
74647db96d56Sopenharmony_ci    return (PyObject *)self;
74657db96d56Sopenharmony_ci}
74667db96d56Sopenharmony_ci
74677db96d56Sopenharmony_ci/*****************************************************************************/
74687db96d56Sopenharmony_ci
74697db96d56Sopenharmony_ci
74707db96d56Sopenharmony_cistatic PyObject *
74717db96d56Sopenharmony_ciUnpickler_get_memo(UnpicklerObject *self, void *Py_UNUSED(ignored))
74727db96d56Sopenharmony_ci{
74737db96d56Sopenharmony_ci    return UnpicklerMemoProxy_New(self);
74747db96d56Sopenharmony_ci}
74757db96d56Sopenharmony_ci
74767db96d56Sopenharmony_cistatic int
74777db96d56Sopenharmony_ciUnpickler_set_memo(UnpicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored))
74787db96d56Sopenharmony_ci{
74797db96d56Sopenharmony_ci    PyObject **new_memo;
74807db96d56Sopenharmony_ci    size_t new_memo_size = 0;
74817db96d56Sopenharmony_ci
74827db96d56Sopenharmony_ci    if (obj == NULL) {
74837db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError,
74847db96d56Sopenharmony_ci                        "attribute deletion is not supported");
74857db96d56Sopenharmony_ci        return -1;
74867db96d56Sopenharmony_ci    }
74877db96d56Sopenharmony_ci
74887db96d56Sopenharmony_ci    if (Py_IS_TYPE(obj, &UnpicklerMemoProxyType)) {
74897db96d56Sopenharmony_ci        UnpicklerObject *unpickler =
74907db96d56Sopenharmony_ci            ((UnpicklerMemoProxyObject *)obj)->unpickler;
74917db96d56Sopenharmony_ci
74927db96d56Sopenharmony_ci        new_memo_size = unpickler->memo_size;
74937db96d56Sopenharmony_ci        new_memo = _Unpickler_NewMemo(new_memo_size);
74947db96d56Sopenharmony_ci        if (new_memo == NULL)
74957db96d56Sopenharmony_ci            return -1;
74967db96d56Sopenharmony_ci
74977db96d56Sopenharmony_ci        for (size_t i = 0; i < new_memo_size; i++) {
74987db96d56Sopenharmony_ci            Py_XINCREF(unpickler->memo[i]);
74997db96d56Sopenharmony_ci            new_memo[i] = unpickler->memo[i];
75007db96d56Sopenharmony_ci        }
75017db96d56Sopenharmony_ci    }
75027db96d56Sopenharmony_ci    else if (PyDict_Check(obj)) {
75037db96d56Sopenharmony_ci        Py_ssize_t i = 0;
75047db96d56Sopenharmony_ci        PyObject *key, *value;
75057db96d56Sopenharmony_ci
75067db96d56Sopenharmony_ci        new_memo_size = PyDict_GET_SIZE(obj);
75077db96d56Sopenharmony_ci        new_memo = _Unpickler_NewMemo(new_memo_size);
75087db96d56Sopenharmony_ci        if (new_memo == NULL)
75097db96d56Sopenharmony_ci            return -1;
75107db96d56Sopenharmony_ci
75117db96d56Sopenharmony_ci        while (PyDict_Next(obj, &i, &key, &value)) {
75127db96d56Sopenharmony_ci            Py_ssize_t idx;
75137db96d56Sopenharmony_ci            if (!PyLong_Check(key)) {
75147db96d56Sopenharmony_ci                PyErr_SetString(PyExc_TypeError,
75157db96d56Sopenharmony_ci                                "memo key must be integers");
75167db96d56Sopenharmony_ci                goto error;
75177db96d56Sopenharmony_ci            }
75187db96d56Sopenharmony_ci            idx = PyLong_AsSsize_t(key);
75197db96d56Sopenharmony_ci            if (idx == -1 && PyErr_Occurred())
75207db96d56Sopenharmony_ci                goto error;
75217db96d56Sopenharmony_ci            if (idx < 0) {
75227db96d56Sopenharmony_ci                PyErr_SetString(PyExc_ValueError,
75237db96d56Sopenharmony_ci                                "memo key must be positive integers.");
75247db96d56Sopenharmony_ci                goto error;
75257db96d56Sopenharmony_ci            }
75267db96d56Sopenharmony_ci            if (_Unpickler_MemoPut(self, idx, value) < 0)
75277db96d56Sopenharmony_ci                goto error;
75287db96d56Sopenharmony_ci        }
75297db96d56Sopenharmony_ci    }
75307db96d56Sopenharmony_ci    else {
75317db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
75327db96d56Sopenharmony_ci                     "'memo' attribute must be an UnpicklerMemoProxy object "
75337db96d56Sopenharmony_ci                     "or dict, not %.200s", Py_TYPE(obj)->tp_name);
75347db96d56Sopenharmony_ci        return -1;
75357db96d56Sopenharmony_ci    }
75367db96d56Sopenharmony_ci
75377db96d56Sopenharmony_ci    _Unpickler_MemoCleanup(self);
75387db96d56Sopenharmony_ci    self->memo_size = new_memo_size;
75397db96d56Sopenharmony_ci    self->memo = new_memo;
75407db96d56Sopenharmony_ci
75417db96d56Sopenharmony_ci    return 0;
75427db96d56Sopenharmony_ci
75437db96d56Sopenharmony_ci  error:
75447db96d56Sopenharmony_ci    if (new_memo_size) {
75457db96d56Sopenharmony_ci        for (size_t i = new_memo_size - 1; i != SIZE_MAX; i--) {
75467db96d56Sopenharmony_ci            Py_XDECREF(new_memo[i]);
75477db96d56Sopenharmony_ci        }
75487db96d56Sopenharmony_ci        PyMem_Free(new_memo);
75497db96d56Sopenharmony_ci    }
75507db96d56Sopenharmony_ci    return -1;
75517db96d56Sopenharmony_ci}
75527db96d56Sopenharmony_ci
75537db96d56Sopenharmony_cistatic PyObject *
75547db96d56Sopenharmony_ciUnpickler_get_persload(UnpicklerObject *self, void *Py_UNUSED(ignored))
75557db96d56Sopenharmony_ci{
75567db96d56Sopenharmony_ci    if (self->pers_func == NULL) {
75577db96d56Sopenharmony_ci        PyErr_SetString(PyExc_AttributeError, "persistent_load");
75587db96d56Sopenharmony_ci        return NULL;
75597db96d56Sopenharmony_ci    }
75607db96d56Sopenharmony_ci    return reconstruct_method(self->pers_func, self->pers_func_self);
75617db96d56Sopenharmony_ci}
75627db96d56Sopenharmony_ci
75637db96d56Sopenharmony_cistatic int
75647db96d56Sopenharmony_ciUnpickler_set_persload(UnpicklerObject *self, PyObject *value, void *Py_UNUSED(ignored))
75657db96d56Sopenharmony_ci{
75667db96d56Sopenharmony_ci    if (value == NULL) {
75677db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError,
75687db96d56Sopenharmony_ci                        "attribute deletion is not supported");
75697db96d56Sopenharmony_ci        return -1;
75707db96d56Sopenharmony_ci    }
75717db96d56Sopenharmony_ci    if (!PyCallable_Check(value)) {
75727db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError,
75737db96d56Sopenharmony_ci                        "persistent_load must be a callable taking "
75747db96d56Sopenharmony_ci                        "one argument");
75757db96d56Sopenharmony_ci        return -1;
75767db96d56Sopenharmony_ci    }
75777db96d56Sopenharmony_ci
75787db96d56Sopenharmony_ci    self->pers_func_self = NULL;
75797db96d56Sopenharmony_ci    Py_INCREF(value);
75807db96d56Sopenharmony_ci    Py_XSETREF(self->pers_func, value);
75817db96d56Sopenharmony_ci
75827db96d56Sopenharmony_ci    return 0;
75837db96d56Sopenharmony_ci}
75847db96d56Sopenharmony_ci
75857db96d56Sopenharmony_cistatic PyGetSetDef Unpickler_getsets[] = {
75867db96d56Sopenharmony_ci    {"memo", (getter)Unpickler_get_memo, (setter)Unpickler_set_memo},
75877db96d56Sopenharmony_ci    {"persistent_load", (getter)Unpickler_get_persload,
75887db96d56Sopenharmony_ci                        (setter)Unpickler_set_persload},
75897db96d56Sopenharmony_ci    {NULL}
75907db96d56Sopenharmony_ci};
75917db96d56Sopenharmony_ci
75927db96d56Sopenharmony_cistatic PyTypeObject Unpickler_Type = {
75937db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(NULL, 0)
75947db96d56Sopenharmony_ci    "_pickle.Unpickler",                /*tp_name*/
75957db96d56Sopenharmony_ci    sizeof(UnpicklerObject),            /*tp_basicsize*/
75967db96d56Sopenharmony_ci    0,                                  /*tp_itemsize*/
75977db96d56Sopenharmony_ci    (destructor)Unpickler_dealloc,      /*tp_dealloc*/
75987db96d56Sopenharmony_ci    0,                                  /*tp_vectorcall_offset*/
75997db96d56Sopenharmony_ci    0,                                  /*tp_getattr*/
76007db96d56Sopenharmony_ci    0,                                  /*tp_setattr*/
76017db96d56Sopenharmony_ci    0,                                  /*tp_as_async*/
76027db96d56Sopenharmony_ci    0,                                  /*tp_repr*/
76037db96d56Sopenharmony_ci    0,                                  /*tp_as_number*/
76047db96d56Sopenharmony_ci    0,                                  /*tp_as_sequence*/
76057db96d56Sopenharmony_ci    0,                                  /*tp_as_mapping*/
76067db96d56Sopenharmony_ci    0,                                  /*tp_hash*/
76077db96d56Sopenharmony_ci    0,                                  /*tp_call*/
76087db96d56Sopenharmony_ci    0,                                  /*tp_str*/
76097db96d56Sopenharmony_ci    0,                                  /*tp_getattro*/
76107db96d56Sopenharmony_ci    0,                                  /*tp_setattro*/
76117db96d56Sopenharmony_ci    0,                                  /*tp_as_buffer*/
76127db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
76137db96d56Sopenharmony_ci    _pickle_Unpickler___init____doc__,  /*tp_doc*/
76147db96d56Sopenharmony_ci    (traverseproc)Unpickler_traverse,   /*tp_traverse*/
76157db96d56Sopenharmony_ci    (inquiry)Unpickler_clear,           /*tp_clear*/
76167db96d56Sopenharmony_ci    0,                                  /*tp_richcompare*/
76177db96d56Sopenharmony_ci    0,                                  /*tp_weaklistoffset*/
76187db96d56Sopenharmony_ci    0,                                  /*tp_iter*/
76197db96d56Sopenharmony_ci    0,                                  /*tp_iternext*/
76207db96d56Sopenharmony_ci    Unpickler_methods,                  /*tp_methods*/
76217db96d56Sopenharmony_ci    0,                                  /*tp_members*/
76227db96d56Sopenharmony_ci    Unpickler_getsets,                  /*tp_getset*/
76237db96d56Sopenharmony_ci    0,                                  /*tp_base*/
76247db96d56Sopenharmony_ci    0,                                  /*tp_dict*/
76257db96d56Sopenharmony_ci    0,                                  /*tp_descr_get*/
76267db96d56Sopenharmony_ci    0,                                  /*tp_descr_set*/
76277db96d56Sopenharmony_ci    0,                                  /*tp_dictoffset*/
76287db96d56Sopenharmony_ci    _pickle_Unpickler___init__,         /*tp_init*/
76297db96d56Sopenharmony_ci    PyType_GenericAlloc,                /*tp_alloc*/
76307db96d56Sopenharmony_ci    PyType_GenericNew,                  /*tp_new*/
76317db96d56Sopenharmony_ci    PyObject_GC_Del,                    /*tp_free*/
76327db96d56Sopenharmony_ci    0,                                  /*tp_is_gc*/
76337db96d56Sopenharmony_ci};
76347db96d56Sopenharmony_ci
76357db96d56Sopenharmony_ci/*[clinic input]
76367db96d56Sopenharmony_ci
76377db96d56Sopenharmony_ci_pickle.dump
76387db96d56Sopenharmony_ci
76397db96d56Sopenharmony_ci  obj: object
76407db96d56Sopenharmony_ci  file: object
76417db96d56Sopenharmony_ci  protocol: object = None
76427db96d56Sopenharmony_ci  *
76437db96d56Sopenharmony_ci  fix_imports: bool = True
76447db96d56Sopenharmony_ci  buffer_callback: object = None
76457db96d56Sopenharmony_ci
76467db96d56Sopenharmony_ciWrite a pickled representation of obj to the open file object file.
76477db96d56Sopenharmony_ci
76487db96d56Sopenharmony_ciThis is equivalent to ``Pickler(file, protocol).dump(obj)``, but may
76497db96d56Sopenharmony_cibe more efficient.
76507db96d56Sopenharmony_ci
76517db96d56Sopenharmony_ciThe optional *protocol* argument tells the pickler to use the given
76527db96d56Sopenharmony_ciprotocol; supported protocols are 0, 1, 2, 3, 4 and 5.  The default
76537db96d56Sopenharmony_ciprotocol is 4. It was introduced in Python 3.4, and is incompatible
76547db96d56Sopenharmony_ciwith previous versions.
76557db96d56Sopenharmony_ci
76567db96d56Sopenharmony_ciSpecifying a negative protocol version selects the highest protocol
76577db96d56Sopenharmony_civersion supported.  The higher the protocol used, the more recent the
76587db96d56Sopenharmony_civersion of Python needed to read the pickle produced.
76597db96d56Sopenharmony_ci
76607db96d56Sopenharmony_ciThe *file* argument must have a write() method that accepts a single
76617db96d56Sopenharmony_cibytes argument.  It can thus be a file object opened for binary
76627db96d56Sopenharmony_ciwriting, an io.BytesIO instance, or any other custom object that meets
76637db96d56Sopenharmony_cithis interface.
76647db96d56Sopenharmony_ci
76657db96d56Sopenharmony_ciIf *fix_imports* is True and protocol is less than 3, pickle will try
76667db96d56Sopenharmony_cito map the new Python 3 names to the old module names used in Python
76677db96d56Sopenharmony_ci2, so that the pickle data stream is readable with Python 2.
76687db96d56Sopenharmony_ci
76697db96d56Sopenharmony_ciIf *buffer_callback* is None (the default), buffer views are serialized
76707db96d56Sopenharmony_ciinto *file* as part of the pickle stream.  It is an error if
76717db96d56Sopenharmony_ci*buffer_callback* is not None and *protocol* is None or smaller than 5.
76727db96d56Sopenharmony_ci
76737db96d56Sopenharmony_ci[clinic start generated code]*/
76747db96d56Sopenharmony_ci
76757db96d56Sopenharmony_cistatic PyObject *
76767db96d56Sopenharmony_ci_pickle_dump_impl(PyObject *module, PyObject *obj, PyObject *file,
76777db96d56Sopenharmony_ci                  PyObject *protocol, int fix_imports,
76787db96d56Sopenharmony_ci                  PyObject *buffer_callback)
76797db96d56Sopenharmony_ci/*[clinic end generated code: output=706186dba996490c input=5ed6653da99cd97c]*/
76807db96d56Sopenharmony_ci{
76817db96d56Sopenharmony_ci    PicklerObject *pickler = _Pickler_New();
76827db96d56Sopenharmony_ci
76837db96d56Sopenharmony_ci    if (pickler == NULL)
76847db96d56Sopenharmony_ci        return NULL;
76857db96d56Sopenharmony_ci
76867db96d56Sopenharmony_ci    if (_Pickler_SetProtocol(pickler, protocol, fix_imports) < 0)
76877db96d56Sopenharmony_ci        goto error;
76887db96d56Sopenharmony_ci
76897db96d56Sopenharmony_ci    if (_Pickler_SetOutputStream(pickler, file) < 0)
76907db96d56Sopenharmony_ci        goto error;
76917db96d56Sopenharmony_ci
76927db96d56Sopenharmony_ci    if (_Pickler_SetBufferCallback(pickler, buffer_callback) < 0)
76937db96d56Sopenharmony_ci        goto error;
76947db96d56Sopenharmony_ci
76957db96d56Sopenharmony_ci    if (dump(pickler, obj) < 0)
76967db96d56Sopenharmony_ci        goto error;
76977db96d56Sopenharmony_ci
76987db96d56Sopenharmony_ci    if (_Pickler_FlushToFile(pickler) < 0)
76997db96d56Sopenharmony_ci        goto error;
77007db96d56Sopenharmony_ci
77017db96d56Sopenharmony_ci    Py_DECREF(pickler);
77027db96d56Sopenharmony_ci    Py_RETURN_NONE;
77037db96d56Sopenharmony_ci
77047db96d56Sopenharmony_ci  error:
77057db96d56Sopenharmony_ci    Py_XDECREF(pickler);
77067db96d56Sopenharmony_ci    return NULL;
77077db96d56Sopenharmony_ci}
77087db96d56Sopenharmony_ci
77097db96d56Sopenharmony_ci/*[clinic input]
77107db96d56Sopenharmony_ci
77117db96d56Sopenharmony_ci_pickle.dumps
77127db96d56Sopenharmony_ci
77137db96d56Sopenharmony_ci  obj: object
77147db96d56Sopenharmony_ci  protocol: object = None
77157db96d56Sopenharmony_ci  *
77167db96d56Sopenharmony_ci  fix_imports: bool = True
77177db96d56Sopenharmony_ci  buffer_callback: object = None
77187db96d56Sopenharmony_ci
77197db96d56Sopenharmony_ciReturn the pickled representation of the object as a bytes object.
77207db96d56Sopenharmony_ci
77217db96d56Sopenharmony_ciThe optional *protocol* argument tells the pickler to use the given
77227db96d56Sopenharmony_ciprotocol; supported protocols are 0, 1, 2, 3, 4 and 5.  The default
77237db96d56Sopenharmony_ciprotocol is 4. It was introduced in Python 3.4, and is incompatible
77247db96d56Sopenharmony_ciwith previous versions.
77257db96d56Sopenharmony_ci
77267db96d56Sopenharmony_ciSpecifying a negative protocol version selects the highest protocol
77277db96d56Sopenharmony_civersion supported.  The higher the protocol used, the more recent the
77287db96d56Sopenharmony_civersion of Python needed to read the pickle produced.
77297db96d56Sopenharmony_ci
77307db96d56Sopenharmony_ciIf *fix_imports* is True and *protocol* is less than 3, pickle will
77317db96d56Sopenharmony_citry to map the new Python 3 names to the old module names used in
77327db96d56Sopenharmony_ciPython 2, so that the pickle data stream is readable with Python 2.
77337db96d56Sopenharmony_ci
77347db96d56Sopenharmony_ciIf *buffer_callback* is None (the default), buffer views are serialized
77357db96d56Sopenharmony_ciinto *file* as part of the pickle stream.  It is an error if
77367db96d56Sopenharmony_ci*buffer_callback* is not None and *protocol* is None or smaller than 5.
77377db96d56Sopenharmony_ci
77387db96d56Sopenharmony_ci[clinic start generated code]*/
77397db96d56Sopenharmony_ci
77407db96d56Sopenharmony_cistatic PyObject *
77417db96d56Sopenharmony_ci_pickle_dumps_impl(PyObject *module, PyObject *obj, PyObject *protocol,
77427db96d56Sopenharmony_ci                   int fix_imports, PyObject *buffer_callback)
77437db96d56Sopenharmony_ci/*[clinic end generated code: output=fbab0093a5580fdf input=e543272436c6f987]*/
77447db96d56Sopenharmony_ci{
77457db96d56Sopenharmony_ci    PyObject *result;
77467db96d56Sopenharmony_ci    PicklerObject *pickler = _Pickler_New();
77477db96d56Sopenharmony_ci
77487db96d56Sopenharmony_ci    if (pickler == NULL)
77497db96d56Sopenharmony_ci        return NULL;
77507db96d56Sopenharmony_ci
77517db96d56Sopenharmony_ci    if (_Pickler_SetProtocol(pickler, protocol, fix_imports) < 0)
77527db96d56Sopenharmony_ci        goto error;
77537db96d56Sopenharmony_ci
77547db96d56Sopenharmony_ci    if (_Pickler_SetBufferCallback(pickler, buffer_callback) < 0)
77557db96d56Sopenharmony_ci        goto error;
77567db96d56Sopenharmony_ci
77577db96d56Sopenharmony_ci    if (dump(pickler, obj) < 0)
77587db96d56Sopenharmony_ci        goto error;
77597db96d56Sopenharmony_ci
77607db96d56Sopenharmony_ci    result = _Pickler_GetString(pickler);
77617db96d56Sopenharmony_ci    Py_DECREF(pickler);
77627db96d56Sopenharmony_ci    return result;
77637db96d56Sopenharmony_ci
77647db96d56Sopenharmony_ci  error:
77657db96d56Sopenharmony_ci    Py_XDECREF(pickler);
77667db96d56Sopenharmony_ci    return NULL;
77677db96d56Sopenharmony_ci}
77687db96d56Sopenharmony_ci
77697db96d56Sopenharmony_ci/*[clinic input]
77707db96d56Sopenharmony_ci
77717db96d56Sopenharmony_ci_pickle.load
77727db96d56Sopenharmony_ci
77737db96d56Sopenharmony_ci  file: object
77747db96d56Sopenharmony_ci  *
77757db96d56Sopenharmony_ci  fix_imports: bool = True
77767db96d56Sopenharmony_ci  encoding: str = 'ASCII'
77777db96d56Sopenharmony_ci  errors: str = 'strict'
77787db96d56Sopenharmony_ci  buffers: object(c_default="NULL") = ()
77797db96d56Sopenharmony_ci
77807db96d56Sopenharmony_ciRead and return an object from the pickle data stored in a file.
77817db96d56Sopenharmony_ci
77827db96d56Sopenharmony_ciThis is equivalent to ``Unpickler(file).load()``, but may be more
77837db96d56Sopenharmony_ciefficient.
77847db96d56Sopenharmony_ci
77857db96d56Sopenharmony_ciThe protocol version of the pickle is detected automatically, so no
77867db96d56Sopenharmony_ciprotocol argument is needed.  Bytes past the pickled object's
77877db96d56Sopenharmony_cirepresentation are ignored.
77887db96d56Sopenharmony_ci
77897db96d56Sopenharmony_ciThe argument *file* must have two methods, a read() method that takes
77907db96d56Sopenharmony_cian integer argument, and a readline() method that requires no
77917db96d56Sopenharmony_ciarguments.  Both methods should return bytes.  Thus *file* can be a
77927db96d56Sopenharmony_cibinary file object opened for reading, an io.BytesIO object, or any
77937db96d56Sopenharmony_ciother custom object that meets this interface.
77947db96d56Sopenharmony_ci
77957db96d56Sopenharmony_ciOptional keyword arguments are *fix_imports*, *encoding* and *errors*,
77967db96d56Sopenharmony_ciwhich are used to control compatibility support for pickle stream
77977db96d56Sopenharmony_cigenerated by Python 2.  If *fix_imports* is True, pickle will try to
77987db96d56Sopenharmony_cimap the old Python 2 names to the new names used in Python 3.  The
77997db96d56Sopenharmony_ci*encoding* and *errors* tell pickle how to decode 8-bit string
78007db96d56Sopenharmony_ciinstances pickled by Python 2; these default to 'ASCII' and 'strict',
78017db96d56Sopenharmony_cirespectively.  The *encoding* can be 'bytes' to read these 8-bit
78027db96d56Sopenharmony_cistring instances as bytes objects.
78037db96d56Sopenharmony_ci[clinic start generated code]*/
78047db96d56Sopenharmony_ci
78057db96d56Sopenharmony_cistatic PyObject *
78067db96d56Sopenharmony_ci_pickle_load_impl(PyObject *module, PyObject *file, int fix_imports,
78077db96d56Sopenharmony_ci                  const char *encoding, const char *errors,
78087db96d56Sopenharmony_ci                  PyObject *buffers)
78097db96d56Sopenharmony_ci/*[clinic end generated code: output=250452d141c23e76 input=46c7c31c92f4f371]*/
78107db96d56Sopenharmony_ci{
78117db96d56Sopenharmony_ci    PyObject *result;
78127db96d56Sopenharmony_ci    UnpicklerObject *unpickler = _Unpickler_New();
78137db96d56Sopenharmony_ci
78147db96d56Sopenharmony_ci    if (unpickler == NULL)
78157db96d56Sopenharmony_ci        return NULL;
78167db96d56Sopenharmony_ci
78177db96d56Sopenharmony_ci    if (_Unpickler_SetInputStream(unpickler, file) < 0)
78187db96d56Sopenharmony_ci        goto error;
78197db96d56Sopenharmony_ci
78207db96d56Sopenharmony_ci    if (_Unpickler_SetInputEncoding(unpickler, encoding, errors) < 0)
78217db96d56Sopenharmony_ci        goto error;
78227db96d56Sopenharmony_ci
78237db96d56Sopenharmony_ci    if (_Unpickler_SetBuffers(unpickler, buffers) < 0)
78247db96d56Sopenharmony_ci        goto error;
78257db96d56Sopenharmony_ci
78267db96d56Sopenharmony_ci    unpickler->fix_imports = fix_imports;
78277db96d56Sopenharmony_ci
78287db96d56Sopenharmony_ci    result = load(unpickler);
78297db96d56Sopenharmony_ci    Py_DECREF(unpickler);
78307db96d56Sopenharmony_ci    return result;
78317db96d56Sopenharmony_ci
78327db96d56Sopenharmony_ci  error:
78337db96d56Sopenharmony_ci    Py_XDECREF(unpickler);
78347db96d56Sopenharmony_ci    return NULL;
78357db96d56Sopenharmony_ci}
78367db96d56Sopenharmony_ci
78377db96d56Sopenharmony_ci/*[clinic input]
78387db96d56Sopenharmony_ci
78397db96d56Sopenharmony_ci_pickle.loads
78407db96d56Sopenharmony_ci
78417db96d56Sopenharmony_ci  data: object
78427db96d56Sopenharmony_ci  /
78437db96d56Sopenharmony_ci  *
78447db96d56Sopenharmony_ci  fix_imports: bool = True
78457db96d56Sopenharmony_ci  encoding: str = 'ASCII'
78467db96d56Sopenharmony_ci  errors: str = 'strict'
78477db96d56Sopenharmony_ci  buffers: object(c_default="NULL") = ()
78487db96d56Sopenharmony_ci
78497db96d56Sopenharmony_ciRead and return an object from the given pickle data.
78507db96d56Sopenharmony_ci
78517db96d56Sopenharmony_ciThe protocol version of the pickle is detected automatically, so no
78527db96d56Sopenharmony_ciprotocol argument is needed.  Bytes past the pickled object's
78537db96d56Sopenharmony_cirepresentation are ignored.
78547db96d56Sopenharmony_ci
78557db96d56Sopenharmony_ciOptional keyword arguments are *fix_imports*, *encoding* and *errors*,
78567db96d56Sopenharmony_ciwhich are used to control compatibility support for pickle stream
78577db96d56Sopenharmony_cigenerated by Python 2.  If *fix_imports* is True, pickle will try to
78587db96d56Sopenharmony_cimap the old Python 2 names to the new names used in Python 3.  The
78597db96d56Sopenharmony_ci*encoding* and *errors* tell pickle how to decode 8-bit string
78607db96d56Sopenharmony_ciinstances pickled by Python 2; these default to 'ASCII' and 'strict',
78617db96d56Sopenharmony_cirespectively.  The *encoding* can be 'bytes' to read these 8-bit
78627db96d56Sopenharmony_cistring instances as bytes objects.
78637db96d56Sopenharmony_ci[clinic start generated code]*/
78647db96d56Sopenharmony_ci
78657db96d56Sopenharmony_cistatic PyObject *
78667db96d56Sopenharmony_ci_pickle_loads_impl(PyObject *module, PyObject *data, int fix_imports,
78677db96d56Sopenharmony_ci                   const char *encoding, const char *errors,
78687db96d56Sopenharmony_ci                   PyObject *buffers)
78697db96d56Sopenharmony_ci/*[clinic end generated code: output=82ac1e6b588e6d02 input=b3615540d0535087]*/
78707db96d56Sopenharmony_ci{
78717db96d56Sopenharmony_ci    PyObject *result;
78727db96d56Sopenharmony_ci    UnpicklerObject *unpickler = _Unpickler_New();
78737db96d56Sopenharmony_ci
78747db96d56Sopenharmony_ci    if (unpickler == NULL)
78757db96d56Sopenharmony_ci        return NULL;
78767db96d56Sopenharmony_ci
78777db96d56Sopenharmony_ci    if (_Unpickler_SetStringInput(unpickler, data) < 0)
78787db96d56Sopenharmony_ci        goto error;
78797db96d56Sopenharmony_ci
78807db96d56Sopenharmony_ci    if (_Unpickler_SetInputEncoding(unpickler, encoding, errors) < 0)
78817db96d56Sopenharmony_ci        goto error;
78827db96d56Sopenharmony_ci
78837db96d56Sopenharmony_ci    if (_Unpickler_SetBuffers(unpickler, buffers) < 0)
78847db96d56Sopenharmony_ci        goto error;
78857db96d56Sopenharmony_ci
78867db96d56Sopenharmony_ci    unpickler->fix_imports = fix_imports;
78877db96d56Sopenharmony_ci
78887db96d56Sopenharmony_ci    result = load(unpickler);
78897db96d56Sopenharmony_ci    Py_DECREF(unpickler);
78907db96d56Sopenharmony_ci    return result;
78917db96d56Sopenharmony_ci
78927db96d56Sopenharmony_ci  error:
78937db96d56Sopenharmony_ci    Py_XDECREF(unpickler);
78947db96d56Sopenharmony_ci    return NULL;
78957db96d56Sopenharmony_ci}
78967db96d56Sopenharmony_ci
78977db96d56Sopenharmony_cistatic struct PyMethodDef pickle_methods[] = {
78987db96d56Sopenharmony_ci    _PICKLE_DUMP_METHODDEF
78997db96d56Sopenharmony_ci    _PICKLE_DUMPS_METHODDEF
79007db96d56Sopenharmony_ci    _PICKLE_LOAD_METHODDEF
79017db96d56Sopenharmony_ci    _PICKLE_LOADS_METHODDEF
79027db96d56Sopenharmony_ci    {NULL, NULL} /* sentinel */
79037db96d56Sopenharmony_ci};
79047db96d56Sopenharmony_ci
79057db96d56Sopenharmony_cistatic int
79067db96d56Sopenharmony_cipickle_clear(PyObject *m)
79077db96d56Sopenharmony_ci{
79087db96d56Sopenharmony_ci    _Pickle_ClearState(_Pickle_GetState(m));
79097db96d56Sopenharmony_ci    return 0;
79107db96d56Sopenharmony_ci}
79117db96d56Sopenharmony_ci
79127db96d56Sopenharmony_cistatic void
79137db96d56Sopenharmony_cipickle_free(PyObject *m)
79147db96d56Sopenharmony_ci{
79157db96d56Sopenharmony_ci    _Pickle_ClearState(_Pickle_GetState(m));
79167db96d56Sopenharmony_ci}
79177db96d56Sopenharmony_ci
79187db96d56Sopenharmony_cistatic int
79197db96d56Sopenharmony_cipickle_traverse(PyObject *m, visitproc visit, void *arg)
79207db96d56Sopenharmony_ci{
79217db96d56Sopenharmony_ci    PickleState *st = _Pickle_GetState(m);
79227db96d56Sopenharmony_ci    Py_VISIT(st->PickleError);
79237db96d56Sopenharmony_ci    Py_VISIT(st->PicklingError);
79247db96d56Sopenharmony_ci    Py_VISIT(st->UnpicklingError);
79257db96d56Sopenharmony_ci    Py_VISIT(st->dispatch_table);
79267db96d56Sopenharmony_ci    Py_VISIT(st->extension_registry);
79277db96d56Sopenharmony_ci    Py_VISIT(st->extension_cache);
79287db96d56Sopenharmony_ci    Py_VISIT(st->inverted_registry);
79297db96d56Sopenharmony_ci    Py_VISIT(st->name_mapping_2to3);
79307db96d56Sopenharmony_ci    Py_VISIT(st->import_mapping_2to3);
79317db96d56Sopenharmony_ci    Py_VISIT(st->name_mapping_3to2);
79327db96d56Sopenharmony_ci    Py_VISIT(st->import_mapping_3to2);
79337db96d56Sopenharmony_ci    Py_VISIT(st->codecs_encode);
79347db96d56Sopenharmony_ci    Py_VISIT(st->getattr);
79357db96d56Sopenharmony_ci    Py_VISIT(st->partial);
79367db96d56Sopenharmony_ci    return 0;
79377db96d56Sopenharmony_ci}
79387db96d56Sopenharmony_ci
79397db96d56Sopenharmony_cistatic struct PyModuleDef _picklemodule = {
79407db96d56Sopenharmony_ci    PyModuleDef_HEAD_INIT,
79417db96d56Sopenharmony_ci    "_pickle",            /* m_name */
79427db96d56Sopenharmony_ci    pickle_module_doc,    /* m_doc */
79437db96d56Sopenharmony_ci    sizeof(PickleState),  /* m_size */
79447db96d56Sopenharmony_ci    pickle_methods,       /* m_methods */
79457db96d56Sopenharmony_ci    NULL,                 /* m_reload */
79467db96d56Sopenharmony_ci    pickle_traverse,      /* m_traverse */
79477db96d56Sopenharmony_ci    pickle_clear,         /* m_clear */
79487db96d56Sopenharmony_ci    (freefunc)pickle_free /* m_free */
79497db96d56Sopenharmony_ci};
79507db96d56Sopenharmony_ci
79517db96d56Sopenharmony_ciPyMODINIT_FUNC
79527db96d56Sopenharmony_ciPyInit__pickle(void)
79537db96d56Sopenharmony_ci{
79547db96d56Sopenharmony_ci    PyObject *m;
79557db96d56Sopenharmony_ci    PickleState *st;
79567db96d56Sopenharmony_ci
79577db96d56Sopenharmony_ci    m = PyState_FindModule(&_picklemodule);
79587db96d56Sopenharmony_ci    if (m) {
79597db96d56Sopenharmony_ci        Py_INCREF(m);
79607db96d56Sopenharmony_ci        return m;
79617db96d56Sopenharmony_ci    }
79627db96d56Sopenharmony_ci
79637db96d56Sopenharmony_ci    if (PyType_Ready(&Pdata_Type) < 0)
79647db96d56Sopenharmony_ci        return NULL;
79657db96d56Sopenharmony_ci    if (PyType_Ready(&PicklerMemoProxyType) < 0)
79667db96d56Sopenharmony_ci        return NULL;
79677db96d56Sopenharmony_ci    if (PyType_Ready(&UnpicklerMemoProxyType) < 0)
79687db96d56Sopenharmony_ci        return NULL;
79697db96d56Sopenharmony_ci
79707db96d56Sopenharmony_ci    /* Create the module and add the functions. */
79717db96d56Sopenharmony_ci    m = PyModule_Create(&_picklemodule);
79727db96d56Sopenharmony_ci    if (m == NULL)
79737db96d56Sopenharmony_ci        return NULL;
79747db96d56Sopenharmony_ci
79757db96d56Sopenharmony_ci    /* Add types */
79767db96d56Sopenharmony_ci    if (PyModule_AddType(m, &Pickler_Type) < 0) {
79777db96d56Sopenharmony_ci        return NULL;
79787db96d56Sopenharmony_ci    }
79797db96d56Sopenharmony_ci    if (PyModule_AddType(m, &Unpickler_Type) < 0) {
79807db96d56Sopenharmony_ci        return NULL;
79817db96d56Sopenharmony_ci    }
79827db96d56Sopenharmony_ci    if (PyModule_AddType(m, &PyPickleBuffer_Type) < 0) {
79837db96d56Sopenharmony_ci        return NULL;
79847db96d56Sopenharmony_ci    }
79857db96d56Sopenharmony_ci
79867db96d56Sopenharmony_ci    st = _Pickle_GetState(m);
79877db96d56Sopenharmony_ci
79887db96d56Sopenharmony_ci    /* Initialize the exceptions. */
79897db96d56Sopenharmony_ci    st->PickleError = PyErr_NewException("_pickle.PickleError", NULL, NULL);
79907db96d56Sopenharmony_ci    if (st->PickleError == NULL)
79917db96d56Sopenharmony_ci        return NULL;
79927db96d56Sopenharmony_ci    st->PicklingError = \
79937db96d56Sopenharmony_ci        PyErr_NewException("_pickle.PicklingError", st->PickleError, NULL);
79947db96d56Sopenharmony_ci    if (st->PicklingError == NULL)
79957db96d56Sopenharmony_ci        return NULL;
79967db96d56Sopenharmony_ci    st->UnpicklingError = \
79977db96d56Sopenharmony_ci        PyErr_NewException("_pickle.UnpicklingError", st->PickleError, NULL);
79987db96d56Sopenharmony_ci    if (st->UnpicklingError == NULL)
79997db96d56Sopenharmony_ci        return NULL;
80007db96d56Sopenharmony_ci
80017db96d56Sopenharmony_ci    if (PyModule_AddObjectRef(m, "PickleError", st->PickleError) < 0) {
80027db96d56Sopenharmony_ci        return NULL;
80037db96d56Sopenharmony_ci    }
80047db96d56Sopenharmony_ci    if (PyModule_AddObjectRef(m, "PicklingError", st->PicklingError) < 0) {
80057db96d56Sopenharmony_ci        return NULL;
80067db96d56Sopenharmony_ci    }
80077db96d56Sopenharmony_ci    if (PyModule_AddObjectRef(m, "UnpicklingError", st->UnpicklingError) < 0) {
80087db96d56Sopenharmony_ci        return NULL;
80097db96d56Sopenharmony_ci    }
80107db96d56Sopenharmony_ci    if (_Pickle_InitState(st) < 0)
80117db96d56Sopenharmony_ci        return NULL;
80127db96d56Sopenharmony_ci
80137db96d56Sopenharmony_ci    return m;
80147db96d56Sopenharmony_ci}
8015