1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
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"
41 #define TYPE_FLOAT 'f'
43 #define TYPE_STRING 's'
44 #define TYPE_TUPLE '('
48 #define TYPE_UNKNOWN '?'
52 /* If fp == NULL, the following are valid: */
58 #define w_byte(c, p) if (((p)->fp)) putc((c), (p)->fp); \
59 else if ((p)->ptr != (p)->end) *(p)->ptr++ = (c); \
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
;
76 p
->ptr
= GETSTRINGVALUE((stringobject
*)p
->str
) + size
;
77 p
->end
= GETSTRINGVALUE((stringobject
*)p
->str
) + newsize
;
89 fwrite(s
, 1, n
, p
->fp
);
104 w_byte( x
& 0xff, p
);
105 w_byte((x
>> 8) & 0xff, 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
);
127 w_byte(TYPE_NULL
, p
);
129 w_byte(TYPE_NONE
, p
);
130 else if (is_intobject(v
)) {
132 w_long(getintvalue(v
), p
);
134 else if (is_longobject(v
)) {
135 longobject
*ob
= (longobject
*)v
;
136 w_byte(TYPE_LONG
, p
);
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
);
149 w_byte(TYPE_FLOAT
, p
);
153 else if (is_stringobject(v
)) {
154 w_byte(TYPE_STRING
, p
);
155 n
= getstringsize(v
);
157 w_string(getstringvalue(v
), n
, p
);
159 else if (is_tupleobject(v
)) {
160 w_byte(TYPE_TUPLE
, p
);
163 for (i
= 0; i
< n
; i
++) {
164 w_object(GETTUPLEITEM(v
, i
), p
);
167 else if (is_listobject(v
)) {
168 w_byte(TYPE_LIST
, p
);
171 for (i
= 0; i
< n
; i
++) {
172 w_object(getlistitem(v
, i
), p
);
175 else if (is_dictobject(v
)) {
178 w_byte(TYPE_DICT
, p
);
179 /* This one is NULL object terminated! */
181 while (mappinggetnext(v
, &pos
, &key
, &value
)) {
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
);
197 w_byte(TYPE_UNKNOWN
, p
);
221 typedef WFILE RFILE
; /* Same struct with different invariants */
223 #define rs_byte(p) (((p)->ptr != (p)->end) ? (unsigned char)*(p)->ptr++ : EOF)
225 #define r_byte(p) ((p)->fp ? getc((p)->fp) : rs_byte(p))
234 return fread(s
, 1, n
, p
->fp
);
235 if (p
->end
- p
->ptr
< n
)
237 memcpy(s
, p
->ptr
, n
);
249 /* XXX If your short is > 16 bits, add sign-extension here!!! */
258 register FILE *fp
= p
->fp
;
261 x
|= (long)getc(fp
) << 8;
262 x
|= (long)getc(fp
) << 16;
263 x
|= (long)getc(fp
) << 24;
267 x
|= (long)rs_byte(p
) << 8;
268 x
|= (long)rs_byte(p
) << 16;
269 x
|= (long)rs_byte(p
) << 24;
271 /* XXX If your long is > 32 bits, add sign-extension here!!! */
281 int type
= r_byte(p
);
286 err_setstr(EOFError
, "EOF read where object expected");
297 return newintobject(r_long(p
));
305 ob
= alloclongobject(size
);
309 for (i
= 0; i
< size
; i
++)
310 ob
->ob_digit
[i
] = r_short(p
);
316 extern double atof
PROTO((const char *));
319 if (r_string(buf
, (int)n
, p
) != n
) {
321 "EOF read where object expected");
325 return newfloatobject(atof(buf
));
330 v
= newsizedstringobject((char *)NULL
, n
);
332 if (r_string(getstringvalue(v
), (int)n
, p
) != n
) {
336 "EOF read where object expected");
343 v
= newtupleobject((int)n
);
346 for (i
= 0; i
< n
; i
++)
347 SETTUPLEITEM(v
, (int)i
, r_object(p
));
352 v
= newlistobject((int)n
);
355 for (i
= 0; i
< n
; i
++)
356 setlistitem(v
, (int)i
, r_object(p
));
369 dict2insert(v
, key
, val
);
377 object
*code
= r_object(p
);
378 object
*consts
= r_object(p
);
379 object
*names
= r_object(p
);
380 object
*filename
= r_object(p
);
381 object
*name
= r_object(p
);
382 if (!err_occurred()) {
383 v
= (object
*) newcodeobject(code
,
384 consts
, names
, filename
, name
);
398 err_setstr(TypeError
, "read unknown object");
418 if (err_occurred()) {
419 fprintf(stderr
, "XXX rd_object called with exception set\n");
423 return r_object(&rf
);
432 if (err_occurred()) {
433 fprintf(stderr
, "XXX rds_object called with exception set\n");
440 return r_object(&rf
);
443 /* And an interface for Python programs... */
446 marshal_dump(self
, args
)
453 if (!getargs(args
, "(OO)", &x
, &f
))
455 if (!is_fileobject(f
)) {
456 err_setstr(TypeError
, "marshal.dump() 2nd arg must be file");
459 wf
.fp
= getfilefile(f
);
461 wf
.ptr
= wf
.end
= NULL
;
468 marshal_load(self
, args
)
475 if (!getargs(args
, "O", &f
))
477 if (!is_fileobject(f
)) {
478 err_setstr(TypeError
, "marshal.load() arg must be file");
481 rf
.fp
= getfilefile(f
);
483 rf
.ptr
= rf
.end
= NULL
;
486 if (err_occurred()) {
494 marshal_dumps(self
, args
)
500 if (!getargs(args
, "O", &x
))
503 wf
.str
= newsizedstringobject((char *)NULL
, 50);
506 wf
.ptr
= GETSTRINGVALUE((stringobject
*)wf
.str
);
507 wf
.end
= wf
.ptr
+ getstringsize(wf
.str
);
510 resizestring(&wf
.str
,
511 (int) (wf
.ptr
- GETSTRINGVALUE((stringobject
*)wf
.str
)));
516 marshal_loads(self
, args
)
524 if (!getargs(args
, "s#", &s
, &n
))
532 if (err_occurred()) {
539 static struct methodlist marshal_methods
[] = {
540 {"dump", marshal_dump
},
541 {"load", marshal_load
},
542 {"dumps", marshal_dumps
},
543 {"loads", marshal_loads
},
544 {NULL
, NULL
} /* sentinel */
550 (void) initmodule("marshal", marshal_methods
);