blob: b3986a80a6cd5ce8d889343894720fa31b8827f6 [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>
36
37#define TYPE_NULL '0'
38#define TYPE_NONE 'N'
39#define TYPE_INT 'i'
40#define TYPE_FLOAT 'f'
41#define TYPE_LONG 'l'
42#define TYPE_STRING 's'
43#define TYPE_TUPLE '('
44#define TYPE_LIST '['
45#define TYPE_DICT '{'
46#define TYPE_CODE 'C'
47#define TYPE_UNKNOWN '?'
48
49#define wr_byte(c, fp) putc((c), (fp))
50
51void
52wr_short(x, fp)
53 int x;
54 FILE *fp;
55{
56 wr_byte( x & 0xff, fp);
57 wr_byte((x>> 8) & 0xff, fp);
58}
59
60void
61wr_long(x, fp)
62 long x;
63 FILE *fp;
64{
65 wr_byte((int)( x & 0xff), fp);
66 wr_byte((int)((x>> 8) & 0xff), fp);
67 wr_byte((int)((x>>16) & 0xff), fp);
68 wr_byte((int)((x>>24) & 0xff), fp);
69}
70
71void
72wr_object(v, fp)
73 object *v;
74 FILE *fp;
75{
76 long i, n;
77
78 if (v == NULL)
79 wr_byte(TYPE_NULL, fp);
80 else if (v == None)
81 wr_byte(TYPE_NONE, fp);
82 else if (is_intobject(v)) {
83 wr_byte(TYPE_INT, fp);
84 wr_long(getintvalue(v), fp);
85 }
86 else if (is_longobject(v)) {
87 longobject *ob = (longobject *)v;
88 wr_byte(TYPE_LONG, fp);
89 n = ob->ob_size;
90 wr_long((long)n, fp);
91 if (n < 0)
92 n = -n;
93 for (i = 0; i < n; i++)
94 wr_short(ob->ob_digit[i], fp);
95 }
96 else if (is_floatobject(v)) {
97 extern void float_buf_repr PROTO((char *, floatobject *));
98 char buf[256]; /* Plenty to format any double */
99 float_buf_repr(buf, (floatobject *)v);
100 n = strlen(buf);
101 wr_byte(TYPE_FLOAT, fp);
102 wr_byte((int)n, fp);
103 fwrite(buf, 1, (int)n, fp);
104 }
105 else if (is_stringobject(v)) {
106 wr_byte(TYPE_STRING, fp);
107 n = getstringsize(v);
108 wr_long(n, fp);
109 fwrite(getstringvalue(v), 1, (int)n, fp);
110 }
111 else if (is_tupleobject(v)) {
112 wr_byte(TYPE_TUPLE, fp);
113 n = gettuplesize(v);
114 wr_long(n, fp);
115 for (i = 0; i < n; i++) {
116 wr_object(gettupleitem(v, (int)i), fp);
117 }
118 }
119 else if (is_listobject(v)) {
120 wr_byte(TYPE_LIST, fp);
121 n = getlistsize(v);
122 wr_long(n, fp);
123 for (i = 0; i < n; i++) {
124 wr_object(getlistitem(v, (int)i), fp);
125 }
126 }
127 else if (is_codeobject(v)) {
128 codeobject *co = (codeobject *)v;
129 wr_byte(TYPE_CODE, fp);
130 wr_object((object *)co->co_code, fp);
131 wr_object(co->co_consts, fp);
132 wr_object(co->co_names, fp);
133 wr_object(co->co_filename, fp);
134 }
135 else {
136 wr_byte(TYPE_UNKNOWN, fp);
137 }
138}
139
140#define rd_byte(fp) getc(fp)
141
142int
143rd_short(fp)
144 FILE *fp;
145{
146 register short x;
147 x = rd_byte(fp);
148 x |= rd_byte(fp) << 8;
149 /* XXX If your short is > 16 bits, add sign-extension here!!! */
150 return x;
151}
152
153long
154rd_long(fp)
155 FILE *fp;
156{
157 register long x;
158 x = rd_byte(fp);
159 x |= (long)rd_byte(fp) << 8;
160 x |= (long)rd_byte(fp) << 16;
161 x |= (long)rd_byte(fp) << 24;
162 /* XXX If your long is > 32 bits, add sign-extension here!!! */
163 return x;
164}
165
166object *
167rd_object(fp)
168 FILE *fp;
169{
170 object *v;
171 long i, n;
172 int type = rd_byte(fp);
173
174 switch (type) {
175
176 case EOF:
177 err_setstr(RuntimeError, "EOF read where object expected");
178 return NULL;
179
180 case TYPE_NULL:
181 return NULL;
182
183 case TYPE_NONE:
184 INCREF(None);
185 return None;
186
187 case TYPE_INT:
188 return newintobject(rd_long(fp));
189
190 case TYPE_LONG:
191 {
192 int size;
193 longobject *ob;
194 n = rd_long(fp);
195 size = n<0 ? -n : n;
196 ob = alloclongobject(size);
197 if (ob == NULL)
198 return NULL;
199 ob->ob_size = n;
200 for (i = 0; i < size; i++)
201 ob->ob_digit[i] = rd_short(fp);
202 return (object *)ob;
203 }
204
205 case TYPE_FLOAT:
206 {
207 extern double strtod();
208 char buf[256];
209 double res;
210 char *end;
211 n = rd_byte(fp);
212 if (fread(buf, 1, (int)n, fp) != n) {
213 err_setstr(RuntimeError,
214 "EOF read where object expected");
215 return NULL;
216 }
217 buf[n] = '\0';
218 errno = 0;
219 res = strtod(buf, &end);
220 if (*end != '\0') {
221 err_setstr(RuntimeError, "bad float syntax");
222 return NULL;
223 }
224 if (errno != 0) {
225 err_setstr(RuntimeError,
226 "float constant too large");
227 return NULL;
228 }
229 return newfloatobject(res);
230 }
231
232 case TYPE_STRING:
233 n = rd_long(fp);
234 v = newsizedstringobject((char *)NULL, n);
235 if (v != NULL) {
236 if (fread(getstringvalue(v), 1, (int)n, fp) != n) {
237 DECREF(v);
238 v = NULL;
239 err_setstr(RuntimeError,
240 "EOF read where object expected");
241 }
242 }
243 return v;
244
245 case TYPE_TUPLE:
246 n = rd_long(fp);
247 v = newtupleobject((int)n);
248 if (v == NULL)
249 return v;
250 for (i = 0; i < n; i++)
251 settupleitem(v, (int)i, rd_object(fp));
252 return v;
253
254 case TYPE_LIST:
255 n = rd_long(fp);
256 v = newlistobject((int)n);
257 if (v == NULL)
258 return v;
259 for (i = 0; i < n; i++)
260 setlistitem(v, (int)i, rd_object(fp));
261 return v;
262
263 case TYPE_CODE:
264 {
265 object *code = rd_object(fp);
266 object *consts = rd_object(fp);
267 object *names = rd_object(fp);
268 object *filename = rd_object(fp);
269 if (!err_occurred()) {
270 v = (object *) newcodeobject(code,
271 consts, names, filename);
272 }
273 else
274 v = NULL;
275 XDECREF(code);
276 XDECREF(consts);
277 XDECREF(names);
278 XDECREF(filename);
279
280 }
281 return v;
282
283 default:
284 err_setstr(RuntimeError, "read unknown object");
285 return NULL;
286
287 }
288}
289
290/* The rest is meant to test only... */
291
292static object *
293dump(self, args)
294 object *self;
295 object *args;
296{
297 object *f;
298 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
299 err_badarg();
300 return NULL;
301 }
302 f = gettupleitem(args, 1);
303 if (f == NULL || !is_fileobject(f)) {
304 err_badarg();
305 return NULL;
306 }
307 wr_object(gettupleitem(args, 0), getfilefile(f));
308 INCREF(None);
309 return None;
310}
311
312static object *
313load(self, f)
314 object *self;
315 object *f;
316{
317 object *v;
318 if (f == NULL || !is_fileobject(f)) {
319 err_badarg();
320 return NULL;
321 }
322 v = rd_object(getfilefile(f));
323 if (err_occurred()) {
324 XDECREF(v);
325 v = NULL;
326 }
327 return v;
328}
329
330static struct methodlist marshal_methods[] = {
331 {"dump", dump},
332 {"load", load},
333 {NULL, NULL} /* sentinel */
334};
335
336void
337initmarshal()
338{
339 (void) initmodule("marshal", marshal_methods);
340}