blob: 94e6d3a7620428244fd30d92e08d1a868469920e [file] [log] [blame]
Guido van Rossumdce2e3d1991-06-04 19:42:30 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
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. */
29
30#include "allobjects.h"
31#include "longintrepr.h"
32#include "compile.h"
33#include "marshal.h"
34
35#include <errno.h>
Guido van Rossum065d71e1991-06-04 20:23:28 +000036extern int errno;
Guido van Rossumdce2e3d1991-06-04 19:42:30 +000037
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 '?'
49
50#define wr_byte(c, fp) putc((c), (fp))
51
52void
53wr_short(x, fp)
54 int x;
55 FILE *fp;
56{
57 wr_byte( x & 0xff, fp);
58 wr_byte((x>> 8) & 0xff, fp);
59}
60
61void
62wr_long(x, fp)
63 long x;
64 FILE *fp;
65{
66 wr_byte((int)( x & 0xff), fp);
67 wr_byte((int)((x>> 8) & 0xff), fp);
68 wr_byte((int)((x>>16) & 0xff), fp);
69 wr_byte((int)((x>>24) & 0xff), fp);
70}
71
72void
73wr_object(v, fp)
74 object *v;
75 FILE *fp;
76{
77 long i, n;
78
79 if (v == NULL)
80 wr_byte(TYPE_NULL, fp);
81 else if (v == None)
82 wr_byte(TYPE_NONE, fp);
83 else if (is_intobject(v)) {
84 wr_byte(TYPE_INT, fp);
85 wr_long(getintvalue(v), fp);
86 }
87 else if (is_longobject(v)) {
88 longobject *ob = (longobject *)v;
89 wr_byte(TYPE_LONG, fp);
90 n = ob->ob_size;
91 wr_long((long)n, fp);
92 if (n < 0)
93 n = -n;
94 for (i = 0; i < n; i++)
95 wr_short(ob->ob_digit[i], fp);
96 }
97 else if (is_floatobject(v)) {
98 extern void float_buf_repr PROTO((char *, floatobject *));
99 char buf[256]; /* Plenty to format any double */
100 float_buf_repr(buf, (floatobject *)v);
101 n = strlen(buf);
102 wr_byte(TYPE_FLOAT, fp);
103 wr_byte((int)n, fp);
104 fwrite(buf, 1, (int)n, fp);
105 }
106 else if (is_stringobject(v)) {
107 wr_byte(TYPE_STRING, fp);
108 n = getstringsize(v);
109 wr_long(n, fp);
110 fwrite(getstringvalue(v), 1, (int)n, fp);
111 }
112 else if (is_tupleobject(v)) {
113 wr_byte(TYPE_TUPLE, fp);
114 n = gettuplesize(v);
115 wr_long(n, fp);
116 for (i = 0; i < n; i++) {
117 wr_object(gettupleitem(v, (int)i), fp);
118 }
119 }
120 else if (is_listobject(v)) {
121 wr_byte(TYPE_LIST, fp);
122 n = getlistsize(v);
123 wr_long(n, fp);
124 for (i = 0; i < n; i++) {
125 wr_object(getlistitem(v, (int)i), fp);
126 }
127 }
128 else if (is_codeobject(v)) {
129 codeobject *co = (codeobject *)v;
130 wr_byte(TYPE_CODE, fp);
131 wr_object((object *)co->co_code, fp);
132 wr_object(co->co_consts, fp);
133 wr_object(co->co_names, fp);
134 wr_object(co->co_filename, fp);
135 }
136 else {
137 wr_byte(TYPE_UNKNOWN, fp);
138 }
139}
140
141#define rd_byte(fp) getc(fp)
142
143int
144rd_short(fp)
145 FILE *fp;
146{
147 register short x;
148 x = rd_byte(fp);
149 x |= rd_byte(fp) << 8;
150 /* XXX If your short is > 16 bits, add sign-extension here!!! */
151 return x;
152}
153
154long
155rd_long(fp)
156 FILE *fp;
157{
158 register long x;
159 x = rd_byte(fp);
160 x |= (long)rd_byte(fp) << 8;
161 x |= (long)rd_byte(fp) << 16;
162 x |= (long)rd_byte(fp) << 24;
163 /* XXX If your long is > 32 bits, add sign-extension here!!! */
164 return x;
165}
166
167object *
168rd_object(fp)
169 FILE *fp;
170{
171 object *v;
172 long i, n;
173 int type = rd_byte(fp);
174
175 switch (type) {
176
177 case EOF:
178 err_setstr(RuntimeError, "EOF read where object expected");
179 return NULL;
180
181 case TYPE_NULL:
182 return NULL;
183
184 case TYPE_NONE:
185 INCREF(None);
186 return None;
187
188 case TYPE_INT:
189 return newintobject(rd_long(fp));
190
191 case TYPE_LONG:
192 {
193 int size;
194 longobject *ob;
195 n = rd_long(fp);
196 size = n<0 ? -n : n;
197 ob = alloclongobject(size);
198 if (ob == NULL)
199 return NULL;
200 ob->ob_size = n;
201 for (i = 0; i < size; i++)
202 ob->ob_digit[i] = rd_short(fp);
203 return (object *)ob;
204 }
205
206 case TYPE_FLOAT:
207 {
208 extern double strtod();
209 char buf[256];
210 double res;
211 char *end;
212 n = rd_byte(fp);
213 if (fread(buf, 1, (int)n, fp) != n) {
214 err_setstr(RuntimeError,
215 "EOF read where object expected");
216 return NULL;
217 }
218 buf[n] = '\0';
219 errno = 0;
220 res = strtod(buf, &end);
221 if (*end != '\0') {
222 err_setstr(RuntimeError, "bad float syntax");
223 return NULL;
224 }
225 if (errno != 0) {
226 err_setstr(RuntimeError,
227 "float constant too large");
228 return NULL;
229 }
230 return newfloatobject(res);
231 }
232
233 case TYPE_STRING:
234 n = rd_long(fp);
235 v = newsizedstringobject((char *)NULL, n);
236 if (v != NULL) {
237 if (fread(getstringvalue(v), 1, (int)n, fp) != n) {
238 DECREF(v);
239 v = NULL;
240 err_setstr(RuntimeError,
241 "EOF read where object expected");
242 }
243 }
244 return v;
245
246 case TYPE_TUPLE:
247 n = rd_long(fp);
248 v = newtupleobject((int)n);
249 if (v == NULL)
250 return v;
251 for (i = 0; i < n; i++)
252 settupleitem(v, (int)i, rd_object(fp));
253 return v;
254
255 case TYPE_LIST:
256 n = rd_long(fp);
257 v = newlistobject((int)n);
258 if (v == NULL)
259 return v;
260 for (i = 0; i < n; i++)
261 setlistitem(v, (int)i, rd_object(fp));
262 return v;
263
264 case TYPE_CODE:
265 {
266 object *code = rd_object(fp);
267 object *consts = rd_object(fp);
268 object *names = rd_object(fp);
269 object *filename = rd_object(fp);
270 if (!err_occurred()) {
271 v = (object *) newcodeobject(code,
272 consts, names, filename);
273 }
274 else
275 v = NULL;
276 XDECREF(code);
277 XDECREF(consts);
278 XDECREF(names);
279 XDECREF(filename);
280
281 }
282 return v;
283
284 default:
285 err_setstr(RuntimeError, "read unknown object");
286 return NULL;
287
288 }
289}
290
291/* The rest is meant to test only... */
292
293static object *
294dump(self, args)
295 object *self;
296 object *args;
297{
298 object *f;
299 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
300 err_badarg();
301 return NULL;
302 }
303 f = gettupleitem(args, 1);
304 if (f == NULL || !is_fileobject(f)) {
305 err_badarg();
306 return NULL;
307 }
308 wr_object(gettupleitem(args, 0), getfilefile(f));
309 INCREF(None);
310 return None;
311}
312
313static object *
314load(self, f)
315 object *self;
316 object *f;
317{
318 object *v;
319 if (f == NULL || !is_fileobject(f)) {
320 err_badarg();
321 return NULL;
322 }
323 v = rd_object(getfilefile(f));
324 if (err_occurred()) {
325 XDECREF(v);
326 v = NULL;
327 }
328 return v;
329}
330
331static struct methodlist marshal_methods[] = {
332 {"dump", dump},
333 {"load", load},
334 {NULL, NULL} /* sentinel */
335};
336
337void
338initmarshal()
339{
340 (void) initmodule("marshal", marshal_methods);
341}