blob: 4d6012258b4d8a557d2b54bd92e8f42e664d175b [file] [log] [blame]
Guido van Rossum02975121992-08-17 08:55:12 +00001
2/* struct module -- pack values into and (out of) strings */
3
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00004/* New version supporting byte order, alignment and size options,
5 character strings, and unsigned numbers */
6
Guido van Rossum414fd481997-12-19 04:24:24 +00007static char struct__doc__[] = "\
8Functions to convert between Python values and C structs.\n\
9Python strings are used to hold the data representing the C struct\n\
10and also as format strings to describe the layout of data in the C struct.\n\
11\n\
12The optional first format char indicates byte ordering and alignment:\n\
13 @: native w/native alignment(default)\n\
14 =: native w/standard alignment\n\
15 <: little-endian, std. alignment\n\
16 >: big-endian, std. alignment\n\
17 !: network, std (same as >)\n\
18\n\
19The remaining chars indicate types of args and must match exactly;\n\
20these can be preceded by a decimal repeat count:\n\
21 x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
22 h:short; H:unsigned short; i:int; I:unsigned int;\n\
23 l:long; L:unsigned long; f:float; d:double.\n\
24Special cases (preceding decimal count indicates length):\n\
25 s:string (array of char); p: pascal string (w. count byte).\n\
Guido van Rossum78694d91998-09-18 14:14:13 +000026Special case (only available in native format):\n\
27 P:an integer type that is wide enough to hold a pointer.\n\
Guido van Rossum414fd481997-12-19 04:24:24 +000028Whitespace between formats is ignored.\n\
29\n\
30The variable struct.error is an exception raised on errors.";
31
Barry Warsaw30695fa1996-12-12 23:32:31 +000032#include "Python.h"
Guido van Rossum02975121992-08-17 08:55:12 +000033
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000034#include <limits.h>
Guido van Rossume20aef51997-08-26 20:39:54 +000035#include <ctype.h>
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000036
37
38/* Exception */
39
Barry Warsaw30695fa1996-12-12 23:32:31 +000040static PyObject *StructError;
Guido van Rossum02975121992-08-17 08:55:12 +000041
42
43/* Define various structs to figure out the alignments of types */
44
Jack Jansen971e1df1995-02-02 14:29:10 +000045#ifdef __MWERKS__
46/*
47** XXXX We have a problem here. There are no unique alignment rules
48** on the PowerPC mac.
49*/
50#ifdef __powerc
51#pragma options align=mac68k
52#endif
53#endif /* __MWERKS__ */
54
Guido van Rossum02975121992-08-17 08:55:12 +000055typedef struct { char c; short x; } s_short;
56typedef struct { char c; int x; } s_int;
57typedef struct { char c; long x; } s_long;
58typedef struct { char c; float x; } s_float;
59typedef struct { char c; double x; } s_double;
Guido van Rossum78694d91998-09-18 14:14:13 +000060typedef struct { char c; void *x; } s_void_p;
Guido van Rossum02975121992-08-17 08:55:12 +000061
62#define SHORT_ALIGN (sizeof(s_short) - sizeof(short))
63#define INT_ALIGN (sizeof(s_int) - sizeof(int))
64#define LONG_ALIGN (sizeof(s_long) - sizeof(long))
65#define FLOAT_ALIGN (sizeof(s_float) - sizeof(float))
66#define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))
Guido van Rossum78694d91998-09-18 14:14:13 +000067#define VOID_P_ALIGN (sizeof(s_void_p) - sizeof(void *))
Guido van Rossum02975121992-08-17 08:55:12 +000068
Martin v. Löwis2af72d52000-09-15 08:10:33 +000069#define STRINGIFY(x) #x
70
Jack Jansen971e1df1995-02-02 14:29:10 +000071#ifdef __powerc
72#pragma options align=reset
73#endif
74
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000075/* Helper routine to get a Python integer and raise the appropriate error
76 if it isn't one */
77
78static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +000079get_long(PyObject *v, long *p)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000080{
81 long x = PyInt_AsLong(v);
82 if (x == -1 && PyErr_Occurred()) {
Fred Draked3dbb381998-05-28 04:35:49 +000083 if (PyErr_ExceptionMatches(PyExc_TypeError))
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000084 PyErr_SetString(StructError,
85 "required argument is not an integer");
86 return -1;
87 }
88 *p = x;
89 return 0;
90}
91
92
Guido van Rossum60c50611996-12-31 16:29:52 +000093/* Same, but handling unsigned long */
94
95static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +000096get_ulong(PyObject *v, unsigned long *p)
Guido van Rossum60c50611996-12-31 16:29:52 +000097{
Guido van Rossum6c87eca1997-01-03 19:08:16 +000098 if (PyLong_Check(v)) {
99 unsigned long x = PyLong_AsUnsignedLong(v);
100 if (x == (unsigned long)(-1) && PyErr_Occurred())
Guido van Rossum60c50611996-12-31 16:29:52 +0000101 return -1;
Guido van Rossum6c87eca1997-01-03 19:08:16 +0000102 *p = x;
103 return 0;
Guido van Rossum60c50611996-12-31 16:29:52 +0000104 }
Guido van Rossum6c87eca1997-01-03 19:08:16 +0000105 else {
106 return get_long(v, (long *)p);
107 }
Guido van Rossum60c50611996-12-31 16:29:52 +0000108}
109
110
Guido van Rossum74679b41997-01-02 22:21:36 +0000111/* Floating point helpers */
112
113/* These use ANSI/IEEE Standard 754-1985 (Standard for Binary Floating
114 Point Arithmetic). See the following URL:
115 http://www.psc.edu/general/software/packages/ieee/ieee.html */
116
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000117/* XXX Inf/NaN are not handled quite right (but underflow is!) */
Guido van Rossum74679b41997-01-02 22:21:36 +0000118
119static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000120pack_float(double x, /* The number to pack */
121 char *p, /* Where to pack the high order byte */
122 int incr) /* 1 for big-endian; -1 for little-endian */
Guido van Rossum74679b41997-01-02 22:21:36 +0000123{
124 int s;
125 int e;
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000126 double f;
127 long fbits;
Guido van Rossum74679b41997-01-02 22:21:36 +0000128
129 if (x < 0) {
130 s = 1;
131 x = -x;
132 }
133 else
134 s = 0;
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000135
136 f = frexp(x, &e);
137
138 /* Normalize f to be in the range [1.0, 2.0) */
139 if (0.5 <= f && f < 1.0) {
140 f *= 2.0;
Guido van Rossum74679b41997-01-02 22:21:36 +0000141 e--;
142 }
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000143 else if (f == 0.0) {
Guido van Rossum74679b41997-01-02 22:21:36 +0000144 e = 0;
145 }
146 else {
147 PyErr_SetString(PyExc_SystemError,
148 "frexp() result out of range");
149 return -1;
150 }
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000151
152 if (e >= 128) {
153 /* XXX 128 itself is reserved for Inf/NaN */
Guido van Rossum74679b41997-01-02 22:21:36 +0000154 PyErr_SetString(PyExc_OverflowError,
155 "float too large to pack with f format");
156 return -1;
157 }
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000158 else if (e < -126) {
159 /* Gradual underflow */
160 f = ldexp(f, 126 + e);
Guido van Rossum74679b41997-01-02 22:21:36 +0000161 e = 0;
162 }
Guido van Rossum8f3c8121997-11-04 17:12:33 +0000163 else if (!(e == 0 && f == 0.0)) {
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000164 e += 127;
165 f -= 1.0; /* Get rid of leading 1 */
Guido van Rossum74679b41997-01-02 22:21:36 +0000166 }
167
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000168 f *= 8388608.0; /* 2**23 */
169 fbits = (long) floor(f + 0.5); /* Round */
170
Guido van Rossum74679b41997-01-02 22:21:36 +0000171 /* First byte */
172 *p = (s<<7) | (e>>1);
173 p += incr;
174
175 /* Second byte */
Guido van Rossum7844e381997-04-11 20:44:04 +0000176 *p = (char) (((e&1)<<7) | (fbits>>16));
Guido van Rossum74679b41997-01-02 22:21:36 +0000177 p += incr;
178
179 /* Third byte */
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000180 *p = (fbits>>8) & 0xFF;
Guido van Rossum74679b41997-01-02 22:21:36 +0000181 p += incr;
182
183 /* Fourth byte */
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000184 *p = fbits&0xFF;
Guido van Rossum74679b41997-01-02 22:21:36 +0000185
186 /* Done */
187 return 0;
188}
189
190static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000191pack_double(double x, /* The number to pack */
192 char *p, /* Where to pack the high order byte */
193 int incr) /* 1 for big-endian; -1 for little-endian */
Guido van Rossum74679b41997-01-02 22:21:36 +0000194{
195 int s;
196 int e;
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000197 double f;
Guido van Rossum74679b41997-01-02 22:21:36 +0000198 long fhi, flo;
199
200 if (x < 0) {
201 s = 1;
202 x = -x;
203 }
204 else
205 s = 0;
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000206
207 f = frexp(x, &e);
208
209 /* Normalize f to be in the range [1.0, 2.0) */
210 if (0.5 <= f && f < 1.0) {
211 f *= 2.0;
Guido van Rossum74679b41997-01-02 22:21:36 +0000212 e--;
213 }
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000214 else if (f == 0.0) {
Guido van Rossum74679b41997-01-02 22:21:36 +0000215 e = 0;
216 }
217 else {
218 PyErr_SetString(PyExc_SystemError,
219 "frexp() result out of range");
220 return -1;
221 }
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000222
223 if (e >= 1024) {
224 /* XXX 1024 itself is reserved for Inf/NaN */
Guido van Rossum74679b41997-01-02 22:21:36 +0000225 PyErr_SetString(PyExc_OverflowError,
226 "float too large to pack with d format");
227 return -1;
228 }
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000229 else if (e < -1022) {
230 /* Gradual underflow */
231 f = ldexp(f, 1022 + e);
Guido van Rossum74679b41997-01-02 22:21:36 +0000232 e = 0;
233 }
Guido van Rossum8f3c8121997-11-04 17:12:33 +0000234 else if (!(e == 0 && f == 0.0)) {
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000235 e += 1023;
236 f -= 1.0; /* Get rid of leading 1 */
Guido van Rossum74679b41997-01-02 22:21:36 +0000237 }
238
Guido van Rossum4ccc5311997-01-02 23:23:20 +0000239 /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
240 f *= 268435456.0; /* 2**28 */
241 fhi = (long) floor(f); /* Truncate */
242 f -= (double)fhi;
243 f *= 16777216.0; /* 2**24 */
244 flo = (long) floor(f + 0.5); /* Round */
245
Guido van Rossum74679b41997-01-02 22:21:36 +0000246 /* First byte */
247 *p = (s<<7) | (e>>4);
248 p += incr;
249
250 /* Second byte */
Guido van Rossum7844e381997-04-11 20:44:04 +0000251 *p = (char) (((e&0xF)<<4) | (fhi>>24));
Guido van Rossum74679b41997-01-02 22:21:36 +0000252 p += incr;
253
254 /* Third byte */
255 *p = (fhi>>16) & 0xFF;
256 p += incr;
257
258 /* Fourth byte */
259 *p = (fhi>>8) & 0xFF;
260 p += incr;
261
262 /* Fifth byte */
263 *p = fhi & 0xFF;
264 p += incr;
265
266 /* Sixth byte */
267 *p = (flo>>16) & 0xFF;
268 p += incr;
269
270 /* Seventh byte */
271 *p = (flo>>8) & 0xFF;
272 p += incr;
273
274 /* Eighth byte */
275 *p = flo & 0xFF;
276 p += incr;
277
278 /* Done */
279 return 0;
280}
281
282static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000283unpack_float(const char *p, /* Where the high order byte is */
284 int incr) /* 1 for big-endian; -1 for little-endian */
Guido van Rossum74679b41997-01-02 22:21:36 +0000285{
286 int s;
287 int e;
288 long f;
289 double x;
290
291 /* First byte */
292 s = (*p>>7) & 1;
293 e = (*p & 0x7F) << 1;
294 p += incr;
295
296 /* Second byte */
297 e |= (*p>>7) & 1;
298 f = (*p & 0x7F) << 16;
299 p += incr;
300
301 /* Third byte */
302 f |= (*p & 0xFF) << 8;
303 p += incr;
304
305 /* Fourth byte */
306 f |= *p & 0xFF;
307
308 x = (double)f / 8388608.0;
309
310 /* XXX This sadly ignores Inf/NaN issues */
Guido van Rossum07ef6551997-01-02 22:31:07 +0000311 if (e == 0)
312 e = -126;
313 else {
314 x += 1.0;
315 e -= 127;
316 }
317 x = ldexp(x, e);
Guido van Rossum74679b41997-01-02 22:21:36 +0000318
319 if (s)
320 x = -x;
321
322 return PyFloat_FromDouble(x);
323}
324
325static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000326unpack_double(const char *p, /* Where the high order byte is */
327 int incr) /* 1 for big-endian; -1 for little-endian */
Guido van Rossum74679b41997-01-02 22:21:36 +0000328{
329 int s;
330 int e;
331 long fhi, flo;
332 double x;
333
334 /* First byte */
335 s = (*p>>7) & 1;
336 e = (*p & 0x7F) << 4;
337 p += incr;
338
339 /* Second byte */
340 e |= (*p>>4) & 0xF;
341 fhi = (*p & 0xF) << 24;
342 p += incr;
343
344 /* Third byte */
345 fhi |= (*p & 0xFF) << 16;
346 p += incr;
347
348 /* Fourth byte */
349 fhi |= (*p & 0xFF) << 8;
350 p += incr;
351
352 /* Fifth byte */
353 fhi |= *p & 0xFF;
354 p += incr;
355
356 /* Sixth byte */
357 flo = (*p & 0xFF) << 16;
358 p += incr;
359
360 /* Seventh byte */
361 flo |= (*p & 0xFF) << 8;
362 p += incr;
363
364 /* Eighth byte */
365 flo |= *p & 0xFF;
366 p += incr;
367
368 x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
369 x /= 268435456.0; /* 2**28 */
370
371 /* XXX This sadly ignores Inf/NaN */
Guido van Rossum07ef6551997-01-02 22:31:07 +0000372 if (e == 0)
373 e = -1022;
374 else {
375 x += 1.0;
376 e -= 1023;
377 }
378 x = ldexp(x, e);
Guido van Rossum74679b41997-01-02 22:21:36 +0000379
380 if (s)
381 x = -x;
382
383 return PyFloat_FromDouble(x);
384}
385
386
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000387/* The translation function for each format character is table driven */
388
389typedef struct _formatdef {
390 char format;
391 int size;
392 int alignment;
Tim Petersdbd9ba62000-07-09 03:09:57 +0000393 PyObject* (*unpack)(const char *,
394 const struct _formatdef *);
395 int (*pack)(char *, PyObject *,
396 const struct _formatdef *);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000397} formatdef;
398
399static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000400nu_char(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000401{
402 return PyString_FromStringAndSize(p, 1);
403}
404
405static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000406nu_byte(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000407{
408 return PyInt_FromLong((long) *(signed char *)p);
409}
410
411static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000412nu_ubyte(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000413{
414 return PyInt_FromLong((long) *(unsigned char *)p);
415}
416
417static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000418nu_short(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000419{
420 return PyInt_FromLong((long) *(short *)p);
421}
422
423static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000424nu_ushort(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000425{
426 return PyInt_FromLong((long) *(unsigned short *)p);
427}
428
429static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000430nu_int(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000431{
432 return PyInt_FromLong((long) *(int *)p);
433}
434
435static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000436nu_uint(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000437{
438 unsigned int x = *(unsigned int *)p;
Guido van Rossum6c87eca1997-01-03 19:08:16 +0000439 return PyLong_FromUnsignedLong((unsigned long)x);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000440}
441
442static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000443nu_long(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000444{
445 return PyInt_FromLong(*(long *)p);
446}
447
448static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000449nu_ulong(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000450{
Guido van Rossum6c87eca1997-01-03 19:08:16 +0000451 return PyLong_FromUnsignedLong(*(unsigned long *)p);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000452}
453
454static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000455nu_float(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000456{
457 float x;
458 memcpy((char *)&x, p, sizeof(float));
459 return PyFloat_FromDouble((double)x);
460}
461
462static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000463nu_double(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000464{
465 double x;
466 memcpy((char *)&x, p, sizeof(double));
467 return PyFloat_FromDouble(x);
468}
469
Guido van Rossum78694d91998-09-18 14:14:13 +0000470static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000471nu_void_p(const char *p, const formatdef *f)
Guido van Rossum78694d91998-09-18 14:14:13 +0000472{
473 return PyLong_FromVoidPtr(*(void **)p);
474}
475
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000476static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000477np_byte(char *p, PyObject *v, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000478{
479 long x;
480 if (get_long(v, &x) < 0)
481 return -1;
Martin v. Löwis66de5492000-09-15 07:31:57 +0000482 if (x < -128 || x > 127){
483 PyErr_SetString(StructError,
484 "byte format requires -128<=number<=127");
485 return -1;
486 }
487 *p = (char)x;
488 return 0;
489}
490
491static int
492np_ubyte(char *p, PyObject *v, const formatdef *f)
493{
494 long x;
495 if (get_long(v, &x) < 0)
496 return -1;
497 if (x < 0 || x > 255){
498 PyErr_SetString(StructError,
499 "ubyte format requires 0<=number<=255");
500 return -1;
501 }
Guido van Rossum7844e381997-04-11 20:44:04 +0000502 *p = (char)x;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000503 return 0;
504}
505
506static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000507np_char(char *p, PyObject *v, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000508{
509 if (!PyString_Check(v) || PyString_Size(v) != 1) {
510 PyErr_SetString(StructError,
511 "char format require string of length 1");
512 return -1;
513 }
514 *p = *PyString_AsString(v);
515 return 0;
516}
517
518static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000519np_short(char *p, PyObject *v, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000520{
521 long x;
522 if (get_long(v, &x) < 0)
523 return -1;
Martin v. Löwis2af72d52000-09-15 08:10:33 +0000524 if (x < SHRT_MIN || x > SHRT_MAX){
Martin v. Löwis66de5492000-09-15 07:31:57 +0000525 PyErr_SetString(StructError,
Martin v. Löwis2af72d52000-09-15 08:10:33 +0000526 "short format requires " STRINGIFY(SHRT_MIN)
527 "<=number<=" STRINGIFY(SHRT_MAX));
Martin v. Löwis66de5492000-09-15 07:31:57 +0000528 return -1;
529 }
Guido van Rossum7844e381997-04-11 20:44:04 +0000530 * (short *)p = (short)x;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000531 return 0;
532}
533
534static int
Martin v. Löwis66de5492000-09-15 07:31:57 +0000535np_ushort(char *p, PyObject *v, const formatdef *f)
536{
537 long x;
538 if (get_long(v, &x) < 0)
539 return -1;
Martin v. Löwis2af72d52000-09-15 08:10:33 +0000540 if (x < 0 || x > USHRT_MAX){
Martin v. Löwis66de5492000-09-15 07:31:57 +0000541 PyErr_SetString(StructError,
Martin v. Löwis2af72d52000-09-15 08:10:33 +0000542 "short format requires 0<=number<=" STRINGIFY(USHRT_MAX));
Martin v. Löwis66de5492000-09-15 07:31:57 +0000543 return -1;
544 }
545 * (unsigned short *)p = (unsigned short)x;
546 return 0;
547}
548
549static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000550np_int(char *p, PyObject *v, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000551{
552 long x;
553 if (get_long(v, &x) < 0)
554 return -1;
555 * (int *)p = x;
556 return 0;
557}
558
559static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000560np_uint(char *p, PyObject *v, const formatdef *f)
Guido van Rossum60c50611996-12-31 16:29:52 +0000561{
562 unsigned long x;
563 if (get_ulong(v, &x) < 0)
564 return -1;
565 * (unsigned int *)p = x;
566 return 0;
567}
568
569static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000570np_long(char *p, PyObject *v, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000571{
572 long x;
573 if (get_long(v, &x) < 0)
574 return -1;
575 * (long *)p = x;
576 return 0;
577}
578
579static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000580np_ulong(char *p, PyObject *v, const formatdef *f)
Guido van Rossum60c50611996-12-31 16:29:52 +0000581{
582 unsigned long x;
583 if (get_ulong(v, &x) < 0)
584 return -1;
585 * (unsigned long *)p = x;
586 return 0;
587}
588
589static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000590np_float(char *p, PyObject *v, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000591{
592 float x = (float)PyFloat_AsDouble(v);
593 if (x == -1 && PyErr_Occurred()) {
594 PyErr_SetString(StructError,
595 "required argument is not a float");
596 return -1;
597 }
598 memcpy(p, (char *)&x, sizeof(float));
599 return 0;
600}
601
602static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000603np_double(char *p, PyObject *v, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000604{
605 double x = PyFloat_AsDouble(v);
606 if (x == -1 && PyErr_Occurred()) {
607 PyErr_SetString(StructError,
608 "required argument is not a float");
609 return -1;
610 }
611 memcpy(p, (char *)&x, sizeof(double));
612 return 0;
613}
614
Guido van Rossum78694d91998-09-18 14:14:13 +0000615static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000616np_void_p(char *p, PyObject *v, const formatdef *f)
Guido van Rossum78694d91998-09-18 14:14:13 +0000617{
618 void *x = PyLong_AsVoidPtr(v);
619 if (x == NULL && PyErr_Occurred()) {
620 /* ### hrm. PyLong_AsVoidPtr raises SystemError */
621 if (PyErr_ExceptionMatches(PyExc_TypeError))
622 PyErr_SetString(StructError,
623 "required argument is not an integer");
624 return -1;
625 }
626 *(void **)p = x;
627 return 0;
628}
629
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000630static formatdef native_table[] = {
631 {'x', sizeof(char), 0, NULL},
632 {'b', sizeof(char), 0, nu_byte, np_byte},
Martin v. Löwis66de5492000-09-15 07:31:57 +0000633 {'B', sizeof(char), 0, nu_ubyte, np_ubyte},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000634 {'c', sizeof(char), 0, nu_char, np_char},
635 {'s', sizeof(char), 0, NULL},
Guido van Rossum9eb671f1997-09-05 07:08:39 +0000636 {'p', sizeof(char), 0, NULL},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000637 {'h', sizeof(short), SHORT_ALIGN, nu_short, np_short},
Martin v. Löwis66de5492000-09-15 07:31:57 +0000638 {'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_ushort},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000639 {'i', sizeof(int), INT_ALIGN, nu_int, np_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000640 {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000641 {'l', sizeof(long), LONG_ALIGN, nu_long, np_long},
Guido van Rossum60c50611996-12-31 16:29:52 +0000642 {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000643 {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
644 {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
Guido van Rossum78694d91998-09-18 14:14:13 +0000645 {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000646 {0}
647};
648
649static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000650bu_int(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000651{
652 long x = 0;
653 int i = f->size;
654 do {
655 x = (x<<8) | (*p++ & 0xFF);
656 } while (--i > 0);
657 i = 8*(sizeof(long) - f->size);
658 if (i) {
659 x <<= i;
660 x >>= i;
661 }
662 return PyInt_FromLong(x);
663}
664
665static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000666bu_uint(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000667{
Guido van Rossum6c87eca1997-01-03 19:08:16 +0000668 unsigned long x = 0;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000669 int i = f->size;
670 do {
671 x = (x<<8) | (*p++ & 0xFF);
672 } while (--i > 0);
Guido van Rossum39ef2271998-06-29 04:00:40 +0000673 if (f->size >= 4)
674 return PyLong_FromUnsignedLong(x);
675 else
676 return PyInt_FromLong((long)x);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000677}
678
Guido van Rossum74679b41997-01-02 22:21:36 +0000679static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000680bu_float(const char *p, const formatdef *f)
Guido van Rossum74679b41997-01-02 22:21:36 +0000681{
682 return unpack_float(p, 1);
683}
684
685static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000686bu_double(const char *p, const formatdef *f)
Guido van Rossum74679b41997-01-02 22:21:36 +0000687{
688 return unpack_double(p, 1);
689}
690
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000691static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000692bp_int(char *p, PyObject *v, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000693{
694 long x;
695 int i;
696 if (get_long(v, &x) < 0)
697 return -1;
698 i = f->size;
699 do {
Guido van Rossum7844e381997-04-11 20:44:04 +0000700 p[--i] = (char)x;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000701 x >>= 8;
702 } while (i > 0);
703 return 0;
704}
705
Guido van Rossum60c50611996-12-31 16:29:52 +0000706static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000707bp_uint(char *p, PyObject *v, const formatdef *f)
Guido van Rossum60c50611996-12-31 16:29:52 +0000708{
709 unsigned long x;
710 int i;
711 if (get_ulong(v, &x) < 0)
712 return -1;
713 i = f->size;
714 do {
Guido van Rossum7844e381997-04-11 20:44:04 +0000715 p[--i] = (char)x;
Guido van Rossum60c50611996-12-31 16:29:52 +0000716 x >>= 8;
717 } while (i > 0);
718 return 0;
719}
720
Guido van Rossum74679b41997-01-02 22:21:36 +0000721static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000722bp_float(char *p, PyObject *v, const formatdef *f)
Guido van Rossum74679b41997-01-02 22:21:36 +0000723{
724 double x = PyFloat_AsDouble(v);
725 if (x == -1 && PyErr_Occurred()) {
726 PyErr_SetString(StructError,
727 "required argument is not a float");
728 return -1;
729 }
730 return pack_float(x, p, 1);
731}
732
733static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000734bp_double(char *p, PyObject *v, const formatdef *f)
Guido van Rossum74679b41997-01-02 22:21:36 +0000735{
736 double x = PyFloat_AsDouble(v);
737 if (x == -1 && PyErr_Occurred()) {
738 PyErr_SetString(StructError,
739 "required argument is not a float");
740 return -1;
741 }
742 return pack_double(x, p, 1);
743}
744
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000745static formatdef bigendian_table[] = {
746 {'x', 1, 0, NULL},
747 {'b', 1, 0, bu_int, bp_int},
748 {'B', 1, 0, bu_uint, bp_int},
749 {'c', 1, 0, nu_char, np_char},
750 {'s', 1, 0, NULL},
Guido van Rossum9eb671f1997-09-05 07:08:39 +0000751 {'p', 1, 0, NULL},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000752 {'h', 2, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000753 {'H', 2, 0, bu_uint, bp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000754 {'i', 4, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000755 {'I', 4, 0, bu_uint, bp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000756 {'l', 4, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000757 {'L', 4, 0, bu_uint, bp_uint},
Guido van Rossum74679b41997-01-02 22:21:36 +0000758 {'f', 4, 0, bu_float, bp_float},
759 {'d', 8, 0, bu_double, bp_double},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000760 {0}
761};
762
763static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000764lu_int(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000765{
766 long x = 0;
767 int i = f->size;
768 do {
769 x = (x<<8) | (p[--i] & 0xFF);
770 } while (i > 0);
771 i = 8*(sizeof(long) - f->size);
772 if (i) {
773 x <<= i;
774 x >>= i;
775 }
776 return PyInt_FromLong(x);
777}
778
779static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000780lu_uint(const char *p, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000781{
Guido van Rossum6c87eca1997-01-03 19:08:16 +0000782 unsigned long x = 0;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000783 int i = f->size;
784 do {
785 x = (x<<8) | (p[--i] & 0xFF);
786 } while (i > 0);
Guido van Rossum39ef2271998-06-29 04:00:40 +0000787 if (f->size >= 4)
788 return PyLong_FromUnsignedLong(x);
789 else
790 return PyInt_FromLong((long)x);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000791}
792
Guido van Rossum74679b41997-01-02 22:21:36 +0000793static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000794lu_float(const char *p, const formatdef *f)
Guido van Rossum74679b41997-01-02 22:21:36 +0000795{
796 return unpack_float(p+3, -1);
797}
798
799static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000800lu_double(const char *p, const formatdef *f)
Guido van Rossum74679b41997-01-02 22:21:36 +0000801{
802 return unpack_double(p+7, -1);
803}
804
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000805static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000806lp_int(char *p, PyObject *v, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000807{
808 long x;
809 int i;
810 if (get_long(v, &x) < 0)
811 return -1;
812 i = f->size;
813 do {
Guido van Rossum7844e381997-04-11 20:44:04 +0000814 *p++ = (char)x;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000815 x >>= 8;
816 } while (--i > 0);
817 return 0;
818}
819
Guido van Rossum60c50611996-12-31 16:29:52 +0000820static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000821lp_uint(char *p, PyObject *v, const formatdef *f)
Guido van Rossum60c50611996-12-31 16:29:52 +0000822{
823 unsigned long x;
824 int i;
825 if (get_ulong(v, &x) < 0)
826 return -1;
827 i = f->size;
828 do {
Guido van Rossum7844e381997-04-11 20:44:04 +0000829 *p++ = (char)x;
Guido van Rossum60c50611996-12-31 16:29:52 +0000830 x >>= 8;
831 } while (--i > 0);
832 return 0;
833}
834
Guido van Rossum74679b41997-01-02 22:21:36 +0000835static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000836lp_float(char *p, PyObject *v, const formatdef *f)
Guido van Rossum74679b41997-01-02 22:21:36 +0000837{
838 double x = PyFloat_AsDouble(v);
839 if (x == -1 && PyErr_Occurred()) {
840 PyErr_SetString(StructError,
841 "required argument is not a float");
842 return -1;
843 }
844 return pack_float(x, p+3, -1);
845}
846
847static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000848lp_double(char *p, PyObject *v, const formatdef *f)
Guido van Rossum74679b41997-01-02 22:21:36 +0000849{
850 double x = PyFloat_AsDouble(v);
851 if (x == -1 && PyErr_Occurred()) {
852 PyErr_SetString(StructError,
853 "required argument is not a float");
854 return -1;
855 }
856 return pack_double(x, p+7, -1);
857}
858
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000859static formatdef lilendian_table[] = {
860 {'x', 1, 0, NULL},
861 {'b', 1, 0, lu_int, lp_int},
862 {'B', 1, 0, lu_uint, lp_int},
863 {'c', 1, 0, nu_char, np_char},
864 {'s', 1, 0, NULL},
Guido van Rossum9eb671f1997-09-05 07:08:39 +0000865 {'p', 1, 0, NULL},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000866 {'h', 2, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000867 {'H', 2, 0, lu_uint, lp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000868 {'i', 4, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000869 {'I', 4, 0, lu_uint, lp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000870 {'l', 4, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000871 {'L', 4, 0, lu_uint, lp_uint},
Guido van Rossum74679b41997-01-02 22:21:36 +0000872 {'f', 4, 0, lu_float, lp_float},
873 {'d', 8, 0, lu_double, lp_double},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000874 {0}
875};
876
877
878static const formatdef *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000879whichtable(char **pfmt)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000880{
881 const char *fmt = (*pfmt)++; /* May be backed out of later */
882 switch (*fmt) {
883 case '<':
884 return lilendian_table;
885 case '>':
886 case '!': /* Network byte order is big-endian */
887 return bigendian_table;
888 case '=': { /* Host byte order -- different from native in aligment! */
889 int n = 1;
890 char *p = (char *) &n;
891 if (*p == 1)
892 return lilendian_table;
893 else
894 return bigendian_table;
895 }
896 default:
897 --*pfmt; /* Back out of pointer increment */
898 /* Fall through */
899 case '@':
900 return native_table;
901 }
902}
903
904
905/* Get the table entry for a format code */
906
907static const formatdef *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000908getentry(int c, const formatdef *f)
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000909{
910 for (; f->format != '\0'; f++) {
911 if (f->format == c) {
912 return f;
913 }
914 }
915 PyErr_SetString(StructError, "bad char in struct format");
916 return NULL;
917}
918
919
Guido van Rossum02975121992-08-17 08:55:12 +0000920/* Align a size according to a format code */
921
922static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000923align(int size, int c, const formatdef *e)
Guido van Rossum02975121992-08-17 08:55:12 +0000924{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000925 if (e->format == c) {
926 if (e->alignment) {
927 size = ((size + e->alignment - 1)
928 / e->alignment)
929 * e->alignment;
930 }
Guido van Rossum02975121992-08-17 08:55:12 +0000931 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000932 return size;
Guido van Rossum02975121992-08-17 08:55:12 +0000933}
934
935
936/* calculate the size of a format string */
937
938static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000939calcsize(const char *fmt, const formatdef *f)
Guido van Rossum02975121992-08-17 08:55:12 +0000940{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000941 const formatdef *e;
942 const char *s;
Guido van Rossum02975121992-08-17 08:55:12 +0000943 char c;
944 int size, num, itemsize, x;
945
946 s = fmt;
947 size = 0;
948 while ((c = *s++) != '\0') {
Guido van Rossum730806d1998-04-10 22:27:42 +0000949 if (isspace((int)c))
Guido van Rossume20aef51997-08-26 20:39:54 +0000950 continue;
Guido van Rossum02975121992-08-17 08:55:12 +0000951 if ('0' <= c && c <= '9') {
952 num = c - '0';
953 while ('0' <= (c = *s++) && c <= '9') {
954 x = num*10 + (c - '0');
955 if (x/10 != num) {
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000956 PyErr_SetString(
957 StructError,
958 "overflow in item count");
Guido van Rossum02975121992-08-17 08:55:12 +0000959 return -1;
960 }
961 num = x;
962 }
963 if (c == '\0')
964 break;
965 }
966 else
967 num = 1;
968
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000969 e = getentry(c, f);
970 if (e == NULL)
Guido van Rossum02975121992-08-17 08:55:12 +0000971 return -1;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000972 itemsize = e->size;
973 size = align(size, c, e);
Guido van Rossum02975121992-08-17 08:55:12 +0000974 x = num * itemsize;
975 size += x;
976 if (x/itemsize != num || size < 0) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000977 PyErr_SetString(StructError,
978 "total struct size too long");
Guido van Rossum02975121992-08-17 08:55:12 +0000979 return -1;
980 }
Guido van Rossum02975121992-08-17 08:55:12 +0000981 }
982
983 return size;
984}
985
986
Guido van Rossum414fd481997-12-19 04:24:24 +0000987static char calcsize__doc__[] = "\
988calcsize(fmt) -> int\n\
989Return size of C struct described by format string fmt.\n\
990See struct.__doc__ for more on format strings.";
Guido van Rossum02975121992-08-17 08:55:12 +0000991
Barry Warsaw30695fa1996-12-12 23:32:31 +0000992static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000993struct_calcsize(PyObject *self, PyObject *args)
Guido van Rossum02975121992-08-17 08:55:12 +0000994{
995 char *fmt;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000996 const formatdef *f;
Guido van Rossum02975121992-08-17 08:55:12 +0000997 int size;
998
Guido van Rossum43713e52000-02-29 13:59:29 +0000999 if (!PyArg_ParseTuple(args, "s:calcsize", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +00001000 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001001 f = whichtable(&fmt);
1002 size = calcsize(fmt, f);
Guido van Rossum02975121992-08-17 08:55:12 +00001003 if (size < 0)
1004 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001005 return PyInt_FromLong((long)size);
Guido van Rossum02975121992-08-17 08:55:12 +00001006}
1007
1008
Guido van Rossum414fd481997-12-19 04:24:24 +00001009static char pack__doc__[] = "\
1010pack(fmt, v1, v2, ...) -> string\n\
1011Return string containing values v1, v2, ... packed according to fmt.\n\
1012See struct.__doc__ for more on format strings.";
Guido van Rossum02975121992-08-17 08:55:12 +00001013
Barry Warsaw30695fa1996-12-12 23:32:31 +00001014static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +00001015struct_pack(PyObject *self, PyObject *args)
Guido van Rossum02975121992-08-17 08:55:12 +00001016{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001017 const formatdef *f, *e;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001018 PyObject *format, *result, *v;
Guido van Rossum02975121992-08-17 08:55:12 +00001019 char *fmt;
1020 int size, num;
1021 int i, n;
Guido van Rossumb9d338c1997-01-03 15:40:33 +00001022 char *s, *res, *restart, *nres;
Guido van Rossum02975121992-08-17 08:55:12 +00001023 char c;
Guido van Rossum02975121992-08-17 08:55:12 +00001024
Barry Warsaw30695fa1996-12-12 23:32:31 +00001025 if (args == NULL || !PyTuple_Check(args) ||
1026 (n = PyTuple_Size(args)) < 1)
1027 {
Fred Drake137507e2000-06-01 02:02:46 +00001028 PyErr_SetString(PyExc_TypeError,
1029 "struct.pack requires at least one argument");
Guido van Rossum02975121992-08-17 08:55:12 +00001030 return NULL;
1031 }
Barry Warsaw30695fa1996-12-12 23:32:31 +00001032 format = PyTuple_GetItem(args, 0);
1033 if (!PyArg_Parse(format, "s", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +00001034 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001035 f = whichtable(&fmt);
1036 size = calcsize(fmt, f);
Guido van Rossum02975121992-08-17 08:55:12 +00001037 if (size < 0)
1038 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001039 result = PyString_FromStringAndSize((char *)NULL, size);
Guido van Rossum02975121992-08-17 08:55:12 +00001040 if (result == NULL)
1041 return NULL;
1042
1043 s = fmt;
1044 i = 1;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001045 res = restart = PyString_AsString(result);
Guido van Rossum02975121992-08-17 08:55:12 +00001046
1047 while ((c = *s++) != '\0') {
Guido van Rossum730806d1998-04-10 22:27:42 +00001048 if (isspace((int)c))
Guido van Rossume20aef51997-08-26 20:39:54 +00001049 continue;
Guido van Rossum02975121992-08-17 08:55:12 +00001050 if ('0' <= c && c <= '9') {
1051 num = c - '0';
1052 while ('0' <= (c = *s++) && c <= '9')
1053 num = num*10 + (c - '0');
1054 if (c == '\0')
1055 break;
1056 }
1057 else
1058 num = 1;
1059
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001060 e = getentry(c, f);
1061 if (e == NULL)
1062 goto fail;
Guido van Rossumb9d338c1997-01-03 15:40:33 +00001063 nres = restart + align((int)(res-restart), c, e);
1064 /* Fill padd bytes with zeros */
1065 while (res < nres)
1066 *res++ = '\0';
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001067 if (num == 0 && c != 's')
1068 continue;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001069 do {
1070 if (c == 'x') {
1071 /* doesn't consume arguments */
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001072 memset(res, '\0', num);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001073 res += num;
Guido van Rossum02975121992-08-17 08:55:12 +00001074 break;
Guido van Rossum02975121992-08-17 08:55:12 +00001075 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001076 if (i >= n) {
1077 PyErr_SetString(StructError,
1078 "insufficient arguments to pack");
1079 goto fail;
1080 }
1081 v = PyTuple_GetItem(args, i++);
1082 if (v == NULL)
1083 goto fail;
1084 if (c == 's') {
1085 /* num is string size, not repeat count */
1086 int n;
1087 if (!PyString_Check(v)) {
1088 PyErr_SetString(StructError,
1089 "argument for 's' must be a string");
1090 goto fail;
1091 }
1092 n = PyString_Size(v);
1093 if (n > num)
1094 n = num;
1095 if (n > 0)
1096 memcpy(res, PyString_AsString(v), n);
1097 if (n < num)
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001098 memset(res+n, '\0', num-n);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001099 res += num;
1100 break;
1101 }
Guido van Rossum9eb671f1997-09-05 07:08:39 +00001102 else if (c == 'p') {
1103 /* num is string size + 1,
1104 to fit in the count byte */
1105 int n;
1106 num--; /* now num is max string size */
1107 if (!PyString_Check(v)) {
1108 PyErr_SetString(StructError,
1109 "argument for 'p' must be a string");
1110 goto fail;
1111 }
1112 n = PyString_Size(v);
1113 if (n > num)
1114 n = num;
1115 if (n > 0)
1116 memcpy(res+1, PyString_AsString(v), n);
1117 if (n < num)
1118 /* no real need, just to be nice */
1119 memset(res+1+n, '\0', num-n);
1120 *res++ = n; /* store the length byte */
1121 res += num;
1122 break;
1123 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001124 else {
1125 if (e->pack(res, v, e) < 0)
1126 goto fail;
1127 res += e->size;
1128 }
1129 } while (--num > 0);
Guido van Rossum02975121992-08-17 08:55:12 +00001130 }
1131
1132 if (i < n) {
Barry Warsaw30695fa1996-12-12 23:32:31 +00001133 PyErr_SetString(StructError,
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001134 "too many arguments for pack format");
Guido van Rossum02975121992-08-17 08:55:12 +00001135 goto fail;
1136 }
1137
1138 return result;
1139
1140 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +00001141 Py_DECREF(result);
Guido van Rossum02975121992-08-17 08:55:12 +00001142 return NULL;
1143}
1144
1145
Guido van Rossum9897f0f1997-12-21 06:46:20 +00001146static char unpack__doc__[] = "\
1147unpack(fmt, string) -> (v1, v2, ...)\n\
1148Unpack the string, containing packed C structure data, according\n\
1149to fmt. Requires len(string)==calcsize(fmt).\n\
Guido van Rossum414fd481997-12-19 04:24:24 +00001150See struct.__doc__ for more on format strings.";
Guido van Rossum02975121992-08-17 08:55:12 +00001151
Barry Warsaw30695fa1996-12-12 23:32:31 +00001152static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +00001153struct_unpack(PyObject *self, PyObject *args)
Guido van Rossum02975121992-08-17 08:55:12 +00001154{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001155 const formatdef *f, *e;
Guido van Rossum02975121992-08-17 08:55:12 +00001156 char *str, *start, *fmt, *s;
1157 char c;
Barry Warsawb9a781e1997-01-03 00:26:28 +00001158 int len, size, num;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001159 PyObject *res, *v;
Guido van Rossum02975121992-08-17 08:55:12 +00001160
Guido van Rossum43713e52000-02-29 13:59:29 +00001161 if (!PyArg_ParseTuple(args, "ss#:unpack", &fmt, &start, &len))
Guido van Rossum02975121992-08-17 08:55:12 +00001162 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001163 f = whichtable(&fmt);
1164 size = calcsize(fmt, f);
1165 if (size < 0)
1166 return NULL;
Guido van Rossum02975121992-08-17 08:55:12 +00001167 if (size != len) {
Barry Warsaw30695fa1996-12-12 23:32:31 +00001168 PyErr_SetString(StructError,
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001169 "unpack str size does not match format");
Guido van Rossum02975121992-08-17 08:55:12 +00001170 return NULL;
1171 }
Barry Warsaw30695fa1996-12-12 23:32:31 +00001172 res = PyList_New(0);
Guido van Rossum02975121992-08-17 08:55:12 +00001173 if (res == NULL)
1174 return NULL;
1175 str = start;
1176 s = fmt;
1177 while ((c = *s++) != '\0') {
Guido van Rossum730806d1998-04-10 22:27:42 +00001178 if (isspace((int)c))
Guido van Rossume20aef51997-08-26 20:39:54 +00001179 continue;
Guido van Rossum02975121992-08-17 08:55:12 +00001180 if ('0' <= c && c <= '9') {
1181 num = c - '0';
1182 while ('0' <= (c = *s++) && c <= '9')
1183 num = num*10 + (c - '0');
1184 if (c == '\0')
1185 break;
1186 }
1187 else
1188 num = 1;
1189
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001190 e = getentry(c, f);
1191 if (e == NULL)
1192 goto fail;
1193 str = start + align((int)(str-start), c, e);
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001194 if (num == 0 && c != 's')
1195 continue;
Guido van Rossum02975121992-08-17 08:55:12 +00001196
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001197 do {
1198 if (c == 'x') {
1199 str += num;
Guido van Rossum02975121992-08-17 08:55:12 +00001200 break;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001201 }
1202 if (c == 's') {
1203 /* num is string size, not repeat count */
1204 v = PyString_FromStringAndSize(str, num);
1205 if (v == NULL)
1206 goto fail;
1207 str += num;
1208 num = 0;
1209 }
Guido van Rossum9eb671f1997-09-05 07:08:39 +00001210 else if (c == 'p') {
1211 /* num is string buffer size,
1212 not repeat count */
1213 int n = *(unsigned char*)str;
1214 /* first byte (unsigned) is string size */
1215 if (n >= num)
1216 n = num-1;
1217 v = PyString_FromStringAndSize(str+1, n);
1218 if (v == NULL)
1219 goto fail;
1220 str += num;
1221 num = 0;
1222 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001223 else {
1224 v = e->unpack(str, e);
1225 if (v == NULL)
1226 goto fail;
1227 str += e->size;
Guido van Rossum02975121992-08-17 08:55:12 +00001228 }
Barry Warsaw30695fa1996-12-12 23:32:31 +00001229 if (v == NULL || PyList_Append(res, v) < 0)
Guido van Rossum02975121992-08-17 08:55:12 +00001230 goto fail;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001231 Py_DECREF(v);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001232 } while (--num > 0);
Guido van Rossum02975121992-08-17 08:55:12 +00001233 }
1234
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001235 v = PyList_AsTuple(res);
1236 Py_DECREF(res);
1237 return v;
Guido van Rossum02975121992-08-17 08:55:12 +00001238
1239 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +00001240 Py_DECREF(res);
Guido van Rossum02975121992-08-17 08:55:12 +00001241 return NULL;
1242}
1243
Guido van Rossum90ddb7b1992-08-19 16:44:15 +00001244
Guido van Rossum02975121992-08-17 08:55:12 +00001245/* List of functions */
1246
Barry Warsaw30695fa1996-12-12 23:32:31 +00001247static PyMethodDef struct_methods[] = {
Guido van Rossum414fd481997-12-19 04:24:24 +00001248 {"calcsize", struct_calcsize, METH_VARARGS, calcsize__doc__},
1249 {"pack", struct_pack, METH_VARARGS, pack__doc__},
1250 {"unpack", struct_unpack, METH_VARARGS, unpack__doc__},
Guido van Rossum02975121992-08-17 08:55:12 +00001251 {NULL, NULL} /* sentinel */
1252};
1253
1254
1255/* Module initialization */
1256
Guido van Rossum3886bb61998-12-04 18:50:17 +00001257DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00001258initstruct(void)
Guido van Rossum02975121992-08-17 08:55:12 +00001259{
Barry Warsaw30695fa1996-12-12 23:32:31 +00001260 PyObject *m, *d;
Guido van Rossum02975121992-08-17 08:55:12 +00001261
1262 /* Create the module and add the functions */
Guido van Rossum414fd481997-12-19 04:24:24 +00001263 m = Py_InitModule4("struct", struct_methods, struct__doc__,
1264 (PyObject*)NULL, PYTHON_API_VERSION);
Guido van Rossum02975121992-08-17 08:55:12 +00001265
1266 /* Add some symbolic constants to the module */
Barry Warsaw30695fa1996-12-12 23:32:31 +00001267 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +00001268 StructError = PyErr_NewException("struct.error", NULL, NULL);
1269 if (StructError == NULL)
1270 return;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001271 PyDict_SetItemString(d, "error", StructError);
Guido van Rossum02975121992-08-17 08:55:12 +00001272}