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 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\
60 The variable struct.error is an exception raised on errors.";
71 static PyObject
*StructError
;
74 /* Define various structs to figure out the alignments of types */
78 ** XXXX We have a problem here. There are no unique alignment rules
79 ** on the PowerPC mac.
82 #pragma options align=mac68k
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 *))
101 #pragma options align=reset
104 /* Helper routine to get a Python integer and raise the appropriate error
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");
124 /* Same, but handling unsigned long */
131 if (PyLong_Check(v
)) {
132 unsigned long x
= PyLong_AsUnsignedLong(v
);
133 if (x
== (unsigned long)(-1) && PyErr_Occurred())
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!) */
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 */
172 /* Normalize f to be in the range [1.0, 2.0) */
173 if (0.5 <= f
&& f
< 1.0) {
181 PyErr_SetString(PyExc_SystemError
,
182 "frexp() result out of range");
187 /* XXX 128 itself is reserved for Inf/NaN */
188 PyErr_SetString(PyExc_OverflowError
,
189 "float too large to pack with f format");
193 /* Gradual underflow */
194 f
= ldexp(f
, 126 + e
);
197 else if (!(e
== 0 && f
== 0.0)) {
199 f
-= 1.0; /* Get rid of leading 1 */
202 f
*= 8388608.0; /* 2**23 */
203 fbits
= (long) floor(f
+ 0.5); /* Round */
206 *p
= (s
<<7) | (e
>>1);
210 *p
= (char) (((e
&1)<<7) | (fbits
>>16));
214 *p
= (fbits
>>8) & 0xFF;
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 */
244 /* Normalize f to be in the range [1.0, 2.0) */
245 if (0.5 <= f
&& f
< 1.0) {
253 PyErr_SetString(PyExc_SystemError
,
254 "frexp() result out of range");
259 /* XXX 1024 itself is reserved for Inf/NaN */
260 PyErr_SetString(PyExc_OverflowError
,
261 "float too large to pack with d format");
264 else if (e
< -1022) {
265 /* Gradual underflow */
266 f
= ldexp(f
, 1022 + e
);
269 else if (!(e
== 0 && f
== 0.0)) {
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 */
278 f
*= 16777216.0; /* 2**24 */
279 flo
= (long) floor(f
+ 0.5); /* Round */
282 *p
= (s
<<7) | (e
>>4);
286 *p
= (char) (((e
&0xF)<<4) | (fhi
>>24));
290 *p
= (fhi
>>16) & 0xFF;
294 *p
= (fhi
>>8) & 0xFF;
302 *p
= (flo
>>16) & 0xFF;
306 *p
= (flo
>>8) & 0xFF;
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 */
329 e
= (*p
& 0x7F) << 1;
334 f
= (*p
& 0x7F) << 16;
338 f
|= (*p
& 0xFF) << 8;
344 x
= (double)f
/ 8388608.0;
346 /* XXX This sadly ignores Inf/NaN issues */
358 return PyFloat_FromDouble(x
);
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 */
373 e
= (*p
& 0x7F) << 4;
378 fhi
= (*p
& 0xF) << 24;
382 fhi
|= (*p
& 0xFF) << 16;
386 fhi
|= (*p
& 0xFF) << 8;
394 flo
= (*p
& 0xFF) << 16;
398 flo
|= (*p
& 0xFF) << 8;
405 x
= (double)fhi
+ (double)flo
/ 16777216.0; /* 2**24 */
406 x
/= 268435456.0; /* 2**28 */
408 /* XXX This sadly ignores Inf/NaN */
420 return PyFloat_FromDouble(x
);
424 /* The translation function for each format character is table driven */
426 typedef struct _formatdef
{
430 PyObject
* (*unpack
) Py_PROTO((const char *,
431 const struct _formatdef
*));
432 int (*pack
) Py_PROTO((char *,
434 const struct _formatdef
*));
442 return PyString_FromStringAndSize(p
, 1);
450 return PyInt_FromLong((long) *(signed char *)p
);
458 return PyInt_FromLong((long) *(unsigned char *)p
);
466 return PyInt_FromLong((long) *(short *)p
);
474 return PyInt_FromLong((long) *(unsigned short *)p
);
482 return PyInt_FromLong((long) *(int *)p
);
490 unsigned int x
= *(unsigned int *)p
;
491 return PyLong_FromUnsignedLong((unsigned long)x
);
499 return PyInt_FromLong(*(long *)p
);
507 return PyLong_FromUnsignedLong(*(unsigned long *)p
);
516 memcpy((char *)&x
, p
, sizeof(float));
517 return PyFloat_FromDouble((double)x
);
526 memcpy((char *)&x
, p
, sizeof(double));
527 return PyFloat_FromDouble(x
);
535 return PyLong_FromVoidPtr(*(void **)p
);
545 if (get_long(v
, &x
) < 0)
557 if (!PyString_Check(v
) || PyString_Size(v
) != 1) {
558 PyErr_SetString(StructError
,
559 "char format require string of length 1");
562 *p
= *PyString_AsString(v
);
573 if (get_long(v
, &x
) < 0)
575 * (short *)p
= (short)x
;
586 if (get_long(v
, &x
) < 0)
599 if (get_ulong(v
, &x
) < 0)
601 * (unsigned int *)p
= x
;
612 if (get_long(v
, &x
) < 0)
625 if (get_ulong(v
, &x
) < 0)
627 * (unsigned long *)p
= x
;
637 float x
= (float)PyFloat_AsDouble(v
);
638 if (x
== -1 && PyErr_Occurred()) {
639 PyErr_SetString(StructError
,
640 "required argument is not a float");
643 memcpy(p
, (char *)&x
, sizeof(float));
653 double x
= PyFloat_AsDouble(v
);
654 if (x
== -1 && PyErr_Occurred()) {
655 PyErr_SetString(StructError
,
656 "required argument is not a float");
659 memcpy(p
, (char *)&x
, sizeof(double));
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");
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
},
708 x
= (x
<<8) | (*p
++ & 0xFF);
710 i
= 8*(sizeof(long) - f
->size
);
715 return PyInt_FromLong(x
);
726 x
= (x
<<8) | (*p
++ & 0xFF);
729 return PyLong_FromUnsignedLong(x
);
731 return PyInt_FromLong((long)x
);
739 return unpack_float(p
, 1);
747 return unpack_double(p
, 1);
758 if (get_long(v
, &x
) < 0)
776 if (get_ulong(v
, &x
) < 0)
792 double x
= PyFloat_AsDouble(v
);
793 if (x
== -1 && PyErr_Occurred()) {
794 PyErr_SetString(StructError
,
795 "required argument is not a float");
798 return pack_float(x
, p
, 1);
807 double x
= PyFloat_AsDouble(v
);
808 if (x
== -1 && PyErr_Occurred()) {
809 PyErr_SetString(StructError
,
810 "required argument is not a float");
813 return pack_double(x
, p
, 1);
816 static formatdef bigendian_table
[] = {
818 {'b', 1, 0, bu_int
, bp_int
},
819 {'B', 1, 0, bu_uint
, bp_int
},
820 {'c', 1, 0, nu_char
, np_char
},
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
},
842 x
= (x
<<8) | (p
[--i
] & 0xFF);
844 i
= 8*(sizeof(long) - f
->size
);
849 return PyInt_FromLong(x
);
860 x
= (x
<<8) | (p
[--i
] & 0xFF);
863 return PyLong_FromUnsignedLong(x
);
865 return PyInt_FromLong((long)x
);
873 return unpack_float(p
+3, -1);
881 return unpack_double(p
+7, -1);
892 if (get_long(v
, &x
) < 0)
910 if (get_ulong(v
, &x
) < 0)
926 double x
= PyFloat_AsDouble(v
);
927 if (x
== -1 && PyErr_Occurred()) {
928 PyErr_SetString(StructError
,
929 "required argument is not a float");
932 return pack_float(x
, p
+3, -1);
941 double x
= PyFloat_AsDouble(v
);
942 if (x
== -1 && PyErr_Occurred()) {
943 PyErr_SetString(StructError
,
944 "required argument is not a float");
947 return pack_double(x
, p
+7, -1);
950 static formatdef lilendian_table
[] = {
952 {'b', 1, 0, lu_int
, lp_int
},
953 {'B', 1, 0, lu_uint
, lp_int
},
954 {'c', 1, 0, nu_char
, np_char
},
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
*
973 const char *fmt
= (*pfmt
)++; /* May be backed out of later */
976 return lilendian_table
;
978 case '!': /* Network byte order is big-endian */
979 return bigendian_table
;
980 case '=': { /* Host byte order -- different from native in aligment! */
982 char *p
= (char *) &n
;
984 return lilendian_table
;
986 return bigendian_table
;
989 --*pfmt
; /* Back out of pointer increment */
997 /* Get the table entry for a format code */
999 static const formatdef
*
1004 for (; f
->format
!= '\0'; f
++) {
1005 if (f
->format
== c
) {
1009 PyErr_SetString(StructError
, "bad char in struct format");
1014 /* Align a size according to a format code */
1022 if (e
->format
== c
) {
1024 size
= ((size
+ e
->alignment
- 1)
1033 /* calculate the size of a format string */
1043 int size
, num
, itemsize
, x
;
1047 while ((c
= *s
++) != '\0') {
1048 if (isspace((int)c
))
1050 if ('0' <= c
&& c
<= '9') {
1052 while ('0' <= (c
= *s
++) && c
<= '9') {
1053 x
= num
*10 + (c
- '0');
1057 "overflow in item count");
1072 size
= align(size
, c
, e
);
1075 if (x
/itemsize
!= num
|| size
< 0) {
1076 PyErr_SetString(StructError
,
1077 "total struct size too long");
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.";
1092 struct_calcsize(self
, args
)
1093 PyObject
*self
; /* Not used */
1100 if (!PyArg_ParseTuple(args
, "s", &fmt
))
1102 f
= whichtable(&fmt
);
1103 size
= calcsize(fmt
, f
);
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.";
1116 struct_pack(self
, args
)
1117 PyObject
*self
; /* Not used */
1120 const formatdef
*f
, *e
;
1121 PyObject
*format
, *result
, *v
;
1125 char *s
, *res
, *restart
, *nres
;
1128 if (args
== NULL
|| !PyTuple_Check(args
) ||
1129 (n
= PyTuple_Size(args
)) < 1)
1131 PyErr_BadArgument();
1134 format
= PyTuple_GetItem(args
, 0);
1135 if (!PyArg_Parse(format
, "s", &fmt
))
1137 f
= whichtable(&fmt
);
1138 size
= calcsize(fmt
, f
);
1141 result
= PyString_FromStringAndSize((char *)NULL
, size
);
1147 res
= restart
= PyString_AsString(result
);
1149 while ((c
= *s
++) != '\0') {
1150 if (isspace((int)c
))
1152 if ('0' <= c
&& c
<= '9') {
1154 while ('0' <= (c
= *s
++) && c
<= '9')
1155 num
= num
*10 + (c
- '0');
1165 nres
= restart
+ align((int)(res
-restart
), c
, e
);
1166 /* Fill padd bytes with zeros */
1169 if (num
== 0 && c
!= 's')
1173 /* doesn't consume arguments */
1174 memset(res
, '\0', num
);
1179 PyErr_SetString(StructError
,
1180 "insufficient arguments to pack");
1183 v
= PyTuple_GetItem(args
, i
++);
1187 /* num is string size, not repeat count */
1189 if (!PyString_Check(v
)) {
1190 PyErr_SetString(StructError
,
1191 "argument for 's' must be a string");
1194 n
= PyString_Size(v
);
1198 memcpy(res
, PyString_AsString(v
), n
);
1200 memset(res
+n
, '\0', num
-n
);
1204 else if (c
== 'p') {
1205 /* num is string size + 1,
1206 to fit in the count byte */
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");
1214 n
= PyString_Size(v
);
1218 memcpy(res
+1, PyString_AsString(v
), n
);
1220 /* no real need, just to be nice */
1221 memset(res
+1+n
, '\0', num
-n
);
1222 *res
++ = n
; /* store the length byte */
1227 if (e
->pack(res
, v
, e
) < 0)
1231 } while (--num
> 0);
1235 PyErr_SetString(StructError
,
1236 "too many arguments for pack format");
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.";
1255 struct_unpack(self
, args
)
1256 PyObject
*self
; /* Not used */
1259 const formatdef
*f
, *e
;
1260 char *str
, *start
, *fmt
, *s
;
1265 if (!PyArg_ParseTuple(args
, "ss#", &fmt
, &start
, &len
))
1267 f
= whichtable(&fmt
);
1268 size
= calcsize(fmt
, f
);
1272 PyErr_SetString(StructError
,
1273 "unpack str size does not match format");
1276 res
= PyList_New(0);
1281 while ((c
= *s
++) != '\0') {
1282 if (isspace((int)c
))
1284 if ('0' <= c
&& c
<= '9') {
1286 while ('0' <= (c
= *s
++) && c
<= '9')
1287 num
= num
*10 + (c
- '0');
1297 str
= start
+ align((int)(str
-start
), c
, e
);
1298 if (num
== 0 && c
!= 's')
1307 /* num is string size, not repeat count */
1308 v
= PyString_FromStringAndSize(str
, num
);
1314 else if (c
== 'p') {
1315 /* num is string buffer size,
1317 int n
= *(unsigned char*)str
;
1318 /* first byte (unsigned) is string size */
1321 v
= PyString_FromStringAndSize(str
+1, n
);
1328 v
= e
->unpack(str
, e
);
1333 if (v
== NULL
|| PyList_Append(res
, v
) < 0)
1336 } while (--num
> 0);
1339 v
= PyList_AsTuple(res
);
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 */
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
)
1375 PyDict_SetItemString(d
, "error", StructError
);