This commit was manufactured by cvs2svn to create tag 'release101'.
[python/dscho.git] / Python / marshal.c
blob1c88da052f3329fb91a77caefa710bc286165caf
1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Write Python objects to files and read them back.
26 This is intended for writing and reading compiled Python code only;
27 a true persistent storage facility would be much harder, since
28 it would have to take circular links and sharing into account. */
30 #include "allobjects.h"
31 #include "modsupport.h"
32 #include "longintrepr.h"
33 #include "compile.h"
34 #include "marshal.h"
36 #include <errno.h>
38 #define TYPE_NULL '0'
39 #define TYPE_NONE 'N'
40 #define TYPE_INT 'i'
41 #define TYPE_FLOAT 'f'
42 #define TYPE_LONG 'l'
43 #define TYPE_STRING 's'
44 #define TYPE_TUPLE '('
45 #define TYPE_LIST '['
46 #define TYPE_DICT '{'
47 #define TYPE_CODE 'C'
48 #define TYPE_UNKNOWN '?'
50 typedef struct {
51 FILE *fp;
52 /* If fp == NULL, the following are valid: */
53 object *str;
54 char *ptr;
55 char *end;
56 } WFILE;
58 #define w_byte(c, p) if (((p)->fp)) putc((c), (p)->fp); \
59 else if ((p)->ptr != (p)->end) *(p)->ptr++ = (c); \
60 else w_more(c, p)
62 static void
63 w_more(c, p)
64 char c;
65 WFILE *p;
67 int size, newsize;
68 if (p->str == NULL)
69 return; /* An error already occurred */
70 size = getstringsize(p->str);
71 newsize = size + 1024;
72 if (resizestring(&p->str, newsize) != 0) {
73 p->ptr = p->end = NULL;
75 else {
76 p->ptr = GETSTRINGVALUE((stringobject *)p->str) + size;
77 p->end = GETSTRINGVALUE((stringobject *)p->str) + newsize;
78 *p->ptr++ = c;
82 static void
83 w_string(s, n, p)
84 char *s;
85 int n;
86 WFILE *p;
88 if (p->fp != NULL) {
89 fwrite(s, 1, n, p->fp);
91 else {
92 while (--n >= 0) {
93 w_byte(*s, p);
94 s++;
99 static void
100 w_short(x, p)
101 int x;
102 WFILE *p;
104 w_byte( x & 0xff, p);
105 w_byte((x>> 8) & 0xff, p);
108 static void
109 w_long(x, p)
110 long x;
111 WFILE *p;
113 w_byte((int)( x & 0xff), p);
114 w_byte((int)((x>> 8) & 0xff), p);
115 w_byte((int)((x>>16) & 0xff), p);
116 w_byte((int)((x>>24) & 0xff), p);
119 static void
120 w_object(v, p)
121 object *v;
122 WFILE *p;
124 long i, n;
126 if (v == NULL)
127 w_byte(TYPE_NULL, p);
128 else if (v == None)
129 w_byte(TYPE_NONE, p);
130 else if (is_intobject(v)) {
131 w_byte(TYPE_INT, p);
132 w_long(getintvalue(v), p);
134 else if (is_longobject(v)) {
135 longobject *ob = (longobject *)v;
136 w_byte(TYPE_LONG, p);
137 n = ob->ob_size;
138 w_long((long)n, p);
139 if (n < 0)
140 n = -n;
141 for (i = 0; i < n; i++)
142 w_short(ob->ob_digit[i], p);
144 else if (is_floatobject(v)) {
145 extern void float_buf_repr PROTO((char *, floatobject *));
146 char buf[256]; /* Plenty to format any double */
147 float_buf_repr(buf, (floatobject *)v);
148 n = strlen(buf);
149 w_byte(TYPE_FLOAT, p);
150 w_byte((int)n, p);
151 w_string(buf, (int)n, p);
153 else if (is_stringobject(v)) {
154 w_byte(TYPE_STRING, p);
155 n = getstringsize(v);
156 w_long(n, p);
157 w_string(getstringvalue(v), (int)n, p);
159 else if (is_tupleobject(v)) {
160 w_byte(TYPE_TUPLE, p);
161 n = gettuplesize(v);
162 w_long(n, p);
163 for (i = 0; i < n; i++) {
164 w_object(gettupleitem(v, (int)i), p);
167 else if (is_listobject(v)) {
168 w_byte(TYPE_LIST, p);
169 n = getlistsize(v);
170 w_long(n, p);
171 for (i = 0; i < n; i++) {
172 w_object(getlistitem(v, (int)i), p);
175 else if (is_dictobject(v)) {
176 int pos;
177 object *key, *value;
178 w_byte(TYPE_DICT, p);
179 /* This one is NULL object terminated! */
180 pos = 0;
181 while (mappinggetnext(v, &pos, &key, &value)) {
182 w_object(key, p);
183 w_object(value, p);
185 w_object((object *)NULL, p);
187 else if (is_codeobject(v)) {
188 codeobject *co = (codeobject *)v;
189 w_byte(TYPE_CODE, p);
190 w_object((object *)co->co_code, p);
191 w_object(co->co_consts, p);
192 w_object(co->co_names, p);
193 w_object(co->co_filename, p);
194 w_object(co->co_name, p);
196 else {
197 w_byte(TYPE_UNKNOWN, p);
201 void
202 wr_long(x, fp)
203 long x;
204 FILE *fp;
206 WFILE wf;
207 wf.fp = fp;
208 w_long(x, &wf);
211 void
212 wr_object(x, fp)
213 object *x;
214 FILE *fp;
216 WFILE wf;
217 wf.fp = fp;
218 w_object(x, &wf);
221 typedef WFILE RFILE; /* Same struct with different invariants */
223 #define r_byte(p) ((p)->fp ? getc((p)->fp) \
224 : ((p)->ptr != (p)->end) ? \
225 (unsigned char)*(p)->ptr++ : EOF)
227 static int
228 r_string(s, n, p)
229 char *s;
230 int n;
231 RFILE *p;
233 if (p->fp != NULL)
234 return fread(s, 1, n, p->fp);
235 if (p->end - p->ptr < n)
236 n = p->end - p->ptr;
237 memcpy(s, p->ptr, n);
238 p->ptr += n;
239 return n;
242 static int
243 r_short(p)
244 RFILE *p;
246 register short x;
247 x = r_byte(p);
248 x |= r_byte(p) << 8;
249 /* XXX If your short is > 16 bits, add sign-extension here!!! */
250 return x;
253 static long
254 r_long(p)
255 RFILE *p;
257 register long x;
258 x = r_byte(p);
259 x |= (long)r_byte(p) << 8;
260 x |= (long)r_byte(p) << 16;
261 x |= (long)r_byte(p) << 24;
262 /* XXX If your long is > 32 bits, add sign-extension here!!! */
263 return x;
266 static object *
267 r_object(p)
268 RFILE *p;
270 object *v;
271 long i, n;
272 int type = r_byte(p);
274 switch (type) {
276 case EOF:
277 err_setstr(EOFError, "EOF read where object expected");
278 return NULL;
280 case TYPE_NULL:
281 return NULL;
283 case TYPE_NONE:
284 INCREF(None);
285 return None;
287 case TYPE_INT:
288 return newintobject(r_long(p));
290 case TYPE_LONG:
292 int size;
293 longobject *ob;
294 n = r_long(p);
295 size = n<0 ? -n : n;
296 ob = alloclongobject(size);
297 if (ob == NULL)
298 return NULL;
299 ob->ob_size = n;
300 for (i = 0; i < size; i++)
301 ob->ob_digit[i] = r_short(p);
302 return (object *)ob;
305 case TYPE_FLOAT:
307 extern double strtod PROTO((const char *, char **));
308 char buf[256];
309 double res;
310 char *end;
311 n = r_byte(p);
312 if (r_string(buf, (int)n, p) != n) {
313 err_setstr(EOFError,
314 "EOF read where object expected");
315 return NULL;
317 buf[n] = '\0';
318 errno = 0;
319 res = strtod(buf, &end);
320 if (*end != '\0') {
321 err_setstr(ValueError, "bad float syntax");
322 return NULL;
324 if (errno != 0) {
325 err_setstr(ValueError,
326 "float constant too large");
327 return NULL;
329 return newfloatobject(res);
332 case TYPE_STRING:
333 n = r_long(p);
334 v = newsizedstringobject((char *)NULL, n);
335 if (v != NULL) {
336 if (r_string(getstringvalue(v), (int)n, p) != n) {
337 DECREF(v);
338 v = NULL;
339 err_setstr(EOFError,
340 "EOF read where object expected");
343 return v;
345 case TYPE_TUPLE:
346 n = r_long(p);
347 v = newtupleobject((int)n);
348 if (v == NULL)
349 return v;
350 for (i = 0; i < n; i++)
351 settupleitem(v, (int)i, r_object(p));
352 return v;
354 case TYPE_LIST:
355 n = r_long(p);
356 v = newlistobject((int)n);
357 if (v == NULL)
358 return v;
359 for (i = 0; i < n; i++)
360 setlistitem(v, (int)i, r_object(p));
361 return v;
363 case TYPE_DICT:
364 v = newdictobject();
365 if (v == NULL)
366 return NULL;
367 for (;;) {
368 object *key, *val;
369 key = r_object(p);
370 if (key == NULL)
371 break;
372 val = r_object(p);
373 dict2insert(v, key, val);
374 DECREF(key);
375 XDECREF(val);
377 return v;
379 case TYPE_CODE:
381 object *code = r_object(p);
382 object *consts = r_object(p);
383 object *names = r_object(p);
384 object *filename = r_object(p);
385 object *name = r_object(p);
386 if (!err_occurred()) {
387 v = (object *) newcodeobject(code,
388 consts, names, filename, name);
390 else
391 v = NULL;
392 XDECREF(code);
393 XDECREF(consts);
394 XDECREF(names);
395 XDECREF(filename);
398 return v;
400 default:
401 err_setstr(TypeError, "read unknown object");
402 return NULL;
407 long
408 rd_long(fp)
409 FILE *fp;
411 RFILE rf;
412 rf.fp = fp;
413 return r_long(&rf);
416 object *
417 rd_object(fp)
418 FILE *fp;
420 RFILE rf;
421 rf.fp = fp;
422 return r_object(&rf);
425 object *
426 rds_object(str, len)
427 char *str;
428 int len;
430 RFILE rf;
431 rf.fp = NULL;
432 rf.str = NULL;
433 rf.ptr = str;
434 rf.end = str + len;
435 return r_object(&rf);
438 /* And an interface for Python programs... */
440 static object *
441 marshal_dump(self, args)
442 object *self;
443 object *args;
445 WFILE wf;
446 object *x;
447 object *f;
448 if (!getargs(args, "(OO)", &x, &f))
449 return NULL;
450 if (!is_fileobject(f)) {
451 err_setstr(TypeError, "marshal.dump() 2nd arg must be file");
452 return NULL;
454 wf.fp = getfilefile(f);
455 wf.str = NULL;
456 wf.ptr = wf.end = NULL;
457 w_object(x, &wf);
458 INCREF(None);
459 return None;
462 static object *
463 marshal_load(self, args)
464 object *self;
465 object *args;
467 RFILE rf;
468 object *f;
469 object *v;
470 if (!getargs(args, "O", &f))
471 return NULL;
472 if (!is_fileobject(f)) {
473 err_setstr(TypeError, "marshal.load() arg must be file");
474 return NULL;
476 rf.fp = getfilefile(f);
477 rf.str = NULL;
478 rf.ptr = rf.end = NULL;
479 err_clear();
480 v = r_object(&rf);
481 if (err_occurred()) {
482 XDECREF(v);
483 v = NULL;
485 return v;
488 static object *
489 marshal_dumps(self, args)
490 object *self;
491 object *args;
493 WFILE wf;
494 object *x;
495 if (!getargs(args, "O", &x))
496 return NULL;
497 wf.fp = NULL;
498 wf.str = newsizedstringobject((char *)NULL, 50);
499 if (wf.str == NULL)
500 return NULL;
501 wf.ptr = GETSTRINGVALUE((stringobject *)wf.str);
502 wf.end = wf.ptr + getstringsize(wf.str);
503 w_object(x, &wf);
504 if (wf.str != NULL)
505 resizestring(&wf.str,
506 (int) (wf.ptr - GETSTRINGVALUE((stringobject *)wf.str)));
507 return wf.str;
510 static object *
511 marshal_loads(self, args)
512 object *self;
513 object *args;
515 RFILE rf;
516 object *v;
517 char *s;
518 int n;
519 if (!getargs(args, "s#", &s, &n))
520 return NULL;
521 rf.fp = NULL;
522 rf.str = args;
523 rf.ptr = s;
524 rf.end = s + n;
525 err_clear();
526 v = r_object(&rf);
527 if (err_occurred()) {
528 XDECREF(v);
529 v = NULL;
531 return v;
534 static struct methodlist marshal_methods[] = {
535 {"dump", marshal_dump},
536 {"load", marshal_load},
537 {"dumps", marshal_dumps},
538 {"loads", marshal_loads},
539 {NULL, NULL} /* sentinel */
542 void
543 initmarshal()
545 (void) initmodule("marshal", marshal_methods);