blob: 8e68e286f5e63f8634ece4b33b242ac9875c4824 [file] [log] [blame]
Guido van Rossumdce2e3d1991-06-04 19:42:30 +00001/***********************************************************
Guido van Rossumbab9d031992-04-05 14:26:55 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossumdce2e3d1991-06-04 19:42:30 +00003Netherlands.
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"
Guido van Rossum2807d191992-03-27 17:23:17 +000031#include "modsupport.h"
Guido van Rossumdce2e3d1991-06-04 19:42:30 +000032#include "longintrepr.h"
33#include "compile.h"
34#include "marshal.h"
35
36#include <errno.h>
Guido van Rossum065d71e1991-06-04 20:23:28 +000037extern int errno;
Guido van Rossumdce2e3d1991-06-04 19:42:30 +000038
39#define TYPE_NULL '0'
40#define TYPE_NONE 'N'
41#define TYPE_INT 'i'
42#define TYPE_FLOAT 'f'
43#define TYPE_LONG 'l'
44#define TYPE_STRING 's'
45#define TYPE_TUPLE '('
46#define TYPE_LIST '['
47#define TYPE_DICT '{'
48#define TYPE_CODE 'C'
49#define TYPE_UNKNOWN '?'
50
51#define wr_byte(c, fp) putc((c), (fp))
52
53void
54wr_short(x, fp)
55 int x;
56 FILE *fp;
57{
58 wr_byte( x & 0xff, fp);
59 wr_byte((x>> 8) & 0xff, fp);
60}
61
62void
63wr_long(x, fp)
64 long x;
65 FILE *fp;
66{
67 wr_byte((int)( x & 0xff), fp);
68 wr_byte((int)((x>> 8) & 0xff), fp);
69 wr_byte((int)((x>>16) & 0xff), fp);
70 wr_byte((int)((x>>24) & 0xff), fp);
71}
72
73void
74wr_object(v, fp)
75 object *v;
76 FILE *fp;
77{
78 long i, n;
79
80 if (v == NULL)
81 wr_byte(TYPE_NULL, fp);
82 else if (v == None)
83 wr_byte(TYPE_NONE, fp);
84 else if (is_intobject(v)) {
85 wr_byte(TYPE_INT, fp);
86 wr_long(getintvalue(v), fp);
87 }
88 else if (is_longobject(v)) {
89 longobject *ob = (longobject *)v;
90 wr_byte(TYPE_LONG, fp);
91 n = ob->ob_size;
92 wr_long((long)n, fp);
93 if (n < 0)
94 n = -n;
95 for (i = 0; i < n; i++)
96 wr_short(ob->ob_digit[i], fp);
97 }
98 else if (is_floatobject(v)) {
99 extern void float_buf_repr PROTO((char *, floatobject *));
100 char buf[256]; /* Plenty to format any double */
101 float_buf_repr(buf, (floatobject *)v);
102 n = strlen(buf);
103 wr_byte(TYPE_FLOAT, fp);
104 wr_byte((int)n, fp);
105 fwrite(buf, 1, (int)n, fp);
106 }
107 else if (is_stringobject(v)) {
108 wr_byte(TYPE_STRING, fp);
109 n = getstringsize(v);
110 wr_long(n, fp);
111 fwrite(getstringvalue(v), 1, (int)n, fp);
112 }
113 else if (is_tupleobject(v)) {
114 wr_byte(TYPE_TUPLE, fp);
115 n = gettuplesize(v);
116 wr_long(n, fp);
117 for (i = 0; i < n; i++) {
118 wr_object(gettupleitem(v, (int)i), fp);
119 }
120 }
121 else if (is_listobject(v)) {
122 wr_byte(TYPE_LIST, fp);
123 n = getlistsize(v);
124 wr_long(n, fp);
125 for (i = 0; i < n; i++) {
126 wr_object(getlistitem(v, (int)i), fp);
127 }
128 }
Guido van Rossum64b45521991-06-07 13:58:22 +0000129 else if (is_dictobject(v)) {
130 wr_byte(TYPE_DICT, fp);
131 /* This one is NULL object terminated! */
132 n = getdictsize(v);
133 for (i = 0; i < n; i++) {
134 object *key, *val;
Guido van Rossum64b45521991-06-07 13:58:22 +0000135 key = getdict2key(v, (int)i);
136 if (key != NULL) {
Guido van Rossumb8813141991-08-16 09:01:55 +0000137 val = dict2lookup(v, key); /* Can't be NULL */
Guido van Rossum64b45521991-06-07 13:58:22 +0000138 wr_object(key, fp);
139 wr_object(val, fp);
140 }
141 }
142 wr_object((object *)NULL, fp);
143 }
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000144 else if (is_codeobject(v)) {
145 codeobject *co = (codeobject *)v;
146 wr_byte(TYPE_CODE, fp);
147 wr_object((object *)co->co_code, fp);
148 wr_object(co->co_consts, fp);
149 wr_object(co->co_names, fp);
150 wr_object(co->co_filename, fp);
151 }
152 else {
153 wr_byte(TYPE_UNKNOWN, fp);
154 }
155}
156
157#define rd_byte(fp) getc(fp)
158
159int
160rd_short(fp)
161 FILE *fp;
162{
163 register short x;
164 x = rd_byte(fp);
165 x |= rd_byte(fp) << 8;
166 /* XXX If your short is > 16 bits, add sign-extension here!!! */
167 return x;
168}
169
170long
171rd_long(fp)
172 FILE *fp;
173{
174 register long x;
175 x = rd_byte(fp);
176 x |= (long)rd_byte(fp) << 8;
177 x |= (long)rd_byte(fp) << 16;
178 x |= (long)rd_byte(fp) << 24;
179 /* XXX If your long is > 32 bits, add sign-extension here!!! */
180 return x;
181}
182
183object *
184rd_object(fp)
185 FILE *fp;
186{
187 object *v;
188 long i, n;
189 int type = rd_byte(fp);
190
191 switch (type) {
192
193 case EOF:
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000194 err_setstr(EOFError, "EOF read where object expected");
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000195 return NULL;
196
197 case TYPE_NULL:
198 return NULL;
199
200 case TYPE_NONE:
201 INCREF(None);
202 return None;
203
204 case TYPE_INT:
205 return newintobject(rd_long(fp));
206
207 case TYPE_LONG:
208 {
209 int size;
210 longobject *ob;
211 n = rd_long(fp);
212 size = n<0 ? -n : n;
213 ob = alloclongobject(size);
214 if (ob == NULL)
215 return NULL;
216 ob->ob_size = n;
217 for (i = 0; i < size; i++)
218 ob->ob_digit[i] = rd_short(fp);
219 return (object *)ob;
220 }
221
222 case TYPE_FLOAT:
223 {
Guido van Rossum2807d191992-03-27 17:23:17 +0000224 extern double strtod PROTO((const char *, char **));
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000225 char buf[256];
226 double res;
227 char *end;
228 n = rd_byte(fp);
229 if (fread(buf, 1, (int)n, fp) != n) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000230 err_setstr(EOFError,
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000231 "EOF read where object expected");
232 return NULL;
233 }
234 buf[n] = '\0';
235 errno = 0;
236 res = strtod(buf, &end);
237 if (*end != '\0') {
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000238 err_setstr(ValueError, "bad float syntax");
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000239 return NULL;
240 }
241 if (errno != 0) {
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000242 err_setstr(ValueError,
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000243 "float constant too large");
244 return NULL;
245 }
246 return newfloatobject(res);
247 }
248
249 case TYPE_STRING:
250 n = rd_long(fp);
251 v = newsizedstringobject((char *)NULL, n);
252 if (v != NULL) {
253 if (fread(getstringvalue(v), 1, (int)n, fp) != n) {
254 DECREF(v);
255 v = NULL;
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000256 err_setstr(EOFError,
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000257 "EOF read where object expected");
258 }
259 }
260 return v;
261
262 case TYPE_TUPLE:
263 n = rd_long(fp);
264 v = newtupleobject((int)n);
265 if (v == NULL)
266 return v;
267 for (i = 0; i < n; i++)
268 settupleitem(v, (int)i, rd_object(fp));
269 return v;
270
271 case TYPE_LIST:
272 n = rd_long(fp);
273 v = newlistobject((int)n);
274 if (v == NULL)
275 return v;
276 for (i = 0; i < n; i++)
277 setlistitem(v, (int)i, rd_object(fp));
278 return v;
279
Guido van Rossum64b45521991-06-07 13:58:22 +0000280 case TYPE_DICT:
281 v = newdictobject();
282 if (v == NULL)
283 return NULL;
284 for (;;) {
285 object *key, *val;
286 key = rd_object(fp);
287 if (key == NULL)
288 break;
289 val = rd_object(fp);
290 dict2insert(v, key, val);
291 DECREF(key);
292 XDECREF(val);
293 }
294 return v;
295
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000296 case TYPE_CODE:
297 {
298 object *code = rd_object(fp);
299 object *consts = rd_object(fp);
300 object *names = rd_object(fp);
301 object *filename = rd_object(fp);
302 if (!err_occurred()) {
303 v = (object *) newcodeobject(code,
304 consts, names, filename);
305 }
306 else
307 v = NULL;
308 XDECREF(code);
309 XDECREF(consts);
310 XDECREF(names);
311 XDECREF(filename);
312
313 }
314 return v;
315
316 default:
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000317 err_setstr(TypeError, "read unknown object");
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000318 return NULL;
319
320 }
321}
322
Guido van Rossum64b45521991-06-07 13:58:22 +0000323/* And an interface for Python programs... */
Guido van Rossumdce2e3d1991-06-04 19:42:30 +0000324
325static object *
326dump(self, args)
327 object *self;
328 object *args;
329{
330 object *f;
331 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
332 err_badarg();
333 return NULL;
334 }
335 f = gettupleitem(args, 1);
336 if (f == NULL || !is_fileobject(f)) {
337 err_badarg();
338 return NULL;
339 }
340 wr_object(gettupleitem(args, 0), getfilefile(f));
341 INCREF(None);
342 return None;
343}
344
345static object *
346load(self, f)
347 object *self;
348 object *f;
349{
350 object *v;
351 if (f == NULL || !is_fileobject(f)) {
352 err_badarg();
353 return NULL;
354 }
355 v = rd_object(getfilefile(f));
356 if (err_occurred()) {
357 XDECREF(v);
358 v = NULL;
359 }
360 return v;
361}
362
363static struct methodlist marshal_methods[] = {
364 {"dump", dump},
365 {"load", load},
366 {NULL, NULL} /* sentinel */
367};
368
369void
370initmarshal()
371{
372 (void) initmodule("marshal", marshal_methods);
373}