cpickle.c

来自「python s60 1.4.5版本的源代码」· C语言 代码 · 共 2,601 行 · 第 1/5 页

C
2,601
字号

        if (x < 0) {
            s = 1;
            x = -x;
        }
        else
            s = 0;

        f = frexp(x, &e);

        /* Normalize f to be in the range [1.0, 2.0) */
        if (0.5 <= f && f < 1.0) {
            f *= 2.0;
            e--;
        }
        else if (f == 0.0) {
            e = 0;
        }
        else {
            PyErr_SetString(PyExc_SystemError,
                            "frexp() result out of range");
            return -1;
        }

        if (e >= 1024) {
            /* XXX 1024 itself is reserved for Inf/NaN */
            PyErr_SetString(PyExc_OverflowError,
                            "float too large to pack with d format");
            return -1;
        }
        else if (e < -1022) {
            /* Gradual underflow */
            f = ldexp(f, 1022 + e);
            e = 0;
        }
        else if (!(e == 0 && f == 0.0)) {
            e += 1023;
            f -= 1.0; /* Get rid of leading 1 */
        }

        /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
        f *= 268435456.0; /* 2**28 */
        fhi = (long) floor(f); /* Truncate */
        f -= (double)fhi;
        f *= 16777216.0; /* 2**24 */
        flo = (long) floor(f + 0.5); /* Round */

        /* First byte */
        *p = (s<<7) | (e>>4);
        p++;

        /* Second byte */
        *p = (unsigned char) (((e&0xF)<<4) | (fhi>>24));
        p++;

        /* Third byte */
        *p = (unsigned char) ((fhi>>16) & 0xFF);
        p++;

        /* Fourth byte */
        *p = (unsigned char) ((fhi>>8) & 0xFF);
        p++;

        /* Fifth byte */
        *p = (unsigned char) (fhi & 0xFF);
        p++;

        /* Sixth byte */
        *p = (unsigned char) ((flo>>16) & 0xFF);
        p++;

        /* Seventh byte */
        *p = (unsigned char) ((flo>>8) & 0xFF);
        p++;

        /* Eighth byte */
        *p = (unsigned char) (flo & 0xFF);

        if ((*self->write_func)(self, str, 9) < 0)
            return -1;
    }
    else {
        char c_str[250];
        c_str[0] = FLOAT;
        PyOS_snprintf(c_str + 1, sizeof(c_str) - 1, "%.17g\n", x);

        if ((*self->write_func)(self, c_str, strlen(c_str)) < 0)
            return -1;
    }

    return 0;
}


static int
save_string(Picklerobject *self, PyObject *args, int doput) {
    int size, len;
    PyObject *repr=0;

    if ((size = PyString_Size(args)) < 0)
      return -1;

    if (!self->bin) {
        char *repr_str;

        static char string = STRING;

        UNLESS (repr = PyObject_Repr(args))
            return -1;

        if ((len = PyString_Size(repr)) < 0)
          goto err;
        repr_str = PyString_AS_STRING((PyStringObject *)repr);

        if ((*self->write_func)(self, &string, 1) < 0)
            goto err;

        if ((*self->write_func)(self, repr_str, len) < 0)
            goto err;

        if ((*self->write_func)(self, "\n", 1) < 0)
            goto err;

        Py_XDECREF(repr);
    }
    else {
        int i;
        char c_str[5];

        if ((size = PyString_Size(args)) < 0)
          return -1;

        if (size < 256) {
            c_str[0] = SHORT_BINSTRING;
            c_str[1] = size;
            len = 2;
        }
        else {
            c_str[0] = BINSTRING;
            for (i = 1; i < 5; i++)
                c_str[i] = (int)(size >> ((i - 1) * 8));
            len = 5;
        }

        if ((*self->write_func)(self, c_str, len) < 0)
            return -1;

        if (size > 128 && Pdata_Check(self->file)) {
            if (write_other(self, NULL, 0) < 0) return -1;
            PDATA_APPEND(self->file, args, -1);
          }
        else {
          if ((*self->write_func)(self,
              PyString_AS_STRING((PyStringObject *)args), size) < 0)
            return -1;
        }
    }

    if (doput)
      if (put(self, args) < 0)
        return -1;

    return 0;

err:
    Py_XDECREF(repr);
    return -1;
}


