blob: 5eb7922c6c3f775a4f5c139ea4d2131b299e346b [file] [log] [blame]
Guido van Rossum02975121992-08-17 08:55:12 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum02975121992-08-17 08:55:12 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum02975121992-08-17 08:55:12 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum02975121992-08-17 08:55:12 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum02975121992-08-17 08:55:12 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum02975121992-08-17 08:55:12 +000029
30******************************************************************/
31
32/* struct module -- pack values into and (out of) strings */
33
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000034/* New version supporting byte order, alignment and size options,
35 character strings, and unsigned numbers */
36
Barry Warsaw30695fa1996-12-12 23:32:31 +000037#include "Python.h"
Guido van Rossum02975121992-08-17 08:55:12 +000038
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000039#include <limits.h>
40
41
42/* Exception */
43
Barry Warsaw30695fa1996-12-12 23:32:31 +000044static PyObject *StructError;
Guido van Rossum02975121992-08-17 08:55:12 +000045
46
47/* Define various structs to figure out the alignments of types */
48
Jack Jansen971e1df1995-02-02 14:29:10 +000049#ifdef __MWERKS__
50/*
51** XXXX We have a problem here. There are no unique alignment rules
52** on the PowerPC mac.
53*/
54#ifdef __powerc
55#pragma options align=mac68k
56#endif
57#endif /* __MWERKS__ */
58
Guido van Rossum02975121992-08-17 08:55:12 +000059typedef struct { char c; short x; } s_short;
60typedef struct { char c; int x; } s_int;
61typedef struct { char c; long x; } s_long;
62typedef struct { char c; float x; } s_float;
63typedef struct { char c; double x; } s_double;
64
65#define SHORT_ALIGN (sizeof(s_short) - sizeof(short))
66#define INT_ALIGN (sizeof(s_int) - sizeof(int))
67#define LONG_ALIGN (sizeof(s_long) - sizeof(long))
68#define FLOAT_ALIGN (sizeof(s_float) - sizeof(float))
69#define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))
70
Jack Jansen971e1df1995-02-02 14:29:10 +000071#ifdef __powerc
72#pragma options align=reset
73#endif
74
Guido van Rossum02975121992-08-17 08:55:12 +000075
Guido van Rossum60c50611996-12-31 16:29:52 +000076/* Global that will contain 2**<bits-per-long> */
77
78static PyObject *offset = NULL;
79
80
81/* Helper to create 2**<bits-per-long> */
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000082/* XXX This assumes 2's complement arithmetic */
83
84static PyObject *
Guido van Rossum60c50611996-12-31 16:29:52 +000085init_offset()
86{
87 PyObject *result = NULL;
88 PyObject *one = PyLong_FromLong(1L);
89 PyObject *shiftcount = PyLong_FromLong(8 * sizeof(long));
90 if (one == NULL || shiftcount == NULL)
91 goto finally;
92 result = PyNumber_Lshift(one, shiftcount);
93 finally:
94 Py_XDECREF(one);
95 Py_XDECREF(shiftcount);
96 return result;
97}
98
99
100/* Helper to add offset to a number */
101
102static PyObject *
103add_offset(v)
104 PyObject *v;
105{
106 PyObject *result = NULL;
107 if (offset == NULL) {
108 if ((offset = init_offset()) == NULL)
109 goto finally;
110 }
111 result = PyNumber_Add(v, offset);
112 finally:
113 return result;
114}
115
116
117/* Same, but subtracting */
118
119static PyObject *
120sub_offset(v)
121 PyObject *v;
122{
123 PyObject *result = NULL;
124 if (offset == NULL) {
125 if ((offset = init_offset()) == NULL)
126 goto finally;
127 }
128 result = PyNumber_Subtract(v, offset);
129 finally:
130 return result;
131}
132
133
134/* Helper routine to turn a (signed) long into an unsigned long */
135
136static PyObject *
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000137make_ulong(x)
138 long x;
139{
140 PyObject *v = PyLong_FromLong(x);
141 if (x < 0 && v != NULL) {
Guido van Rossum60c50611996-12-31 16:29:52 +0000142 PyObject *w = add_offset(v);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000143 Py_DECREF(v);
Guido van Rossum60c50611996-12-31 16:29:52 +0000144 return w;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000145 }
146 else
147 return v;
148}
149
150/* Helper routine to get a Python integer and raise the appropriate error
151 if it isn't one */
152
153static int
154get_long(v, p)
155 PyObject *v;
156 long *p;
157{
158 long x = PyInt_AsLong(v);
159 if (x == -1 && PyErr_Occurred()) {
160 if (PyErr_Occurred() == PyExc_TypeError)
161 PyErr_SetString(StructError,
162 "required argument is not an integer");
163 return -1;
164 }
165 *p = x;
166 return 0;
167}
168
169
Guido van Rossum60c50611996-12-31 16:29:52 +0000170/* Same, but handling unsigned long */
171
172static int
173get_ulong(v, p)
174 PyObject *v;
175 unsigned long *p;
176{
177 long x = PyInt_AsLong(v);
178 PyObject *exc;
179 if (x == -1 && (exc = PyErr_Occurred()) != NULL) {
180 if (exc == PyExc_OverflowError) {
181 /* Try again after subtracting offset */
182 PyObject *w;
183 PyErr_Clear();
184 if ((w = sub_offset(v)) == NULL)
185 return -1;
186 x = PyInt_AsLong(w);
187 Py_DECREF(w);
188 if (x != -1 || (exc = PyErr_Occurred()) == NULL)
189 goto okay;
190 }
191 if (exc == PyExc_TypeError)
192 PyErr_SetString(StructError,
193 "required argument is not an integer");
194 else
195 return -1;
196 }
197 okay:
198 *p = x;
199 return 0;
200}
201
202
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000203/* The translation function for each format character is table driven */
204
205typedef struct _formatdef {
206 char format;
207 int size;
208 int alignment;
209 PyObject* (*unpack) Py_PROTO((const char *,
210 const struct _formatdef *));
211 int (*pack) Py_PROTO((char *,
212 PyObject *,
213 const struct _formatdef *));
214} formatdef;
215
216static PyObject *
217nu_char(p, f)
218 const char *p;
219 const formatdef *f;
220{
221 return PyString_FromStringAndSize(p, 1);
222}
223
224static PyObject *
225nu_byte(p, f)
226 const char *p;
227 const formatdef *f;
228{
229 return PyInt_FromLong((long) *(signed char *)p);
230}
231
232static PyObject *
233nu_ubyte(p, f)
234 const char *p;
235 const formatdef *f;
236{
237 return PyInt_FromLong((long) *(unsigned char *)p);
238}
239
240static PyObject *
241nu_short(p, f)
242 const char *p;
243 const formatdef *f;
244{
245 return PyInt_FromLong((long) *(short *)p);
246}
247
248static PyObject *
249nu_ushort(p, f)
250 const char *p;
251 const formatdef *f;
252{
253 return PyInt_FromLong((long) *(unsigned short *)p);
254}
255
256static PyObject *
257nu_int(p, f)
258 const char *p;
259 const formatdef *f;
260{
261 return PyInt_FromLong((long) *(int *)p);
262}
263
264static PyObject *
265nu_uint(p, f)
266 const char *p;
267 const formatdef *f;
268{
269 unsigned int x = *(unsigned int *)p;
270#if INT_MAX == LONG_MAX
271 return make_ulong((long)x);
272#else
273 return PyInt_FromLong((long)x);
274#endif
275}
276
277static PyObject *
278nu_long(p, f)
279 const char *p;
280 const formatdef *f;
281{
282 return PyInt_FromLong(*(long *)p);
283}
284
285static PyObject *
286nu_ulong(p, f)
287 const char *p;
288 const formatdef *f;
289{
290 return make_ulong(*(long *)p);
291}
292
293static PyObject *
294nu_float(p, f)
295 const char *p;
296 const formatdef *f;
297{
298 float x;
299 memcpy((char *)&x, p, sizeof(float));
300 return PyFloat_FromDouble((double)x);
301}
302
303static PyObject *
304nu_double(p, f)
305 const char *p;
306 const formatdef *f;
307{
308 double x;
309 memcpy((char *)&x, p, sizeof(double));
310 return PyFloat_FromDouble(x);
311}
312
313static int
314np_byte(p, v, f)
315 char *p;
316 PyObject *v;
317 const formatdef *f;
318{
319 long x;
320 if (get_long(v, &x) < 0)
321 return -1;
322 *p = x;
323 return 0;
324}
325
326static int
327np_char(p, v, f)
328 char *p;
329 PyObject *v;
330 const formatdef *f;
331{
332 if (!PyString_Check(v) || PyString_Size(v) != 1) {
333 PyErr_SetString(StructError,
334 "char format require string of length 1");
335 return -1;
336 }
337 *p = *PyString_AsString(v);
338 return 0;
339}
340
341static int
342np_short(p, v, f)
343 char *p;
344 PyObject *v;
345 const formatdef *f;
346{
347 long x;
348 if (get_long(v, &x) < 0)
349 return -1;
350 * (short *)p = x;
351 return 0;
352}
353
354static int
355np_int(p, v, f)
356 char *p;
357 PyObject *v;
358 const formatdef *f;
359{
360 long x;
361 if (get_long(v, &x) < 0)
362 return -1;
363 * (int *)p = x;
364 return 0;
365}
366
367static int
Guido van Rossum60c50611996-12-31 16:29:52 +0000368np_uint(p, v, f)
369 char *p;
370 PyObject *v;
371 const formatdef *f;
372{
373 unsigned long x;
374 if (get_ulong(v, &x) < 0)
375 return -1;
376 * (unsigned int *)p = x;
377 return 0;
378}
379
380static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000381np_long(p, v, f)
382 char *p;
383 PyObject *v;
384 const formatdef *f;
385{
386 long x;
387 if (get_long(v, &x) < 0)
388 return -1;
389 * (long *)p = x;
390 return 0;
391}
392
393static int
Guido van Rossum60c50611996-12-31 16:29:52 +0000394np_ulong(p, v, f)
395 char *p;
396 PyObject *v;
397 const formatdef *f;
398{
399 unsigned long x;
400 if (get_ulong(v, &x) < 0)
401 return -1;
402 * (unsigned long *)p = x;
403 return 0;
404}
405
406static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000407np_float(p, v, f)
408 char *p;
409 PyObject *v;
410 const formatdef *f;
411{
412 float x = (float)PyFloat_AsDouble(v);
413 if (x == -1 && PyErr_Occurred()) {
414 PyErr_SetString(StructError,
415 "required argument is not a float");
416 return -1;
417 }
418 memcpy(p, (char *)&x, sizeof(float));
419 return 0;
420}
421
422static int
423np_double(p, v, f)
424 char *p;
425 PyObject *v;
426 const formatdef *f;
427{
428 double x = PyFloat_AsDouble(v);
429 if (x == -1 && PyErr_Occurred()) {
430 PyErr_SetString(StructError,
431 "required argument is not a float");
432 return -1;
433 }
434 memcpy(p, (char *)&x, sizeof(double));
435 return 0;
436}
437
438static formatdef native_table[] = {
439 {'x', sizeof(char), 0, NULL},
440 {'b', sizeof(char), 0, nu_byte, np_byte},
441 {'B', sizeof(char), 0, nu_ubyte, np_byte},
442 {'c', sizeof(char), 0, nu_char, np_char},
443 {'s', sizeof(char), 0, NULL},
444 {'h', sizeof(short), SHORT_ALIGN, nu_short, np_short},
445 {'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_short},
446 {'i', sizeof(int), INT_ALIGN, nu_int, np_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000447 {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000448 {'l', sizeof(long), LONG_ALIGN, nu_long, np_long},
Guido van Rossum60c50611996-12-31 16:29:52 +0000449 {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000450 {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
451 {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
452 {0}
453};
454
455static PyObject *
456bu_int(p, f)
457 const char *p;
458 const formatdef *f;
459{
460 long x = 0;
461 int i = f->size;
462 do {
463 x = (x<<8) | (*p++ & 0xFF);
464 } while (--i > 0);
465 i = 8*(sizeof(long) - f->size);
466 if (i) {
467 x <<= i;
468 x >>= i;
469 }
470 return PyInt_FromLong(x);
471}
472
473static PyObject *
474bu_uint(p, f)
475 const char *p;
476 const formatdef *f;
477{
478 long x = 0;
479 int i = f->size;
480 do {
481 x = (x<<8) | (*p++ & 0xFF);
482 } while (--i > 0);
483 if (f->size == sizeof(long))
484 return make_ulong(x);
485 else
486 return PyLong_FromLong(x);
487}
488
489static int
490bp_int(p, v, f)
491 char *p;
492 PyObject *v;
493 const formatdef *f;
494{
495 long x;
496 int i;
497 if (get_long(v, &x) < 0)
498 return -1;
499 i = f->size;
500 do {
501 p[--i] = x;
502 x >>= 8;
503 } while (i > 0);
504 return 0;
505}
506
Guido van Rossum60c50611996-12-31 16:29:52 +0000507static int
508bp_uint(p, v, f)
509 char *p;
510 PyObject *v;
511 const formatdef *f;
512{
513 unsigned long x;
514 int i;
515 if (get_ulong(v, &x) < 0)
516 return -1;
517 i = f->size;
518 do {
519 p[--i] = x;
520 x >>= 8;
521 } while (i > 0);
522 return 0;
523}
524
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000525static formatdef bigendian_table[] = {
526 {'x', 1, 0, NULL},
527 {'b', 1, 0, bu_int, bp_int},
528 {'B', 1, 0, bu_uint, bp_int},
529 {'c', 1, 0, nu_char, np_char},
530 {'s', 1, 0, NULL},
531 {'h', 2, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000532 {'H', 2, 0, bu_uint, bp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000533 {'i', 4, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000534 {'I', 4, 0, bu_uint, bp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000535 {'l', 4, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000536 {'L', 4, 0, bu_uint, bp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000537 /* No float and double! */
538 {0}
539};
540
541static PyObject *
542lu_int(p, f)
543 const char *p;
544 const formatdef *f;
545{
546 long x = 0;
547 int i = f->size;
548 do {
549 x = (x<<8) | (p[--i] & 0xFF);
550 } while (i > 0);
551 i = 8*(sizeof(long) - f->size);
552 if (i) {
553 x <<= i;
554 x >>= i;
555 }
556 return PyInt_FromLong(x);
557}
558
559static PyObject *
560lu_uint(p, f)
561 const char *p;
562 const formatdef *f;
563{
564 long x = 0;
565 int i = f->size;
566 do {
567 x = (x<<8) | (p[--i] & 0xFF);
568 } while (i > 0);
569 if (f->size == sizeof(long))
570 return make_ulong(x);
571 else
572 return PyLong_FromLong(x);
573}
574
575static int
576lp_int(p, v, f)
577 char *p;
578 PyObject *v;
579 const formatdef *f;
580{
581 long x;
582 int i;
583 if (get_long(v, &x) < 0)
584 return -1;
585 i = f->size;
586 do {
587 *p++ = x;
588 x >>= 8;
589 } while (--i > 0);
590 return 0;
591}
592
Guido van Rossum60c50611996-12-31 16:29:52 +0000593static int
594lp_uint(p, v, f)
595 char *p;
596 PyObject *v;
597 const formatdef *f;
598{
599 unsigned long x;
600 int i;
601 if (get_ulong(v, &x) < 0)
602 return -1;
603 i = f->size;
604 do {
605 *p++ = x;
606 x >>= 8;
607 } while (--i > 0);
608 return 0;
609}
610
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000611static formatdef lilendian_table[] = {
612 {'x', 1, 0, NULL},
613 {'b', 1, 0, lu_int, lp_int},
614 {'B', 1, 0, lu_uint, lp_int},
615 {'c', 1, 0, nu_char, np_char},
616 {'s', 1, 0, NULL},
617 {'h', 2, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000618 {'H', 2, 0, lu_uint, lp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000619 {'i', 4, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000620 {'I', 4, 0, lu_uint, lp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000621 {'l', 4, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000622 {'L', 4, 0, lu_uint, lp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000623 /* No float and double! */
624 {0}
625};
626
627
628static const formatdef *
629whichtable(pfmt)
630 const char **pfmt;
631{
632 const char *fmt = (*pfmt)++; /* May be backed out of later */
633 switch (*fmt) {
634 case '<':
635 return lilendian_table;
636 case '>':
637 case '!': /* Network byte order is big-endian */
638 return bigendian_table;
639 case '=': { /* Host byte order -- different from native in aligment! */
640 int n = 1;
641 char *p = (char *) &n;
642 if (*p == 1)
643 return lilendian_table;
644 else
645 return bigendian_table;
646 }
647 default:
648 --*pfmt; /* Back out of pointer increment */
649 /* Fall through */
650 case '@':
651 return native_table;
652 }
653}
654
655
656/* Get the table entry for a format code */
657
658static const formatdef *
659getentry(c, f)
660 int c;
661 const formatdef *f;
662{
663 for (; f->format != '\0'; f++) {
664 if (f->format == c) {
665 return f;
666 }
667 }
668 PyErr_SetString(StructError, "bad char in struct format");
669 return NULL;
670}
671
672
Guido van Rossum02975121992-08-17 08:55:12 +0000673/* Align a size according to a format code */
674
675static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000676align(size, c, e)
Guido van Rossum02975121992-08-17 08:55:12 +0000677 int size;
678 int c;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000679 const formatdef *e;
Guido van Rossum02975121992-08-17 08:55:12 +0000680{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000681 if (e->format == c) {
682 if (e->alignment) {
683 size = ((size + e->alignment - 1)
684 / e->alignment)
685 * e->alignment;
686 }
Guido van Rossum02975121992-08-17 08:55:12 +0000687 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000688 return size;
Guido van Rossum02975121992-08-17 08:55:12 +0000689}
690
691
692/* calculate the size of a format string */
693
694static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000695calcsize(fmt, f)
696 const char *fmt;
697 const formatdef *f;
Guido van Rossum02975121992-08-17 08:55:12 +0000698{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000699 const formatdef *e;
700 const char *s;
Guido van Rossum02975121992-08-17 08:55:12 +0000701 char c;
702 int size, num, itemsize, x;
703
704 s = fmt;
705 size = 0;
706 while ((c = *s++) != '\0') {
707 if ('0' <= c && c <= '9') {
708 num = c - '0';
709 while ('0' <= (c = *s++) && c <= '9') {
710 x = num*10 + (c - '0');
711 if (x/10 != num) {
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000712 PyErr_SetString(
713 StructError,
714 "overflow in item count");
Guido van Rossum02975121992-08-17 08:55:12 +0000715 return -1;
716 }
717 num = x;
718 }
719 if (c == '\0')
720 break;
721 }
722 else
723 num = 1;
724
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000725 e = getentry(c, f);
726 if (e == NULL)
Guido van Rossum02975121992-08-17 08:55:12 +0000727 return -1;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000728 itemsize = e->size;
729 size = align(size, c, e);
Guido van Rossum02975121992-08-17 08:55:12 +0000730 x = num * itemsize;
731 size += x;
732 if (x/itemsize != num || size < 0) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000733 PyErr_SetString(StructError,
734 "total struct size too long");
Guido van Rossum02975121992-08-17 08:55:12 +0000735 return -1;
736 }
Guido van Rossum02975121992-08-17 08:55:12 +0000737 }
738
739 return size;
740}
741
742
743/* pack(fmt, v1, v2, ...) --> string */
744
Barry Warsaw30695fa1996-12-12 23:32:31 +0000745static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +0000746struct_calcsize(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +0000747 PyObject *self; /* Not used */
748 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +0000749{
750 char *fmt;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000751 const formatdef *f;
Guido van Rossum02975121992-08-17 08:55:12 +0000752 int size;
753
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000754 if (!PyArg_ParseTuple(args, "s", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +0000755 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000756 f = whichtable(&fmt);
757 size = calcsize(fmt, f);
Guido van Rossum02975121992-08-17 08:55:12 +0000758 if (size < 0)
759 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000760 return PyInt_FromLong((long)size);
Guido van Rossum02975121992-08-17 08:55:12 +0000761}
762
763
764/* pack(fmt, v1, v2, ...) --> string */
765
Barry Warsaw30695fa1996-12-12 23:32:31 +0000766static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +0000767struct_pack(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +0000768 PyObject *self; /* Not used */
769 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +0000770{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000771 const formatdef *f, *e;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000772 PyObject *format, *result, *v;
Guido van Rossum02975121992-08-17 08:55:12 +0000773 char *fmt;
774 int size, num;
775 int i, n;
776 char *s, *res, *restart;
777 char c;
Guido van Rossum02975121992-08-17 08:55:12 +0000778
Barry Warsaw30695fa1996-12-12 23:32:31 +0000779 if (args == NULL || !PyTuple_Check(args) ||
780 (n = PyTuple_Size(args)) < 1)
781 {
782 PyErr_BadArgument();
Guido van Rossum02975121992-08-17 08:55:12 +0000783 return NULL;
784 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000785 format = PyTuple_GetItem(args, 0);
786 if (!PyArg_Parse(format, "s", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +0000787 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000788 f = whichtable(&fmt);
789 size = calcsize(fmt, f);
Guido van Rossum02975121992-08-17 08:55:12 +0000790 if (size < 0)
791 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000792 result = PyString_FromStringAndSize((char *)NULL, size);
Guido van Rossum02975121992-08-17 08:55:12 +0000793 if (result == NULL)
794 return NULL;
795
796 s = fmt;
797 i = 1;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000798 res = restart = PyString_AsString(result);
Guido van Rossum02975121992-08-17 08:55:12 +0000799
800 while ((c = *s++) != '\0') {
801 if ('0' <= c && c <= '9') {
802 num = c - '0';
803 while ('0' <= (c = *s++) && c <= '9')
804 num = num*10 + (c - '0');
805 if (c == '\0')
806 break;
807 }
808 else
809 num = 1;
810
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000811 e = getentry(c, f);
812 if (e == NULL)
813 goto fail;
814 res = restart + align((int)(res-restart), c, e);
Guido van Rossum3aa27fd1996-12-31 02:10:45 +0000815 if (num == 0 && c != 's')
816 continue;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000817 do {
818 if (c == 'x') {
819 /* doesn't consume arguments */
Guido van Rossum3aa27fd1996-12-31 02:10:45 +0000820 memset(res, '\0', num);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000821 res += num;
Guido van Rossum02975121992-08-17 08:55:12 +0000822 break;
Guido van Rossum02975121992-08-17 08:55:12 +0000823 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000824 if (i >= n) {
825 PyErr_SetString(StructError,
826 "insufficient arguments to pack");
827 goto fail;
828 }
829 v = PyTuple_GetItem(args, i++);
830 if (v == NULL)
831 goto fail;
832 if (c == 's') {
833 /* num is string size, not repeat count */
834 int n;
835 if (!PyString_Check(v)) {
836 PyErr_SetString(StructError,
837 "argument for 's' must be a string");
838 goto fail;
839 }
840 n = PyString_Size(v);
841 if (n > num)
842 n = num;
843 if (n > 0)
844 memcpy(res, PyString_AsString(v), n);
845 if (n < num)
Guido van Rossum3aa27fd1996-12-31 02:10:45 +0000846 memset(res+n, '\0', num-n);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000847 res += num;
848 break;
849 }
850 else {
851 if (e->pack(res, v, e) < 0)
852 goto fail;
853 res += e->size;
854 }
855 } while (--num > 0);
Guido van Rossum02975121992-08-17 08:55:12 +0000856 }
857
858 if (i < n) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000859 PyErr_SetString(StructError,
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000860 "too many arguments for pack format");
Guido van Rossum02975121992-08-17 08:55:12 +0000861 goto fail;
862 }
863
864 return result;
865
866 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +0000867 Py_DECREF(result);
Guido van Rossum02975121992-08-17 08:55:12 +0000868 return NULL;
869}
870
871
872/* unpack(fmt, string) --> (v1, v2, ...) */
873
Barry Warsaw30695fa1996-12-12 23:32:31 +0000874static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +0000875struct_unpack(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +0000876 PyObject *self; /* Not used */
877 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +0000878{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000879 const formatdef *f, *e;
Guido van Rossum02975121992-08-17 08:55:12 +0000880 char *str, *start, *fmt, *s;
881 char c;
882 int len, size, num, x;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000883 PyObject *res, *v;
Guido van Rossum02975121992-08-17 08:55:12 +0000884
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000885 if (!PyArg_ParseTuple(args, "ss#", &fmt, &start, &len))
Guido van Rossum02975121992-08-17 08:55:12 +0000886 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000887 f = whichtable(&fmt);
888 size = calcsize(fmt, f);
889 if (size < 0)
890 return NULL;
Guido van Rossum02975121992-08-17 08:55:12 +0000891 if (size != len) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000892 PyErr_SetString(StructError,
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000893 "unpack str size does not match format");
Guido van Rossum02975121992-08-17 08:55:12 +0000894 return NULL;
895 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000896 res = PyList_New(0);
Guido van Rossum02975121992-08-17 08:55:12 +0000897 if (res == NULL)
898 return NULL;
899 str = start;
900 s = fmt;
901 while ((c = *s++) != '\0') {
902 if ('0' <= c && c <= '9') {
903 num = c - '0';
904 while ('0' <= (c = *s++) && c <= '9')
905 num = num*10 + (c - '0');
906 if (c == '\0')
907 break;
908 }
909 else
910 num = 1;
911
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000912 e = getentry(c, f);
913 if (e == NULL)
914 goto fail;
915 str = start + align((int)(str-start), c, e);
Guido van Rossum3aa27fd1996-12-31 02:10:45 +0000916 if (num == 0 && c != 's')
917 continue;
Guido van Rossum02975121992-08-17 08:55:12 +0000918
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000919 do {
920 if (c == 'x') {
921 str += num;
Guido van Rossum02975121992-08-17 08:55:12 +0000922 break;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000923 }
924 if (c == 's') {
925 /* num is string size, not repeat count */
926 v = PyString_FromStringAndSize(str, num);
927 if (v == NULL)
928 goto fail;
929 str += num;
930 num = 0;
931 }
932 else {
933 v = e->unpack(str, e);
934 if (v == NULL)
935 goto fail;
936 str += e->size;
Guido van Rossum02975121992-08-17 08:55:12 +0000937 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000938 if (v == NULL || PyList_Append(res, v) < 0)
Guido van Rossum02975121992-08-17 08:55:12 +0000939 goto fail;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000940 Py_DECREF(v);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000941 } while (--num > 0);
Guido van Rossum02975121992-08-17 08:55:12 +0000942 }
943
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000944 v = PyList_AsTuple(res);
945 Py_DECREF(res);
946 return v;
Guido van Rossum02975121992-08-17 08:55:12 +0000947
948 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +0000949 Py_DECREF(res);
Guido van Rossum02975121992-08-17 08:55:12 +0000950 return NULL;
951}
952
Guido van Rossum90ddb7b1992-08-19 16:44:15 +0000953
Guido van Rossum02975121992-08-17 08:55:12 +0000954/* List of functions */
955
Barry Warsaw30695fa1996-12-12 23:32:31 +0000956static PyMethodDef struct_methods[] = {
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000957 {"calcsize", struct_calcsize, METH_VARARGS},
958 {"pack", struct_pack, METH_VARARGS},
959 {"unpack", struct_unpack, METH_VARARGS},
Guido van Rossum02975121992-08-17 08:55:12 +0000960 {NULL, NULL} /* sentinel */
961};
962
963
964/* Module initialization */
965
966void
967initstruct()
968{
Barry Warsaw30695fa1996-12-12 23:32:31 +0000969 PyObject *m, *d;
Guido van Rossum02975121992-08-17 08:55:12 +0000970
971 /* Create the module and add the functions */
Barry Warsaw30695fa1996-12-12 23:32:31 +0000972 m = Py_InitModule("struct", struct_methods);
Guido van Rossum02975121992-08-17 08:55:12 +0000973
974 /* Add some symbolic constants to the module */
Barry Warsaw30695fa1996-12-12 23:32:31 +0000975 d = PyModule_GetDict(m);
976 StructError = PyString_FromString("struct.error");
977 PyDict_SetItemString(d, "error", StructError);
Guido van Rossum02975121992-08-17 08:55:12 +0000978
979 /* Check for errors */
Barry Warsaw30695fa1996-12-12 23:32:31 +0000980 if (PyErr_Occurred())
981 Py_FatalError("can't initialize module struct");
Guido van Rossum02975121992-08-17 08:55:12 +0000982}