Marc-Andre Lemburg: support pickling Unicode objects, both in text

mode ('V') and in binary mode ('X').
This commit is contained in:
Guido van Rossum 2000-03-10 23:11:40 +00:00
parent 2a70a3a8fc
commit 5fccb7c58e
1 changed files with 149 additions and 0 deletions

View File

@ -89,6 +89,8 @@ static char cPickle_module_documentation[] =
#define STRING 'S' #define STRING 'S'
#define BINSTRING 'T' #define BINSTRING 'T'
#define SHORT_BINSTRING 'U' #define SHORT_BINSTRING 'U'
#define UNICODE 'V'
#define BINUNICODE 'X'
#define APPEND 'a' #define APPEND 'a'
#define BUILD 'b' #define BUILD 'b'
#define GLOBAL 'c' #define GLOBAL 'c'
@ -1159,6 +1161,79 @@ err:
} }
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 = PyUnicode_AsRawUnicodeEscapeString(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;
}
static int static int
save_tuple(Picklerobject *self, PyObject *args) { save_tuple(Picklerobject *self, PyObject *args) {
PyObject *element = 0, *py_tuple_id = 0; PyObject *element = 0, *py_tuple_id = 0;
@ -1691,6 +1766,12 @@ save(Picklerobject *self, PyObject *args, int pers_save) {
res = save_string(self, args, 0); res = save_string(self, args, 0);
goto finally; goto finally;
} }
case 'u':
if ((type == &PyUnicode_Type) && (PyString_GET_SIZE(args) < 2)) {
res = save_unicode(self, args, 0);
goto finally;
}
} }
if (args->ob_refcnt > 1) { if (args->ob_refcnt > 1) {
@ -1722,6 +1803,13 @@ save(Picklerobject *self, PyObject *args, int pers_save) {
} }
break; break;
case 'u':
if (type == &PyUnicode_Type) {
res = save_unicode(self, args, 1);
goto finally;
}
break;
case 't': case 't':
if (type == &PyTuple_Type) { if (type == &PyTuple_Type) {
res = save_tuple(self, args); res = save_tuple(self, args);
@ -2666,6 +2754,47 @@ load_short_binstring(Unpicklerobject *self) {
} }
static int
load_unicode(Unpicklerobject *self) {
PyObject *str = 0;
int len, res = -1;
char *s;
if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
if (len < 2) return bad_readline();
UNLESS (str = PyUnicode_DecodeRawUnicodeEscape(s, len - 1, NULL))
goto finally;
PDATA_PUSH(self->stack, str, -1);
return 0;
finally:
return res;
}
static int
load_binunicode(Unpicklerobject *self) {
PyObject *unicode;
long l;
char *s;
if ((*self->read_func)(self, &s, 4) < 0) return -1;
l = calc_binint(s, 4);
if ((*self->read_func)(self, &s, l) < 0)
return -1;
UNLESS (unicode = PyUnicode_DecodeUTF8(s, l, NULL))
return -1;
PDATA_PUSH(self->stack, unicode, -1);
return 0;
}
static int static int
load_tuple(Unpicklerobject *self) { load_tuple(Unpicklerobject *self) {
PyObject *tup; PyObject *tup;
@ -3412,6 +3541,16 @@ load(Unpicklerobject *self) {
break; break;
continue; continue;
case UNICODE:
if (load_unicode(self) < 0)
break;
continue;
case BINUNICODE:
if (load_binunicode(self) < 0)
break;
continue;
case EMPTY_TUPLE: case EMPTY_TUPLE:
if (load_empty_tuple(self) < 0) if (load_empty_tuple(self) < 0)
break; break;
@ -3692,6 +3831,16 @@ noload(Unpicklerobject *self) {
break; break;
continue; continue;
case UNICODE:
if (load_unicode(self) < 0)
break;
continue;
case BINUNICODE:
if (load_binunicode(self) < 0)
break;
continue;
case EMPTY_TUPLE: case EMPTY_TUPLE:
if (load_empty_tuple(self) < 0) if (load_empty_tuple(self) < 0)
break; break;