The 0.5 release happened on 2/15, not on 2/14. :-)
[python/dscho.git] / Modules / structmodule.c
blob9994d20313605a2e6dd59d0fcfbb16338ad002e6
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
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 or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* struct module -- pack values into and (out of) strings */
34 /* New version supporting byte order, alignment and size options,
35 character strings, and unsigned numbers */
37 static char struct__doc__[] = "\
38 Functions to convert between Python values and C structs.\n\
39 Python strings are used to hold the data representing the C struct\n\
40 and also as format strings to describe the layout of data in the C struct.\n\
41 \n\
42 The optional first format char indicates byte ordering and alignment:\n\
43 @: native w/native alignment(default)\n\
44 =: native w/standard alignment\n\
45 <: little-endian, std. alignment\n\
46 >: big-endian, std. alignment\n\
47 !: network, std (same as >)\n\
48 \n\
49 The remaining chars indicate types of args and must match exactly;\n\
50 these can be preceded by a decimal repeat count:\n\
51 x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
52 h:short; H:unsigned short; i:int; I:unsigned int;\n\
53 l:long; L:unsigned long; f:float; d:double.\n\
54 Special cases (preceding decimal count indicates length):\n\
55 s:string (array of char); p: pascal string (w. count byte).\n\
56 Special case (only available in native format):\n\
57 P:an integer type that is wide enough to hold a pointer.\n\
58 Whitespace between formats is ignored.\n\
59 \n\
60 The variable struct.error is an exception raised on errors.";
62 #include "Python.h"
63 #include "mymath.h"
65 #include <limits.h>
66 #include <ctype.h>
69 /* Exception */
71 static PyObject *StructError;
74 /* Define various structs to figure out the alignments of types */
76 #ifdef __MWERKS__
78 ** XXXX We have a problem here. There are no unique alignment rules
79 ** on the PowerPC mac.
81 #ifdef __powerc
82 #pragma options align=mac68k
83 #endif
84 #endif /* __MWERKS__ */
86 typedef struct { char c; short x; } s_short;
87 typedef struct { char c; int x; } s_int;
88 typedef struct { char c; long x; } s_long;
89 typedef struct { char c; float x; } s_float;
90 typedef struct { char c; double x; } s_double;
91 typedef struct { char c; void *x; } s_void_p;
93 #define SHORT_ALIGN (sizeof(s_short) - sizeof(short))
94 #define INT_ALIGN (sizeof(s_int) - sizeof(int))
95 #define LONG_ALIGN (sizeof(s_long) - sizeof(long))
96 #define FLOAT_ALIGN (sizeof(s_float) - sizeof(float))
97 #define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))
98 #define VOID_P_ALIGN (sizeof(s_void_p) - sizeof(void *))
100 #ifdef __powerc
101 #pragma options align=reset
102 #endif
104 /* Helper routine to get a Python integer and raise the appropriate error
105 if it isn't one */
107 static int
108 get_long(v, p)
109 PyObject *v;
110 long *p;
112 long x = PyInt_AsLong(v);
113 if (x == -1 && PyErr_Occurred()) {
114 if (PyErr_ExceptionMatches(PyExc_TypeError))
115 PyErr_SetString(StructError,
116 "required argument is not an integer");
117 return -1;
119 *p = x;
120 return 0;
124 /* Same, but handling unsigned long */
126 static int
127 get_ulong(v, p)
128 PyObject *v;
129 unsigned long *p;
131 if (PyLong_Check(v)) {
132 unsigned long x = PyLong_AsUnsignedLong(v);
133 if (x == (unsigned long)(-1) && PyErr_Occurred())
134 return -1;
135 *p = x;
136 return 0;
138 else {
139 return get_long(v, (long *)p);
144 /* Floating point helpers */
146 /* These use ANSI/IEEE Standard 754-1985 (Standard for Binary Floating
147 Point Arithmetic). See the following URL:
148 http://www.psc.edu/general/software/packages/ieee/ieee.html */
150 /* XXX Inf/NaN are not handled quite right (but underflow is!) */
152 static int
153 pack_float(x, p, incr)
154 double x; /* The number to pack */
155 char *p; /* Where to pack the high order byte */
156 int incr; /* 1 for big-endian; -1 for little-endian */
158 int s;
159 int e;
160 double f;
161 long fbits;
163 if (x < 0) {
164 s = 1;
165 x = -x;
167 else
168 s = 0;
170 f = frexp(x, &e);
172 /* Normalize f to be in the range [1.0, 2.0) */
173 if (0.5 <= f && f < 1.0) {
174 f *= 2.0;
175 e--;
177 else if (f == 0.0) {
178 e = 0;
180 else {
181 PyErr_SetString(PyExc_SystemError,
182 "frexp() result out of range");
183 return -1;
186 if (e >= 128) {
187 /* XXX 128 itself is reserved for Inf/NaN */
188 PyErr_SetString(PyExc_OverflowError,
189 "float too large to pack with f format");
190 return -1;
192 else if (e < -126) {
193 /* Gradual underflow */
194 f = ldexp(f, 126 + e);
195 e = 0;
197 else if (!(e == 0 && f == 0.0)) {
198 e += 127;
199 f -= 1.0; /* Get rid of leading 1 */
202 f *= 8388608.0; /* 2**23 */
203 fbits = (long) floor(f + 0.5); /* Round */
205 /* First byte */
206 *p = (s<<7) | (e>>1);
207 p += incr;
209 /* Second byte */
210 *p = (char) (((e&1)<<7) | (fbits>>16));
211 p += incr;
213 /* Third byte */
214 *p = (fbits>>8) & 0xFF;
215 p += incr;
217 /* Fourth byte */
218 *p = fbits&0xFF;
220 /* Done */
221 return 0;
224 static int
225 pack_double(x, p, incr)
226 double x; /* The number to pack */
227 char *p; /* Where to pack the high order byte */
228 int incr; /* 1 for big-endian; -1 for little-endian */
230 int s;
231 int e;
232 double f;
233 long fhi, flo;
235 if (x < 0) {
236 s = 1;
237 x = -x;
239 else
240 s = 0;
242 f = frexp(x, &e);
244 /* Normalize f to be in the range [1.0, 2.0) */
245 if (0.5 <= f && f < 1.0) {
246 f *= 2.0;
247 e--;
249 else if (f == 0.0) {
250 e = 0;
252 else {
253 PyErr_SetString(PyExc_SystemError,
254 "frexp() result out of range");
255 return -1;
258 if (e >= 1024) {
259 /* XXX 1024 itself is reserved for Inf/NaN */
260 PyErr_SetString(PyExc_OverflowError,
261 "float too large to pack with d format");
262 return -1;
264 else if (e < -1022) {
265 /* Gradual underflow */
266 f = ldexp(f, 1022 + e);
267 e = 0;
269 else if (!(e == 0 && f == 0.0)) {
270 e += 1023;
271 f -= 1.0; /* Get rid of leading 1 */
274 /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
275 f *= 268435456.0; /* 2**28 */
276 fhi = (long) floor(f); /* Truncate */
277 f -= (double)fhi;
278 f *= 16777216.0; /* 2**24 */
279 flo = (long) floor(f + 0.5); /* Round */
281 /* First byte */
282 *p = (s<<7) | (e>>4);
283 p += incr;
285 /* Second byte */
286 *p = (char) (((e&0xF)<<4) | (fhi>>24));
287 p += incr;
289 /* Third byte */
290 *p = (fhi>>16) & 0xFF;
291 p += incr;
293 /* Fourth byte */
294 *p = (fhi>>8) & 0xFF;
295 p += incr;
297 /* Fifth byte */
298 *p = fhi & 0xFF;
299 p += incr;
301 /* Sixth byte */
302 *p = (flo>>16) & 0xFF;
303 p += incr;
305 /* Seventh byte */
306 *p = (flo>>8) & 0xFF;
307 p += incr;
309 /* Eighth byte */
310 *p = flo & 0xFF;
311 p += incr;
313 /* Done */
314 return 0;
317 static PyObject *
318 unpack_float(p, incr)
319 char *p; /* Where the high order byte is */
320 int incr; /* 1 for big-endian; -1 for little-endian */
322 int s;
323 int e;
324 long f;
325 double x;
327 /* First byte */
328 s = (*p>>7) & 1;
329 e = (*p & 0x7F) << 1;
330 p += incr;
332 /* Second byte */
333 e |= (*p>>7) & 1;
334 f = (*p & 0x7F) << 16;
335 p += incr;
337 /* Third byte */
338 f |= (*p & 0xFF) << 8;
339 p += incr;
341 /* Fourth byte */
342 f |= *p & 0xFF;
344 x = (double)f / 8388608.0;
346 /* XXX This sadly ignores Inf/NaN issues */
347 if (e == 0)
348 e = -126;
349 else {
350 x += 1.0;
351 e -= 127;
353 x = ldexp(x, e);
355 if (s)
356 x = -x;
358 return PyFloat_FromDouble(x);
361 static PyObject *
362 unpack_double(p, incr)
363 char *p; /* Where the high order byte is */
364 int incr; /* 1 for big-endian; -1 for little-endian */
366 int s;
367 int e;
368 long fhi, flo;
369 double x;
371 /* First byte */
372 s = (*p>>7) & 1;
373 e = (*p & 0x7F) << 4;
374 p += incr;
376 /* Second byte */
377 e |= (*p>>4) & 0xF;
378 fhi = (*p & 0xF) << 24;
379 p += incr;
381 /* Third byte */
382 fhi |= (*p & 0xFF) << 16;
383 p += incr;
385 /* Fourth byte */
386 fhi |= (*p & 0xFF) << 8;
387 p += incr;
389 /* Fifth byte */
390 fhi |= *p & 0xFF;
391 p += incr;
393 /* Sixth byte */
394 flo = (*p & 0xFF) << 16;
395 p += incr;
397 /* Seventh byte */
398 flo |= (*p & 0xFF) << 8;
399 p += incr;
401 /* Eighth byte */
402 flo |= *p & 0xFF;
403 p += incr;
405 x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
406 x /= 268435456.0; /* 2**28 */
408 /* XXX This sadly ignores Inf/NaN */
409 if (e == 0)
410 e = -1022;
411 else {
412 x += 1.0;
413 e -= 1023;
415 x = ldexp(x, e);
417 if (s)
418 x = -x;
420 return PyFloat_FromDouble(x);
424 /* The translation function for each format character is table driven */
426 typedef struct _formatdef {
427 char format;
428 int size;
429 int alignment;
430 PyObject* (*unpack) Py_PROTO((const char *,
431 const struct _formatdef *));
432 int (*pack) Py_PROTO((char *,
433 PyObject *,
434 const struct _formatdef *));
435 } formatdef;
437 static PyObject *
438 nu_char(p, f)
439 const char *p;
440 const formatdef *f;
442 return PyString_FromStringAndSize(p, 1);
445 static PyObject *
446 nu_byte(p, f)
447 const char *p;
448 const formatdef *f;
450 return PyInt_FromLong((long) *(signed char *)p);
453 static PyObject *
454 nu_ubyte(p, f)
455 const char *p;
456 const formatdef *f;
458 return PyInt_FromLong((long) *(unsigned char *)p);
461 static PyObject *
462 nu_short(p, f)
463 const char *p;
464 const formatdef *f;
466 return PyInt_FromLong((long) *(short *)p);
469 static PyObject *
470 nu_ushort(p, f)
471 const char *p;
472 const formatdef *f;
474 return PyInt_FromLong((long) *(unsigned short *)p);
477 static PyObject *
478 nu_int(p, f)
479 const char *p;
480 const formatdef *f;
482 return PyInt_FromLong((long) *(int *)p);
485 static PyObject *
486 nu_uint(p, f)
487 const char *p;
488 const formatdef *f;
490 unsigned int x = *(unsigned int *)p;
491 return PyLong_FromUnsignedLong((unsigned long)x);
494 static PyObject *
495 nu_long(p, f)
496 const char *p;
497 const formatdef *f;
499 return PyInt_FromLong(*(long *)p);
502 static PyObject *
503 nu_ulong(p, f)
504 const char *p;
505 const formatdef *f;
507 return PyLong_FromUnsignedLong(*(unsigned long *)p);
510 static PyObject *
511 nu_float(p, f)
512 const char *p;
513 const formatdef *f;
515 float x;
516 memcpy((char *)&x, p, sizeof(float));
517 return PyFloat_FromDouble((double)x);
520 static PyObject *
521 nu_double(p, f)
522 const char *p;
523 const formatdef *f;
525 double x;
526 memcpy((char *)&x, p, sizeof(double));
527 return PyFloat_FromDouble(x);
530 static PyObject *
531 nu_void_p(p, f)
532 const char *p;
533 const formatdef *f;
535 return PyLong_FromVoidPtr(*(void **)p);
538 static int
539 np_byte(p, v, f)
540 char *p;
541 PyObject *v;
542 const formatdef *f;
544 long x;
545 if (get_long(v, &x) < 0)
546 return -1;
547 *p = (char)x;
548 return 0;
551 static int
552 np_char(p, v, f)
553 char *p;
554 PyObject *v;
555 const formatdef *f;
557 if (!PyString_Check(v) || PyString_Size(v) != 1) {
558 PyErr_SetString(StructError,
559 "char format require string of length 1");
560 return -1;
562 *p = *PyString_AsString(v);
563 return 0;
566 static int
567 np_short(p, v, f)
568 char *p;
569 PyObject *v;
570 const formatdef *f;
572 long x;
573 if (get_long(v, &x) < 0)
574 return -1;
575 * (short *)p = (short)x;
576 return 0;
579 static int
580 np_int(p, v, f)
581 char *p;
582 PyObject *v;
583 const formatdef *f;
585 long x;
586 if (get_long(v, &x) < 0)
587 return -1;
588 * (int *)p = x;
589 return 0;
592 static int
593 np_uint(p, v, f)
594 char *p;
595 PyObject *v;
596 const formatdef *f;
598 unsigned long x;
599 if (get_ulong(v, &x) < 0)
600 return -1;
601 * (unsigned int *)p = x;
602 return 0;
605 static int
606 np_long(p, v, f)
607 char *p;
608 PyObject *v;
609 const formatdef *f;
611 long x;
612 if (get_long(v, &x) < 0)
613 return -1;
614 * (long *)p = x;
615 return 0;
618 static int
619 np_ulong(p, v, f)
620 char *p;
621 PyObject *v;
622 const formatdef *f;
624 unsigned long x;
625 if (get_ulong(v, &x) < 0)
626 return -1;
627 * (unsigned long *)p = x;
628 return 0;
631 static int
632 np_float(p, v, f)
633 char *p;
634 PyObject *v;
635 const formatdef *f;
637 float x = (float)PyFloat_AsDouble(v);
638 if (x == -1 && PyErr_Occurred()) {
639 PyErr_SetString(StructError,
640 "required argument is not a float");
641 return -1;
643 memcpy(p, (char *)&x, sizeof(float));
644 return 0;
647 static int
648 np_double(p, v, f)
649 char *p;
650 PyObject *v;
651 const formatdef *f;
653 double x = PyFloat_AsDouble(v);
654 if (x == -1 && PyErr_Occurred()) {
655 PyErr_SetString(StructError,
656 "required argument is not a float");
657 return -1;
659 memcpy(p, (char *)&x, sizeof(double));
660 return 0;
663 static int
664 np_void_p(p, v, f)
665 char *p;
666 PyObject *v;
667 const formatdef *f;
669 void *x = PyLong_AsVoidPtr(v);
670 if (x == NULL && PyErr_Occurred()) {
671 /* ### hrm. PyLong_AsVoidPtr raises SystemError */
672 if (PyErr_ExceptionMatches(PyExc_TypeError))
673 PyErr_SetString(StructError,
674 "required argument is not an integer");
675 return -1;
677 *(void **)p = x;
678 return 0;
681 static formatdef native_table[] = {
682 {'x', sizeof(char), 0, NULL},
683 {'b', sizeof(char), 0, nu_byte, np_byte},
684 {'B', sizeof(char), 0, nu_ubyte, np_byte},
685 {'c', sizeof(char), 0, nu_char, np_char},
686 {'s', sizeof(char), 0, NULL},
687 {'p', sizeof(char), 0, NULL},
688 {'h', sizeof(short), SHORT_ALIGN, nu_short, np_short},
689 {'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_short},
690 {'i', sizeof(int), INT_ALIGN, nu_int, np_int},
691 {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint},
692 {'l', sizeof(long), LONG_ALIGN, nu_long, np_long},
693 {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong},
694 {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
695 {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
696 {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p},
700 static PyObject *
701 bu_int(p, f)
702 const char *p;
703 const formatdef *f;
705 long x = 0;
706 int i = f->size;
707 do {
708 x = (x<<8) | (*p++ & 0xFF);
709 } while (--i > 0);
710 i = 8*(sizeof(long) - f->size);
711 if (i) {
712 x <<= i;
713 x >>= i;
715 return PyInt_FromLong(x);
718 static PyObject *
719 bu_uint(p, f)
720 const char *p;
721 const formatdef *f;
723 unsigned long x = 0;
724 int i = f->size;
725 do {
726 x = (x<<8) | (*p++ & 0xFF);
727 } while (--i > 0);
728 if (f->size >= 4)
729 return PyLong_FromUnsignedLong(x);
730 else
731 return PyInt_FromLong((long)x);
734 static PyObject *
735 bu_float(p, f)
736 const char *p;
737 const formatdef *f;
739 return unpack_float(p, 1);
742 static PyObject *
743 bu_double(p, f)
744 const char *p;
745 const formatdef *f;
747 return unpack_double(p, 1);
750 static int
751 bp_int(p, v, f)
752 char *p;
753 PyObject *v;
754 const formatdef *f;
756 long x;
757 int i;
758 if (get_long(v, &x) < 0)
759 return -1;
760 i = f->size;
761 do {
762 p[--i] = (char)x;
763 x >>= 8;
764 } while (i > 0);
765 return 0;
768 static int
769 bp_uint(p, v, f)
770 char *p;
771 PyObject *v;
772 const formatdef *f;
774 unsigned long x;
775 int i;
776 if (get_ulong(v, &x) < 0)
777 return -1;
778 i = f->size;
779 do {
780 p[--i] = (char)x;
781 x >>= 8;
782 } while (i > 0);
783 return 0;
786 static int
787 bp_float(p, v, f)
788 char *p;
789 PyObject *v;
790 const formatdef *f;
792 double x = PyFloat_AsDouble(v);
793 if (x == -1 && PyErr_Occurred()) {
794 PyErr_SetString(StructError,
795 "required argument is not a float");
796 return -1;
798 return pack_float(x, p, 1);
801 static int
802 bp_double(p, v, f)
803 char *p;
804 PyObject *v;
805 const formatdef *f;
807 double x = PyFloat_AsDouble(v);
808 if (x == -1 && PyErr_Occurred()) {
809 PyErr_SetString(StructError,
810 "required argument is not a float");
811 return -1;
813 return pack_double(x, p, 1);
816 static formatdef bigendian_table[] = {
817 {'x', 1, 0, NULL},
818 {'b', 1, 0, bu_int, bp_int},
819 {'B', 1, 0, bu_uint, bp_int},
820 {'c', 1, 0, nu_char, np_char},
821 {'s', 1, 0, NULL},
822 {'p', 1, 0, NULL},
823 {'h', 2, 0, bu_int, bp_int},
824 {'H', 2, 0, bu_uint, bp_uint},
825 {'i', 4, 0, bu_int, bp_int},
826 {'I', 4, 0, bu_uint, bp_uint},
827 {'l', 4, 0, bu_int, bp_int},
828 {'L', 4, 0, bu_uint, bp_uint},
829 {'f', 4, 0, bu_float, bp_float},
830 {'d', 8, 0, bu_double, bp_double},
834 static PyObject *
835 lu_int(p, f)
836 const char *p;
837 const formatdef *f;
839 long x = 0;
840 int i = f->size;
841 do {
842 x = (x<<8) | (p[--i] & 0xFF);
843 } while (i > 0);
844 i = 8*(sizeof(long) - f->size);
845 if (i) {
846 x <<= i;
847 x >>= i;
849 return PyInt_FromLong(x);
852 static PyObject *
853 lu_uint(p, f)
854 const char *p;
855 const formatdef *f;
857 unsigned long x = 0;
858 int i = f->size;
859 do {
860 x = (x<<8) | (p[--i] & 0xFF);
861 } while (i > 0);
862 if (f->size >= 4)
863 return PyLong_FromUnsignedLong(x);
864 else
865 return PyInt_FromLong((long)x);
868 static PyObject *
869 lu_float(p, f)
870 const char *p;
871 const formatdef *f;
873 return unpack_float(p+3, -1);
876 static PyObject *
877 lu_double(p, f)
878 const char *p;
879 const formatdef *f;
881 return unpack_double(p+7, -1);
884 static int
885 lp_int(p, v, f)
886 char *p;
887 PyObject *v;
888 const formatdef *f;
890 long x;
891 int i;
892 if (get_long(v, &x) < 0)
893 return -1;
894 i = f->size;
895 do {
896 *p++ = (char)x;
897 x >>= 8;
898 } while (--i > 0);
899 return 0;
902 static int
903 lp_uint(p, v, f)
904 char *p;
905 PyObject *v;
906 const formatdef *f;
908 unsigned long x;
909 int i;
910 if (get_ulong(v, &x) < 0)
911 return -1;
912 i = f->size;
913 do {
914 *p++ = (char)x;
915 x >>= 8;
916 } while (--i > 0);
917 return 0;
920 static int
921 lp_float(p, v, f)
922 char *p;
923 PyObject *v;
924 const formatdef *f;
926 double x = PyFloat_AsDouble(v);
927 if (x == -1 && PyErr_Occurred()) {
928 PyErr_SetString(StructError,
929 "required argument is not a float");
930 return -1;
932 return pack_float(x, p+3, -1);
935 static int
936 lp_double(p, v, f)
937 char *p;
938 PyObject *v;
939 const formatdef *f;
941 double x = PyFloat_AsDouble(v);
942 if (x == -1 && PyErr_Occurred()) {
943 PyErr_SetString(StructError,
944 "required argument is not a float");
945 return -1;
947 return pack_double(x, p+7, -1);
950 static formatdef lilendian_table[] = {
951 {'x', 1, 0, NULL},
952 {'b', 1, 0, lu_int, lp_int},
953 {'B', 1, 0, lu_uint, lp_int},
954 {'c', 1, 0, nu_char, np_char},
955 {'s', 1, 0, NULL},
956 {'p', 1, 0, NULL},
957 {'h', 2, 0, lu_int, lp_int},
958 {'H', 2, 0, lu_uint, lp_uint},
959 {'i', 4, 0, lu_int, lp_int},
960 {'I', 4, 0, lu_uint, lp_uint},
961 {'l', 4, 0, lu_int, lp_int},
962 {'L', 4, 0, lu_uint, lp_uint},
963 {'f', 4, 0, lu_float, lp_float},
964 {'d', 8, 0, lu_double, lp_double},
969 static const formatdef *
970 whichtable(pfmt)
971 const char **pfmt;
973 const char *fmt = (*pfmt)++; /* May be backed out of later */
974 switch (*fmt) {
975 case '<':
976 return lilendian_table;
977 case '>':
978 case '!': /* Network byte order is big-endian */
979 return bigendian_table;
980 case '=': { /* Host byte order -- different from native in aligment! */
981 int n = 1;
982 char *p = (char *) &n;
983 if (*p == 1)
984 return lilendian_table;
985 else
986 return bigendian_table;
988 default:
989 --*pfmt; /* Back out of pointer increment */
990 /* Fall through */
991 case '@':
992 return native_table;
997 /* Get the table entry for a format code */
999 static const formatdef *
1000 getentry(c, f)
1001 int c;
1002 const formatdef *f;
1004 for (; f->format != '\0'; f++) {
1005 if (f->format == c) {
1006 return f;
1009 PyErr_SetString(StructError, "bad char in struct format");
1010 return NULL;
1014 /* Align a size according to a format code */
1016 static int
1017 align(size, c, e)
1018 int size;
1019 int c;
1020 const formatdef *e;
1022 if (e->format == c) {
1023 if (e->alignment) {
1024 size = ((size + e->alignment - 1)
1025 / e->alignment)
1026 * e->alignment;
1029 return size;
1033 /* calculate the size of a format string */
1035 static int
1036 calcsize(fmt, f)
1037 const char *fmt;
1038 const formatdef *f;
1040 const formatdef *e;
1041 const char *s;
1042 char c;
1043 int size, num, itemsize, x;
1045 s = fmt;
1046 size = 0;
1047 while ((c = *s++) != '\0') {
1048 if (isspace((int)c))
1049 continue;
1050 if ('0' <= c && c <= '9') {
1051 num = c - '0';
1052 while ('0' <= (c = *s++) && c <= '9') {
1053 x = num*10 + (c - '0');
1054 if (x/10 != num) {
1055 PyErr_SetString(
1056 StructError,
1057 "overflow in item count");
1058 return -1;
1060 num = x;
1062 if (c == '\0')
1063 break;
1065 else
1066 num = 1;
1068 e = getentry(c, f);
1069 if (e == NULL)
1070 return -1;
1071 itemsize = e->size;
1072 size = align(size, c, e);
1073 x = num * itemsize;
1074 size += x;
1075 if (x/itemsize != num || size < 0) {
1076 PyErr_SetString(StructError,
1077 "total struct size too long");
1078 return -1;
1082 return size;
1086 static char calcsize__doc__[] = "\
1087 calcsize(fmt) -> int\n\
1088 Return size of C struct described by format string fmt.\n\
1089 See struct.__doc__ for more on format strings.";
1091 static PyObject *
1092 struct_calcsize(self, args)
1093 PyObject *self; /* Not used */
1094 PyObject *args;
1096 char *fmt;
1097 const formatdef *f;
1098 int size;
1100 if (!PyArg_ParseTuple(args, "s", &fmt))
1101 return NULL;
1102 f = whichtable(&fmt);
1103 size = calcsize(fmt, f);
1104 if (size < 0)
1105 return NULL;
1106 return PyInt_FromLong((long)size);
1110 static char pack__doc__[] = "\
1111 pack(fmt, v1, v2, ...) -> string\n\
1112 Return string containing values v1, v2, ... packed according to fmt.\n\
1113 See struct.__doc__ for more on format strings.";
1115 static PyObject *
1116 struct_pack(self, args)
1117 PyObject *self; /* Not used */
1118 PyObject *args;
1120 const formatdef *f, *e;
1121 PyObject *format, *result, *v;
1122 char *fmt;
1123 int size, num;
1124 int i, n;
1125 char *s, *res, *restart, *nres;
1126 char c;
1128 if (args == NULL || !PyTuple_Check(args) ||
1129 (n = PyTuple_Size(args)) < 1)
1131 PyErr_BadArgument();
1132 return NULL;
1134 format = PyTuple_GetItem(args, 0);
1135 if (!PyArg_Parse(format, "s", &fmt))
1136 return NULL;
1137 f = whichtable(&fmt);
1138 size = calcsize(fmt, f);
1139 if (size < 0)
1140 return NULL;
1141 result = PyString_FromStringAndSize((char *)NULL, size);
1142 if (result == NULL)
1143 return NULL;
1145 s = fmt;
1146 i = 1;
1147 res = restart = PyString_AsString(result);
1149 while ((c = *s++) != '\0') {
1150 if (isspace((int)c))
1151 continue;
1152 if ('0' <= c && c <= '9') {
1153 num = c - '0';
1154 while ('0' <= (c = *s++) && c <= '9')
1155 num = num*10 + (c - '0');
1156 if (c == '\0')
1157 break;
1159 else
1160 num = 1;
1162 e = getentry(c, f);
1163 if (e == NULL)
1164 goto fail;
1165 nres = restart + align((int)(res-restart), c, e);
1166 /* Fill padd bytes with zeros */
1167 while (res < nres)
1168 *res++ = '\0';
1169 if (num == 0 && c != 's')
1170 continue;
1171 do {
1172 if (c == 'x') {
1173 /* doesn't consume arguments */
1174 memset(res, '\0', num);
1175 res += num;
1176 break;
1178 if (i >= n) {
1179 PyErr_SetString(StructError,
1180 "insufficient arguments to pack");
1181 goto fail;
1183 v = PyTuple_GetItem(args, i++);
1184 if (v == NULL)
1185 goto fail;
1186 if (c == 's') {
1187 /* num is string size, not repeat count */
1188 int n;
1189 if (!PyString_Check(v)) {
1190 PyErr_SetString(StructError,
1191 "argument for 's' must be a string");
1192 goto fail;
1194 n = PyString_Size(v);
1195 if (n > num)
1196 n = num;
1197 if (n > 0)
1198 memcpy(res, PyString_AsString(v), n);
1199 if (n < num)
1200 memset(res+n, '\0', num-n);
1201 res += num;
1202 break;
1204 else if (c == 'p') {
1205 /* num is string size + 1,
1206 to fit in the count byte */
1207 int n;
1208 num--; /* now num is max string size */
1209 if (!PyString_Check(v)) {
1210 PyErr_SetString(StructError,
1211 "argument for 'p' must be a string");
1212 goto fail;
1214 n = PyString_Size(v);
1215 if (n > num)
1216 n = num;
1217 if (n > 0)
1218 memcpy(res+1, PyString_AsString(v), n);
1219 if (n < num)
1220 /* no real need, just to be nice */
1221 memset(res+1+n, '\0', num-n);
1222 *res++ = n; /* store the length byte */
1223 res += num;
1224 break;
1226 else {
1227 if (e->pack(res, v, e) < 0)
1228 goto fail;
1229 res += e->size;
1231 } while (--num > 0);
1234 if (i < n) {
1235 PyErr_SetString(StructError,
1236 "too many arguments for pack format");
1237 goto fail;
1240 return result;
1242 fail:
1243 Py_DECREF(result);
1244 return NULL;
1248 static char unpack__doc__[] = "\
1249 unpack(fmt, string) -> (v1, v2, ...)\n\
1250 Unpack the string, containing packed C structure data, according\n\
1251 to fmt. Requires len(string)==calcsize(fmt).\n\
1252 See struct.__doc__ for more on format strings.";
1254 static PyObject *
1255 struct_unpack(self, args)
1256 PyObject *self; /* Not used */
1257 PyObject *args;
1259 const formatdef *f, *e;
1260 char *str, *start, *fmt, *s;
1261 char c;
1262 int len, size, num;
1263 PyObject *res, *v;
1265 if (!PyArg_ParseTuple(args, "ss#", &fmt, &start, &len))
1266 return NULL;
1267 f = whichtable(&fmt);
1268 size = calcsize(fmt, f);
1269 if (size < 0)
1270 return NULL;
1271 if (size != len) {
1272 PyErr_SetString(StructError,
1273 "unpack str size does not match format");
1274 return NULL;
1276 res = PyList_New(0);
1277 if (res == NULL)
1278 return NULL;
1279 str = start;
1280 s = fmt;
1281 while ((c = *s++) != '\0') {
1282 if (isspace((int)c))
1283 continue;
1284 if ('0' <= c && c <= '9') {
1285 num = c - '0';
1286 while ('0' <= (c = *s++) && c <= '9')
1287 num = num*10 + (c - '0');
1288 if (c == '\0')
1289 break;
1291 else
1292 num = 1;
1294 e = getentry(c, f);
1295 if (e == NULL)
1296 goto fail;
1297 str = start + align((int)(str-start), c, e);
1298 if (num == 0 && c != 's')
1299 continue;
1301 do {
1302 if (c == 'x') {
1303 str += num;
1304 break;
1306 if (c == 's') {
1307 /* num is string size, not repeat count */
1308 v = PyString_FromStringAndSize(str, num);
1309 if (v == NULL)
1310 goto fail;
1311 str += num;
1312 num = 0;
1314 else if (c == 'p') {
1315 /* num is string buffer size,
1316 not repeat count */
1317 int n = *(unsigned char*)str;
1318 /* first byte (unsigned) is string size */
1319 if (n >= num)
1320 n = num-1;
1321 v = PyString_FromStringAndSize(str+1, n);
1322 if (v == NULL)
1323 goto fail;
1324 str += num;
1325 num = 0;
1327 else {
1328 v = e->unpack(str, e);
1329 if (v == NULL)
1330 goto fail;
1331 str += e->size;
1333 if (v == NULL || PyList_Append(res, v) < 0)
1334 goto fail;
1335 Py_DECREF(v);
1336 } while (--num > 0);
1339 v = PyList_AsTuple(res);
1340 Py_DECREF(res);
1341 return v;
1343 fail:
1344 Py_DECREF(res);
1345 return NULL;
1349 /* List of functions */
1351 static PyMethodDef struct_methods[] = {
1352 {"calcsize", struct_calcsize, METH_VARARGS, calcsize__doc__},
1353 {"pack", struct_pack, METH_VARARGS, pack__doc__},
1354 {"unpack", struct_unpack, METH_VARARGS, unpack__doc__},
1355 {NULL, NULL} /* sentinel */
1359 /* Module initialization */
1361 DL_EXPORT(void)
1362 initstruct()
1364 PyObject *m, *d;
1366 /* Create the module and add the functions */
1367 m = Py_InitModule4("struct", struct_methods, struct__doc__,
1368 (PyObject*)NULL, PYTHON_API_VERSION);
1370 /* Add some symbolic constants to the module */
1371 d = PyModule_GetDict(m);
1372 StructError = PyErr_NewException("struct.error", NULL, NULL);
1373 if (StructError == NULL)
1374 return;
1375 PyDict_SetItemString(d, "error", StructError);