1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
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
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\
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\
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 Whitespace between formats is ignored.\n\
58 The variable struct.error is an exception raised on errors.";
69 static PyObject
*StructError
;
72 /* Define various structs to figure out the alignments of types */
76 ** XXXX We have a problem here. There are no unique alignment rules
77 ** on the PowerPC mac.
80 #pragma options align=mac68k
82 #endif /* __MWERKS__ */
84 typedef struct { char c
; short x
; } s_short
;
85 typedef struct { char c
; int x
; } s_int
;
86 typedef struct { char c
; long x
; } s_long
;
87 typedef struct { char c
; float x
; } s_float
;
88 typedef struct { char c
; double x
; } s_double
;
90 #define SHORT_ALIGN (sizeof(s_short) - sizeof(short))
91 #define INT_ALIGN (sizeof(s_int) - sizeof(int))
92 #define LONG_ALIGN (sizeof(s_long) - sizeof(long))
93 #define FLOAT_ALIGN (sizeof(s_float) - sizeof(float))
94 #define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))
97 #pragma options align=reset
100 /* Helper routine to get a Python integer and raise the appropriate error
108 long x
= PyInt_AsLong(v
);
109 if (x
== -1 && PyErr_Occurred()) {
110 if (PyErr_ExceptionMatches(PyExc_TypeError
))
111 PyErr_SetString(StructError
,
112 "required argument is not an integer");
120 /* Same, but handling unsigned long */
127 if (PyLong_Check(v
)) {
128 unsigned long x
= PyLong_AsUnsignedLong(v
);
129 if (x
== (unsigned long)(-1) && PyErr_Occurred())
135 return get_long(v
, (long *)p
);
140 /* Floating point helpers */
142 /* These use ANSI/IEEE Standard 754-1985 (Standard for Binary Floating
143 Point Arithmetic). See the following URL:
144 http://www.psc.edu/general/software/packages/ieee/ieee.html */
146 /* XXX Inf/NaN are not handled quite right (but underflow is!) */
149 pack_float(x
, p
, incr
)
150 double x
; /* The number to pack */
151 char *p
; /* Where to pack the high order byte */
152 int incr
; /* 1 for big-endian; -1 for little-endian */
168 /* Normalize f to be in the range [1.0, 2.0) */
169 if (0.5 <= f
&& f
< 1.0) {
177 PyErr_SetString(PyExc_SystemError
,
178 "frexp() result out of range");
183 /* XXX 128 itself is reserved for Inf/NaN */
184 PyErr_SetString(PyExc_OverflowError
,
185 "float too large to pack with f format");
189 /* Gradual underflow */
190 f
= ldexp(f
, 126 + e
);
193 else if (!(e
== 0 && f
== 0.0)) {
195 f
-= 1.0; /* Get rid of leading 1 */
198 f
*= 8388608.0; /* 2**23 */
199 fbits
= (long) floor(f
+ 0.5); /* Round */
202 *p
= (s
<<7) | (e
>>1);
206 *p
= (char) (((e
&1)<<7) | (fbits
>>16));
210 *p
= (fbits
>>8) & 0xFF;
221 pack_double(x
, p
, incr
)
222 double x
; /* The number to pack */
223 char *p
; /* Where to pack the high order byte */
224 int incr
; /* 1 for big-endian; -1 for little-endian */
240 /* Normalize f to be in the range [1.0, 2.0) */
241 if (0.5 <= f
&& f
< 1.0) {
249 PyErr_SetString(PyExc_SystemError
,
250 "frexp() result out of range");
255 /* XXX 1024 itself is reserved for Inf/NaN */
256 PyErr_SetString(PyExc_OverflowError
,
257 "float too large to pack with d format");
260 else if (e
< -1022) {
261 /* Gradual underflow */
262 f
= ldexp(f
, 1022 + e
);
265 else if (!(e
== 0 && f
== 0.0)) {
267 f
-= 1.0; /* Get rid of leading 1 */
270 /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
271 f
*= 268435456.0; /* 2**28 */
272 fhi
= (long) floor(f
); /* Truncate */
274 f
*= 16777216.0; /* 2**24 */
275 flo
= (long) floor(f
+ 0.5); /* Round */
278 *p
= (s
<<7) | (e
>>4);
282 *p
= (char) (((e
&0xF)<<4) | (fhi
>>24));
286 *p
= (fhi
>>16) & 0xFF;
290 *p
= (fhi
>>8) & 0xFF;
298 *p
= (flo
>>16) & 0xFF;
302 *p
= (flo
>>8) & 0xFF;
314 unpack_float(p
, incr
)
315 char *p
; /* Where the high order byte is */
316 int incr
; /* 1 for big-endian; -1 for little-endian */
325 e
= (*p
& 0x7F) << 1;
330 f
= (*p
& 0x7F) << 16;
334 f
|= (*p
& 0xFF) << 8;
340 x
= (double)f
/ 8388608.0;
342 /* XXX This sadly ignores Inf/NaN issues */
354 return PyFloat_FromDouble(x
);
358 unpack_double(p
, incr
)
359 char *p
; /* Where the high order byte is */
360 int incr
; /* 1 for big-endian; -1 for little-endian */
369 e
= (*p
& 0x7F) << 4;
374 fhi
= (*p
& 0xF) << 24;
378 fhi
|= (*p
& 0xFF) << 16;
382 fhi
|= (*p
& 0xFF) << 8;
390 flo
= (*p
& 0xFF) << 16;
394 flo
|= (*p
& 0xFF) << 8;
401 x
= (double)fhi
+ (double)flo
/ 16777216.0; /* 2**24 */
402 x
/= 268435456.0; /* 2**28 */
404 /* XXX This sadly ignores Inf/NaN */
416 return PyFloat_FromDouble(x
);
420 /* The translation function for each format character is table driven */
422 typedef struct _formatdef
{
426 PyObject
* (*unpack
) Py_PROTO((const char *,
427 const struct _formatdef
*));
428 int (*pack
) Py_PROTO((char *,
430 const struct _formatdef
*));
438 return PyString_FromStringAndSize(p
, 1);
446 return PyInt_FromLong((long) *(signed char *)p
);
454 return PyInt_FromLong((long) *(unsigned char *)p
);
462 return PyInt_FromLong((long) *(short *)p
);
470 return PyInt_FromLong((long) *(unsigned short *)p
);
478 return PyInt_FromLong((long) *(int *)p
);
486 unsigned int x
= *(unsigned int *)p
;
487 return PyLong_FromUnsignedLong((unsigned long)x
);
495 return PyInt_FromLong(*(long *)p
);
503 return PyLong_FromUnsignedLong(*(unsigned long *)p
);
512 memcpy((char *)&x
, p
, sizeof(float));
513 return PyFloat_FromDouble((double)x
);
522 memcpy((char *)&x
, p
, sizeof(double));
523 return PyFloat_FromDouble(x
);
533 if (get_long(v
, &x
) < 0)
545 if (!PyString_Check(v
) || PyString_Size(v
) != 1) {
546 PyErr_SetString(StructError
,
547 "char format require string of length 1");
550 *p
= *PyString_AsString(v
);
561 if (get_long(v
, &x
) < 0)
563 * (short *)p
= (short)x
;
574 if (get_long(v
, &x
) < 0)
587 if (get_ulong(v
, &x
) < 0)
589 * (unsigned int *)p
= x
;
600 if (get_long(v
, &x
) < 0)
613 if (get_ulong(v
, &x
) < 0)
615 * (unsigned long *)p
= x
;
625 float x
= (float)PyFloat_AsDouble(v
);
626 if (x
== -1 && PyErr_Occurred()) {
627 PyErr_SetString(StructError
,
628 "required argument is not a float");
631 memcpy(p
, (char *)&x
, sizeof(float));
641 double x
= PyFloat_AsDouble(v
);
642 if (x
== -1 && PyErr_Occurred()) {
643 PyErr_SetString(StructError
,
644 "required argument is not a float");
647 memcpy(p
, (char *)&x
, sizeof(double));
651 static formatdef native_table
[] = {
652 {'x', sizeof(char), 0, NULL
},
653 {'b', sizeof(char), 0, nu_byte
, np_byte
},
654 {'B', sizeof(char), 0, nu_ubyte
, np_byte
},
655 {'c', sizeof(char), 0, nu_char
, np_char
},
656 {'s', sizeof(char), 0, NULL
},
657 {'p', sizeof(char), 0, NULL
},
658 {'h', sizeof(short), SHORT_ALIGN
, nu_short
, np_short
},
659 {'H', sizeof(short), SHORT_ALIGN
, nu_ushort
, np_short
},
660 {'i', sizeof(int), INT_ALIGN
, nu_int
, np_int
},
661 {'I', sizeof(int), INT_ALIGN
, nu_uint
, np_uint
},
662 {'l', sizeof(long), LONG_ALIGN
, nu_long
, np_long
},
663 {'L', sizeof(long), LONG_ALIGN
, nu_ulong
, np_ulong
},
664 {'f', sizeof(float), FLOAT_ALIGN
, nu_float
, np_float
},
665 {'d', sizeof(double), DOUBLE_ALIGN
, nu_double
, np_double
},
677 x
= (x
<<8) | (*p
++ & 0xFF);
679 i
= 8*(sizeof(long) - f
->size
);
684 return PyInt_FromLong(x
);
695 x
= (x
<<8) | (*p
++ & 0xFF);
698 return PyLong_FromUnsignedLong(x
);
700 return PyInt_FromLong((long)x
);
708 return unpack_float(p
, 1);
716 return unpack_double(p
, 1);
727 if (get_long(v
, &x
) < 0)
745 if (get_ulong(v
, &x
) < 0)
761 double x
= PyFloat_AsDouble(v
);
762 if (x
== -1 && PyErr_Occurred()) {
763 PyErr_SetString(StructError
,
764 "required argument is not a float");
767 return pack_float(x
, p
, 1);
776 double x
= PyFloat_AsDouble(v
);
777 if (x
== -1 && PyErr_Occurred()) {
778 PyErr_SetString(StructError
,
779 "required argument is not a float");
782 return pack_double(x
, p
, 1);
785 static formatdef bigendian_table
[] = {
787 {'b', 1, 0, bu_int
, bp_int
},
788 {'B', 1, 0, bu_uint
, bp_int
},
789 {'c', 1, 0, nu_char
, np_char
},
792 {'h', 2, 0, bu_int
, bp_int
},
793 {'H', 2, 0, bu_uint
, bp_uint
},
794 {'i', 4, 0, bu_int
, bp_int
},
795 {'I', 4, 0, bu_uint
, bp_uint
},
796 {'l', 4, 0, bu_int
, bp_int
},
797 {'L', 4, 0, bu_uint
, bp_uint
},
798 {'f', 4, 0, bu_float
, bp_float
},
799 {'d', 8, 0, bu_double
, bp_double
},
811 x
= (x
<<8) | (p
[--i
] & 0xFF);
813 i
= 8*(sizeof(long) - f
->size
);
818 return PyInt_FromLong(x
);
829 x
= (x
<<8) | (p
[--i
] & 0xFF);
832 return PyLong_FromUnsignedLong(x
);
834 return PyInt_FromLong((long)x
);
842 return unpack_float(p
+3, -1);
850 return unpack_double(p
+7, -1);
861 if (get_long(v
, &x
) < 0)
879 if (get_ulong(v
, &x
) < 0)
895 double x
= PyFloat_AsDouble(v
);
896 if (x
== -1 && PyErr_Occurred()) {
897 PyErr_SetString(StructError
,
898 "required argument is not a float");
901 return pack_float(x
, p
+3, -1);
910 double x
= PyFloat_AsDouble(v
);
911 if (x
== -1 && PyErr_Occurred()) {
912 PyErr_SetString(StructError
,
913 "required argument is not a float");
916 return pack_double(x
, p
+7, -1);
919 static formatdef lilendian_table
[] = {
921 {'b', 1, 0, lu_int
, lp_int
},
922 {'B', 1, 0, lu_uint
, lp_int
},
923 {'c', 1, 0, nu_char
, np_char
},
926 {'h', 2, 0, lu_int
, lp_int
},
927 {'H', 2, 0, lu_uint
, lp_uint
},
928 {'i', 4, 0, lu_int
, lp_int
},
929 {'I', 4, 0, lu_uint
, lp_uint
},
930 {'l', 4, 0, lu_int
, lp_int
},
931 {'L', 4, 0, lu_uint
, lp_uint
},
932 {'f', 4, 0, lu_float
, lp_float
},
933 {'d', 8, 0, lu_double
, lp_double
},
938 static const formatdef
*
942 const char *fmt
= (*pfmt
)++; /* May be backed out of later */
945 return lilendian_table
;
947 case '!': /* Network byte order is big-endian */
948 return bigendian_table
;
949 case '=': { /* Host byte order -- different from native in aligment! */
951 char *p
= (char *) &n
;
953 return lilendian_table
;
955 return bigendian_table
;
958 --*pfmt
; /* Back out of pointer increment */
966 /* Get the table entry for a format code */
968 static const formatdef
*
973 for (; f
->format
!= '\0'; f
++) {
974 if (f
->format
== c
) {
978 PyErr_SetString(StructError
, "bad char in struct format");
983 /* Align a size according to a format code */
991 if (e
->format
== c
) {
993 size
= ((size
+ e
->alignment
- 1)
1002 /* calculate the size of a format string */
1012 int size
, num
, itemsize
, x
;
1016 while ((c
= *s
++) != '\0') {
1017 if (isspace((int)c
))
1019 if ('0' <= c
&& c
<= '9') {
1021 while ('0' <= (c
= *s
++) && c
<= '9') {
1022 x
= num
*10 + (c
- '0');
1026 "overflow in item count");
1041 size
= align(size
, c
, e
);
1044 if (x
/itemsize
!= num
|| size
< 0) {
1045 PyErr_SetString(StructError
,
1046 "total struct size too long");
1055 static char calcsize__doc__
[] = "\
1056 calcsize(fmt) -> int\n\
1057 Return size of C struct described by format string fmt.\n\
1058 See struct.__doc__ for more on format strings.";
1061 struct_calcsize(self
, args
)
1062 PyObject
*self
; /* Not used */
1069 if (!PyArg_ParseTuple(args
, "s", &fmt
))
1071 f
= whichtable(&fmt
);
1072 size
= calcsize(fmt
, f
);
1075 return PyInt_FromLong((long)size
);
1079 static char pack__doc__
[] = "\
1080 pack(fmt, v1, v2, ...) -> string\n\
1081 Return string containing values v1, v2, ... packed according to fmt.\n\
1082 See struct.__doc__ for more on format strings.";
1085 struct_pack(self
, args
)
1086 PyObject
*self
; /* Not used */
1089 const formatdef
*f
, *e
;
1090 PyObject
*format
, *result
, *v
;
1094 char *s
, *res
, *restart
, *nres
;
1097 if (args
== NULL
|| !PyTuple_Check(args
) ||
1098 (n
= PyTuple_Size(args
)) < 1)
1100 PyErr_BadArgument();
1103 format
= PyTuple_GetItem(args
, 0);
1104 if (!PyArg_Parse(format
, "s", &fmt
))
1106 f
= whichtable(&fmt
);
1107 size
= calcsize(fmt
, f
);
1110 result
= PyString_FromStringAndSize((char *)NULL
, size
);
1116 res
= restart
= PyString_AsString(result
);
1118 while ((c
= *s
++) != '\0') {
1119 if (isspace((int)c
))
1121 if ('0' <= c
&& c
<= '9') {
1123 while ('0' <= (c
= *s
++) && c
<= '9')
1124 num
= num
*10 + (c
- '0');
1134 nres
= restart
+ align((int)(res
-restart
), c
, e
);
1135 /* Fill padd bytes with zeros */
1138 if (num
== 0 && c
!= 's')
1142 /* doesn't consume arguments */
1143 memset(res
, '\0', num
);
1148 PyErr_SetString(StructError
,
1149 "insufficient arguments to pack");
1152 v
= PyTuple_GetItem(args
, i
++);
1156 /* num is string size, not repeat count */
1158 if (!PyString_Check(v
)) {
1159 PyErr_SetString(StructError
,
1160 "argument for 's' must be a string");
1163 n
= PyString_Size(v
);
1167 memcpy(res
, PyString_AsString(v
), n
);
1169 memset(res
+n
, '\0', num
-n
);
1173 else if (c
== 'p') {
1174 /* num is string size + 1,
1175 to fit in the count byte */
1177 num
--; /* now num is max string size */
1178 if (!PyString_Check(v
)) {
1179 PyErr_SetString(StructError
,
1180 "argument for 'p' must be a string");
1183 n
= PyString_Size(v
);
1187 memcpy(res
+1, PyString_AsString(v
), n
);
1189 /* no real need, just to be nice */
1190 memset(res
+1+n
, '\0', num
-n
);
1191 *res
++ = n
; /* store the length byte */
1196 if (e
->pack(res
, v
, e
) < 0)
1200 } while (--num
> 0);
1204 PyErr_SetString(StructError
,
1205 "too many arguments for pack format");
1217 static char unpack__doc__
[] = "\
1218 unpack(fmt, string) -> (v1, v2, ...)\n\
1219 Unpack the string, containing packed C structure data, according\n\
1220 to fmt. Requires len(string)==calcsize(fmt).\n\
1221 See struct.__doc__ for more on format strings.";
1224 struct_unpack(self
, args
)
1225 PyObject
*self
; /* Not used */
1228 const formatdef
*f
, *e
;
1229 char *str
, *start
, *fmt
, *s
;
1234 if (!PyArg_ParseTuple(args
, "ss#", &fmt
, &start
, &len
))
1236 f
= whichtable(&fmt
);
1237 size
= calcsize(fmt
, f
);
1241 PyErr_SetString(StructError
,
1242 "unpack str size does not match format");
1245 res
= PyList_New(0);
1250 while ((c
= *s
++) != '\0') {
1251 if (isspace((int)c
))
1253 if ('0' <= c
&& c
<= '9') {
1255 while ('0' <= (c
= *s
++) && c
<= '9')
1256 num
= num
*10 + (c
- '0');
1266 str
= start
+ align((int)(str
-start
), c
, e
);
1267 if (num
== 0 && c
!= 's')
1276 /* num is string size, not repeat count */
1277 v
= PyString_FromStringAndSize(str
, num
);
1283 else if (c
== 'p') {
1284 /* num is string buffer size,
1286 int n
= *(unsigned char*)str
;
1287 /* first byte (unsigned) is string size */
1290 v
= PyString_FromStringAndSize(str
+1, n
);
1297 v
= e
->unpack(str
, e
);
1302 if (v
== NULL
|| PyList_Append(res
, v
) < 0)
1305 } while (--num
> 0);
1308 v
= PyList_AsTuple(res
);
1318 /* List of functions */
1320 static PyMethodDef struct_methods
[] = {
1321 {"calcsize", struct_calcsize
, METH_VARARGS
, calcsize__doc__
},
1322 {"pack", struct_pack
, METH_VARARGS
, pack__doc__
},
1323 {"unpack", struct_unpack
, METH_VARARGS
, unpack__doc__
},
1324 {NULL
, NULL
} /* sentinel */
1328 /* Module initialization */
1335 /* Create the module and add the functions */
1336 m
= Py_InitModule4("struct", struct_methods
, struct__doc__
,
1337 (PyObject
*)NULL
, PYTHON_API_VERSION
);
1339 /* Add some symbolic constants to the module */
1340 d
= PyModule_GetDict(m
);
1341 StructError
= PyErr_NewException("struct.error", NULL
, NULL
);
1342 if (StructError
== NULL
)
1344 PyDict_SetItemString(d
, "error", StructError
);