#ifdef Py_USING_UNICODE
/* A copy of PyUnicode_EncodeRawUnicodeEscape() that also translates
   backslash and newline characters to \uXXXX escapes. */
static PyObject *
modified_EncodeRawUnicodeEscape(const Py_UNICODE *s, int size)
{
    PyObject *repr;
    char *p;
    char *q;

    static const char *hexdigit = "0123456789ABCDEF";

    repr = PyString_FromStringAndSize(NULL, 6 * size);
    if (repr == NULL)
        return NULL;
    if (size == 0)
	return repr;

    p = q = PyString_AS_STRING(repr);
    while (size-- > 0) {
        Py_UNICODE ch = *s++;
	/* Map 16-bit characters to '\uxxxx' */
	if (ch >= 256 || ch == '\\' || ch == '\n') {
            *p++ = '\\';
            *p++ = 'u';
            *p++ = hexdigit[(ch >> 12) & 0xf];
            *p++ = hexdigit[(ch >> 8) & 0xf];
            *p++ = hexdigit[(ch >> 4) & 0xf];
            *p++ = hexdigit[ch & 15];
        }
	/* Copy everything else as-is */
	else
            *p++ = (char) ch;
    }
    *p = '\0';
    if (_PyString_Resize(&repr, p - q))
	goto onError;

    return repr;

 onError:
    Py_DECREF(repr);
    return NULL;
}


static int
save_unicode(Picklerobject *self, PyObject *args, int doput) {
    int size, len;
    PyObject *repr=0;

    if (!PyUnicode_Check(args))
      return -1;

    if (!self->bin) {
        char *repr_str;
        static char string = UNICODE;

        UNLESS(repr = modified_EncodeRawUnicodeEscape(
		PyUnicode_AS_UNICODE(args), PyUnicode_GET_SIZE(args)))
            return -1;

        if ((len = PyString_Size(repr)) < 0)
          goto err;
        repr_str = PyString_AS_STRING((PyStringObject *)repr);

        if ((*self->write_func)(self, &string, 1) < 0)
            goto err;

        if ((*self->write_func)(self, repr_str, len) < 0)
            goto err;

        if ((*self->write_func)(self, "\n", 1) < 0)
            goto err;

        Py_XDECREF(repr);
    }
    else {
        int i;
        char c_str[5];

        UNLESS (repr = PyUnicode_AsUTF8String(args))
            return -1;

        if ((size = PyString_Size(repr)) < 0)
	    goto err;

	c_str[0] = BINUNICODE;
	for (i = 1; i < 5; i++)
	    c_str[i] = (int)(size >> ((i - 1) * 8));
	len = 5;

        if ((*self->write_func)(self, c_str, len) < 0)
            goto err;

        if (size > 128 && Pdata_Check(self->file)) {
            if (write_other(self, NULL, 0) < 0)
		goto err;
            PDATA_APPEND(self->file, repr, -1);
          }
        else {
          if ((*self->write_func)(self, PyString_AS_STRING(repr), size) < 0)
	      goto err;
        }

	Py_DECREF(repr);
    }

    if (doput)
      if (put(self, args) < 0)
        return -1;

    return 0;

err:
    Py_XDECREF(repr);
    return -1;
}
#endif


static int
save_tuple(Picklerobject *self, PyObject *args) {
    PyObject *element = 0, *py_tuple_id = 0;
    int len, i, res = -1;

    static char tuple = TUPLE;

    if ((*self->write_func)(self, &MARKv, 1) < 0)
        goto finally;

    if ((len = PyTuple_Size(args)) < 0)
        goto finally;

    for (i = 0; i < len; i++) {
        UNLESS (element = PyTuple_GET_ITEM((PyTupleObject *)args, i))
            goto finally;

        if (save(self, element, 0) < 0)
            goto finally;
    }

    UNLESS (py_tuple_id = PyLong_FromVoidPtr(args))
        goto finally;

    if (len) {
	if (PyDict_GetItem(self->memo, py_tuple_id)) {
            if (self->bin) {
                static char pop_mark = POP_MARK;

                if ((*self->write_func)(self, &pop_mark, 1) < 0)
                    goto finally;
            }
            else {
                static char pop = POP;

                for (i = 0; i <= len; i++) {
                    if ((*self->write_func)(self, &pop, 1) < 0)
                        goto finally;
                }
            }

            if (get(self, py_tuple_id) < 0)
                goto finally;

            res = 0;
            goto finally;
        }
    }

    if ((*self->write_func)(self, &tuple, 1) < 0) {
        goto finally;
    }

    if (put(self, args) < 0)
        goto finally;

    res = 0;

finally:
    Py_XDECREF(py_tuple_id);

    return res;
}

