1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
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
);
151 w_string(buf
, (int)n
, p
);
153 else if (is_stringobject(v
)) {
154 w_byte(TYPE_STRING
, p
);
155 n
= getstringsize(v
);
157 w_string(getstringvalue(v
), (int)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
, (int)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
, (int)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 r_byte(p) ((p)->fp ? getc((p)->fp) \
224 : ((p)->ptr != (p)->end) ? \
225 (unsigned char)*(p)->ptr++ : EOF)
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!!! */
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!!! */
272 int type
= r_byte(p
);
277 err_setstr(EOFError
, "EOF read where object expected");
288 return newintobject(r_long(p
));
296 ob
= alloclongobject(size
);
300 for (i
= 0; i
< size
; i
++)
301 ob
->ob_digit
[i
] = r_short(p
);
307 extern double strtod
PROTO((const char *, char **));
312 if (r_string(buf
, (int)n
, p
) != n
) {
314 "EOF read where object expected");
319 res
= strtod(buf
, &end
);
321 err_setstr(ValueError
, "bad float syntax");
325 err_setstr(ValueError
,
326 "float constant too large");
329 return newfloatobject(res
);
334 v
= newsizedstringobject((char *)NULL
, n
);
336 if (r_string(getstringvalue(v
), (int)n
, p
) != n
) {
340 "EOF read where object expected");
347 v
= newtupleobject((int)n
);
350 for (i
= 0; i
< n
; i
++)
351 settupleitem(v
, (int)i
, r_object(p
));
356 v
= newlistobject((int)n
);
359 for (i
= 0; i
< n
; i
++)
360 setlistitem(v
, (int)i
, r_object(p
));
373 dict2insert(v
, key
, val
);
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
);
401 err_setstr(TypeError
, "read unknown object");
422 return r_object(&rf
);
435 return r_object(&rf
);
438 /* And an interface for Python programs... */
441 marshal_dump(self
, args
)
448 if (!getargs(args
, "(OO)", &x
, &f
))
450 if (!is_fileobject(f
)) {
451 err_setstr(TypeError
, "marshal.dump() 2nd arg must be file");
454 wf
.fp
= getfilefile(f
);
456 wf
.ptr
= wf
.end
= NULL
;
463 marshal_load(self
, args
)
470 if (!getargs(args
, "O", &f
))
472 if (!is_fileobject(f
)) {
473 err_setstr(TypeError
, "marshal.load() arg must be file");
476 rf
.fp
= getfilefile(f
);
478 rf
.ptr
= rf
.end
= NULL
;
481 if (err_occurred()) {
489 marshal_dumps(self
, args
)
495 if (!getargs(args
, "O", &x
))
498 wf
.str
= newsizedstringobject((char *)NULL
, 50);
501 wf
.ptr
= GETSTRINGVALUE((stringobject
*)wf
.str
);
502 wf
.end
= wf
.ptr
+ getstringsize(wf
.str
);
505 resizestring(&wf
.str
,
506 (int) (wf
.ptr
- GETSTRINGVALUE((stringobject
*)wf
.str
)));
511 marshal_loads(self
, args
)
519 if (!getargs(args
, "s#", &s
, &n
))
527 if (err_occurred()) {
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 */
545 (void) initmodule("marshal", marshal_methods
);