static int
save_empty_tuple(Picklerobject *self, PyObject *args) {
    static char tuple = EMPTY_TUPLE;

    return (*self->write_func)(self, &tuple, 1);
}


static int
save_list(Picklerobject *self, PyObject *args) {
    PyObject *element = 0;
    int s_len, len, i, using_appends, res = -1;
    char s[3];

    static char append = APPEND, appends = APPENDS;

    if (self->fast && !fast_save_enter(self, args))
	goto finally;

    if (self->bin) {
        s[0] = EMPTY_LIST;
        s_len = 1;
    }
    else {
        s[0] = MARK;
        s[1] = LIST;
        s_len = 2;
    }

    if ((len = PyList_Size(args)) < 0)
        goto finally;

    if ((*self->write_func)(self, s, s_len) < 0)
        goto finally;

    if (len == 0) {
        if (put(self, args) < 0)
            goto finally;
    }
    else {
        if (put2(self, args) < 0)
            goto finally;
    }

    if ((using_appends = (self->bin && (len > 1))))
        if ((*self->write_func)(self, &MARKv, 1) < 0)
            goto finally;

    for (i = 0; i < len; i++) {
        UNLESS (element = PyList_GET_ITEM((PyListObject *)args, i))
            goto finally;

        if (save(self, element, 0) < 0)
            goto finally;

        if (!using_appends) {
            if ((*self->write_func)(self, &append, 1) < 0)
                goto finally;
        }
    }

    if (using_appends) {
        if ((*self->write_func)(self, &appends, 1) < 0)
            goto finally;
    }

    res = 0;

finally:
    if (self->fast && !fast_save_leave(self, args))
	res = -1;

    return res;
}


static int
save_dict(Picklerobject *self, PyObject *args) {
    PyObject *key = 0, *value = 0;
    int i, len, res = -1, using_setitems;
    char s[3];

    static char setitem = SETITEM, setitems = SETITEMS;

    if (self->fast && !fast_save_enter(self, args))
	goto finally;

    if (self->bin) {
        s[0] = EMPTY_DICT;
        len = 1;
    }
    else {
        s[0] = MARK;
        s[1] = DICT;
        len = 2;
    }

    if ((*self->write_func)(self, s, len) < 0)
        goto finally;

    if ((len = PyDict_Size(args)) < 0)
        goto finally;

    if (len == 0) {
        if (put(self, args) < 0)
            goto finally;
    }
    else {
        if (put2(self, args) < 0)
            goto finally;
    }

    if ((using_setitems = (self->bin && (PyDict_Size(args) > 1))))
        if ((*self->write_func)(self, &MARKv, 1) < 0)
            goto finally;

    i = 0;
    while (PyDict_Next(args, &i, &key, &value)) {
        if (save(self, key, 0) < 0)
            goto finally;

        if (save(self, value, 0) < 0)
            goto finally;

        if (!using_setitems) {
            if ((*self->write_func)(self, &setitem, 1) < 0)
                goto finally;
        }
    }

    if (using_setitems) {
        if ((*self->write_func)(self, &setitems, 1) < 0)
            goto finally;
    }

    res = 0;

finally:
    if (self->fast && !fast_save_leave(self, args))
	res = -1;

    return res;
}


static int
save_inst(Picklerobject *self, PyObject *args) {
    PyObject *class = 0, *module = 0, *name = 0, *state = 0,
             *getinitargs_func = 0, *getstate_func = 0, *class_args = 0;
    char *module_str, *name_str;
    int module_size, name_size, res = -1;

    static char inst = INST, obj = OBJ, build = BUILD;

    if (self->fast && !fast_save_enter(self, args))
	goto finally;

    if ((*self->write_func)(self, &MARKv, 1) < 0)
        goto finally;

    UNLESS (class = PyObject_GetAttr(args, __class___str))
        goto finally;

    if (self->bin) {
        if (save(self, class, 0) < 0)
            goto finally;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?