blob: 23b820bd6f323820d4a64f45fc38e4b50d537e03 [file] [log] [blame]
Guido van Rossum02975121992-08-17 08:55:12 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum02975121992-08-17 08:55:12 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum02975121992-08-17 08:55:12 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum02975121992-08-17 08:55:12 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum02975121992-08-17 08:55:12 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum02975121992-08-17 08:55:12 +000029
30******************************************************************/
31
32/* struct module -- pack values into and (out of) strings */
33
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000034/* New version supporting byte order, alignment and size options,
35 character strings, and unsigned numbers */
36
Barry Warsaw30695fa1996-12-12 23:32:31 +000037#include "Python.h"
Guido van Rossum74679b41997-01-02 22:21:36 +000038#include "mymath.h"
Guido van Rossum02975121992-08-17 08:55:12 +000039
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000040#include <limits.h>
41
42
43/* Exception */
44
Barry Warsaw30695fa1996-12-12 23:32:31 +000045static PyObject *StructError;
Guido van Rossum02975121992-08-17 08:55:12 +000046
47
48/* Define various structs to figure out the alignments of types */
49
Jack Jansen971e1df1995-02-02 14:29:10 +000050#ifdef __MWERKS__
51/*
52** XXXX We have a problem here. There are no unique alignment rules
53** on the PowerPC mac.
54*/
55#ifdef __powerc
56#pragma options align=mac68k
57#endif
58#endif /* __MWERKS__ */
59
Guido van Rossum02975121992-08-17 08:55:12 +000060typedef struct { char c; short x; } s_short;
61typedef struct { char c; int x; } s_int;
62typedef struct { char c; long x; } s_long;
63typedef struct { char c; float x; } s_float;
64typedef struct { char c; double x; } s_double;
65
66#define SHORT_ALIGN (sizeof(s_short) - sizeof(short))
67#define INT_ALIGN (sizeof(s_int) - sizeof(int))
68#define LONG_ALIGN (sizeof(s_long) - sizeof(long))
69#define FLOAT_ALIGN (sizeof(s_float) - sizeof(float))
70#define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))
71
Jack Jansen971e1df1995-02-02 14:29:10 +000072#ifdef __powerc
73#pragma options align=reset
74#endif
75
Guido van Rossum02975121992-08-17 08:55:12 +000076
Guido van Rossum60c50611996-12-31 16:29:52 +000077/* Global that will contain 2**<bits-per-long> */
78
79static PyObject *offset = NULL;
80
81
82/* Helper to create 2**<bits-per-long> */
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +000083/* XXX This assumes 2's complement arithmetic */
84
85static PyObject *
Guido van Rossum60c50611996-12-31 16:29:52 +000086init_offset()
87{
88 PyObject *result = NULL;
89 PyObject *one = PyLong_FromLong(1L);
90 PyObject *shiftcount = PyLong_FromLong(8 * sizeof(long));
91 if (one == NULL || shiftcount == NULL)
92 goto finally;
93 result = PyNumber_Lshift(one, shiftcount);
94 finally:
95 Py_XDECREF(one);
96 Py_XDECREF(shiftcount);
97 return result;
98}
99
100
101/* Helper to add offset to a number */
102
103static PyObject *
104add_offset(v)
105 PyObject *v;
106{
107 PyObject *result = NULL;
108 if (offset == NULL) {
109 if ((offset = init_offset()) == NULL)
110 goto finally;
111 }
112 result = PyNumber_Add(v, offset);
113 finally:
114 return result;
115}
116
117
118/* Same, but subtracting */
119
120static PyObject *
121sub_offset(v)
122 PyObject *v;
123{
124 PyObject *result = NULL;
125 if (offset == NULL) {
126 if ((offset = init_offset()) == NULL)
127 goto finally;
128 }
129 result = PyNumber_Subtract(v, offset);
130 finally:
131 return result;
132}
133
134
135/* Helper routine to turn a (signed) long into an unsigned long */
136
137static PyObject *
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000138make_ulong(x)
139 long x;
140{
141 PyObject *v = PyLong_FromLong(x);
142 if (x < 0 && v != NULL) {
Guido van Rossum60c50611996-12-31 16:29:52 +0000143 PyObject *w = add_offset(v);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000144 Py_DECREF(v);
Guido van Rossum60c50611996-12-31 16:29:52 +0000145 return w;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000146 }
147 else
148 return v;
149}
150
151/* Helper routine to get a Python integer and raise the appropriate error
152 if it isn't one */
153
154static int
155get_long(v, p)
156 PyObject *v;
157 long *p;
158{
159 long x = PyInt_AsLong(v);
160 if (x == -1 && PyErr_Occurred()) {
161 if (PyErr_Occurred() == PyExc_TypeError)
162 PyErr_SetString(StructError,
163 "required argument is not an integer");
164 return -1;
165 }
166 *p = x;
167 return 0;
168}
169
170
Guido van Rossum60c50611996-12-31 16:29:52 +0000171/* Same, but handling unsigned long */
172
173static int
174get_ulong(v, p)
175 PyObject *v;
176 unsigned long *p;
177{
178 long x = PyInt_AsLong(v);
179 PyObject *exc;
180 if (x == -1 && (exc = PyErr_Occurred()) != NULL) {
181 if (exc == PyExc_OverflowError) {
182 /* Try again after subtracting offset */
183 PyObject *w;
184 PyErr_Clear();
185 if ((w = sub_offset(v)) == NULL)
186 return -1;
187 x = PyInt_AsLong(w);
188 Py_DECREF(w);
189 if (x != -1 || (exc = PyErr_Occurred()) == NULL)
190 goto okay;
191 }
192 if (exc == PyExc_TypeError)
193 PyErr_SetString(StructError,
194 "required argument is not an integer");
195 else
196 return -1;
197 }
198 okay:
199 *p = x;
200 return 0;
201}
202
203
Guido van Rossum74679b41997-01-02 22:21:36 +0000204/* Floating point helpers */
205
206/* These use ANSI/IEEE Standard 754-1985 (Standard for Binary Floating
207 Point Arithmetic). See the following URL:
208 http://www.psc.edu/general/software/packages/ieee/ieee.html */
209
210/* XXX Signed zero, infinity, underflow, NaN are not handled quite right? */
211
212static int
213pack_float(x, p, incr)
214 double x; /* The number to pack */
215 char *p; /* Where to pack the high order byte */
216 int incr; /* 1 for big-endian; -1 for little-endian */
217{
218 int s;
219 int e;
220 double fl;
221 long f;
222
223 if (x < 0) {
224 s = 1;
225 x = -x;
226 }
227 else
228 s = 0;
229 fl = frexp(x, &e);
230 /* Normalize fl to be in the range [1.0, 2.0) */
231 if (0.5 <= fl && fl < 1.0) {
232 fl *= 2.0;
233 e--;
234 }
235 else if (fl == 0.0) {
236 e = 0;
237 }
238 else {
239 PyErr_SetString(PyExc_SystemError,
240 "frexp() result out of range");
241 return -1;
242 }
243 e += 127;
244 if (e >= 255) {
245 /* XXX 255 itself is reserved for Inf/NaN */
246 PyErr_SetString(PyExc_OverflowError,
247 "float too large to pack with f format");
248 return -1;
249 }
250 else if (e <= 0) {
251 /* XXX Underflow -- could do better, but who cares? */
252 fl = 0.0;
253 e = 0;
254 }
255 if (fl == 0.0) {
256 f = 0;
257 }
258 else {
259 fl -= 1.0; /* Get rid of leading 1 */
260 fl *= 8388608.0; /* 2**23 */
261 f = (long) floor(fl + 0.5); /* Round */
262 }
263
264 /* First byte */
265 *p = (s<<7) | (e>>1);
266 p += incr;
267
268 /* Second byte */
269 *p = ((e&1)<<7) | (f>>16);
270 p += incr;
271
272 /* Third byte */
273 *p = (f>>8) & 0xFF;
274 p += incr;
275
276 /* Fourth byte */
277 *p = f&0xFF;
278
279 /* Done */
280 return 0;
281}
282
283static int
284pack_double(x, p, incr)
285 double x; /* The number to pack */
286 char *p; /* Where to pack the high order byte */
287 int incr; /* 1 for big-endian; -1 for little-endian */
288{
289 int s;
290 int e;
291 double fl;
292 long fhi, flo;
293
294 if (x < 0) {
295 s = 1;
296 x = -x;
297 }
298 else
299 s = 0;
300 fl = frexp(x, &e);
301 /* Normalize fl to be in the range [1.0, 2.0) */
302 if (0.5 <= fl && fl < 1.0) {
303 fl *= 2.0;
304 e--;
305 }
306 else if (fl == 0.0) {
307 e = 0;
308 }
309 else {
310 PyErr_SetString(PyExc_SystemError,
311 "frexp() result out of range");
312 return -1;
313 }
314 e += 1023;
315 if (e >= 2047) {
316 /* XXX 2047 itself is reserved for Inf/NaN */
317 PyErr_SetString(PyExc_OverflowError,
318 "float too large to pack with d format");
319 return -1;
320 }
321 else if (e <= 0) {
322 /* XXX Underflow -- could do better, but who cares? */
323 fl = 0.0;
324 e = 0;
325 }
326 if (fl == 0.0) {
327 fhi = flo = 0;
328 }
329 else {
330 /* fhi receives the high 28 bits; flo the low 24 bits */
331 fl -= 1.0;
332 fl *= 268435456.0; /* 2**28 */
333 fhi = (long) floor(fl); /* Truncate */
334 fl -= (double)fhi;
335 fl *= 16777216.0; /* 2**24 */
336 flo = (long) floor(fl + 0.5); /* Round */
337 }
338
339 /* First byte */
340 *p = (s<<7) | (e>>4);
341 p += incr;
342
343 /* Second byte */
344 *p = ((e&0xF)<<4) | (fhi>>24);
345 p += incr;
346
347 /* Third byte */
348 *p = (fhi>>16) & 0xFF;
349 p += incr;
350
351 /* Fourth byte */
352 *p = (fhi>>8) & 0xFF;
353 p += incr;
354
355 /* Fifth byte */
356 *p = fhi & 0xFF;
357 p += incr;
358
359 /* Sixth byte */
360 *p = (flo>>16) & 0xFF;
361 p += incr;
362
363 /* Seventh byte */
364 *p = (flo>>8) & 0xFF;
365 p += incr;
366
367 /* Eighth byte */
368 *p = flo & 0xFF;
369 p += incr;
370
371 /* Done */
372 return 0;
373}
374
375static PyObject *
376unpack_float(p, incr)
377 char *p; /* Where the high order byte is */
378 int incr; /* 1 for big-endian; -1 for little-endian */
379{
380 int s;
381 int e;
382 long f;
383 double x;
384
385 /* First byte */
386 s = (*p>>7) & 1;
387 e = (*p & 0x7F) << 1;
388 p += incr;
389
390 /* Second byte */
391 e |= (*p>>7) & 1;
392 f = (*p & 0x7F) << 16;
393 p += incr;
394
395 /* Third byte */
396 f |= (*p & 0xFF) << 8;
397 p += incr;
398
399 /* Fourth byte */
400 f |= *p & 0xFF;
401
402 x = (double)f / 8388608.0;
403
404 /* XXX This sadly ignores Inf/NaN issues */
405 if (e != 0)
406 x = ldexp(1.0 + x, e - 127);
407
408 if (s)
409 x = -x;
410
411 return PyFloat_FromDouble(x);
412}
413
414static PyObject *
415unpack_double(p, incr)
416 char *p; /* Where the high order byte is */
417 int incr; /* 1 for big-endian; -1 for little-endian */
418{
419 int s;
420 int e;
421 long fhi, flo;
422 double x;
423
424 /* First byte */
425 s = (*p>>7) & 1;
426 e = (*p & 0x7F) << 4;
427 p += incr;
428
429 /* Second byte */
430 e |= (*p>>4) & 0xF;
431 fhi = (*p & 0xF) << 24;
432 p += incr;
433
434 /* Third byte */
435 fhi |= (*p & 0xFF) << 16;
436 p += incr;
437
438 /* Fourth byte */
439 fhi |= (*p & 0xFF) << 8;
440 p += incr;
441
442 /* Fifth byte */
443 fhi |= *p & 0xFF;
444 p += incr;
445
446 /* Sixth byte */
447 flo = (*p & 0xFF) << 16;
448 p += incr;
449
450 /* Seventh byte */
451 flo |= (*p & 0xFF) << 8;
452 p += incr;
453
454 /* Eighth byte */
455 flo |= *p & 0xFF;
456 p += incr;
457
458 x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
459 x /= 268435456.0; /* 2**28 */
460
461 /* XXX This sadly ignores Inf/NaN */
462 if (e != 0)
463 x = ldexp(1.0 + x, e - 1023);
464
465 if (s)
466 x = -x;
467
468 return PyFloat_FromDouble(x);
469}
470
471
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000472/* The translation function for each format character is table driven */
473
474typedef struct _formatdef {
475 char format;
476 int size;
477 int alignment;
478 PyObject* (*unpack) Py_PROTO((const char *,
479 const struct _formatdef *));
480 int (*pack) Py_PROTO((char *,
481 PyObject *,
482 const struct _formatdef *));
483} formatdef;
484
485static PyObject *
486nu_char(p, f)
487 const char *p;
488 const formatdef *f;
489{
490 return PyString_FromStringAndSize(p, 1);
491}
492
493static PyObject *
494nu_byte(p, f)
495 const char *p;
496 const formatdef *f;
497{
498 return PyInt_FromLong((long) *(signed char *)p);
499}
500
501static PyObject *
502nu_ubyte(p, f)
503 const char *p;
504 const formatdef *f;
505{
506 return PyInt_FromLong((long) *(unsigned char *)p);
507}
508
509static PyObject *
510nu_short(p, f)
511 const char *p;
512 const formatdef *f;
513{
514 return PyInt_FromLong((long) *(short *)p);
515}
516
517static PyObject *
518nu_ushort(p, f)
519 const char *p;
520 const formatdef *f;
521{
522 return PyInt_FromLong((long) *(unsigned short *)p);
523}
524
525static PyObject *
526nu_int(p, f)
527 const char *p;
528 const formatdef *f;
529{
530 return PyInt_FromLong((long) *(int *)p);
531}
532
533static PyObject *
534nu_uint(p, f)
535 const char *p;
536 const formatdef *f;
537{
538 unsigned int x = *(unsigned int *)p;
539#if INT_MAX == LONG_MAX
540 return make_ulong((long)x);
541#else
542 return PyInt_FromLong((long)x);
543#endif
544}
545
546static PyObject *
547nu_long(p, f)
548 const char *p;
549 const formatdef *f;
550{
551 return PyInt_FromLong(*(long *)p);
552}
553
554static PyObject *
555nu_ulong(p, f)
556 const char *p;
557 const formatdef *f;
558{
559 return make_ulong(*(long *)p);
560}
561
562static PyObject *
563nu_float(p, f)
564 const char *p;
565 const formatdef *f;
566{
567 float x;
568 memcpy((char *)&x, p, sizeof(float));
569 return PyFloat_FromDouble((double)x);
570}
571
572static PyObject *
573nu_double(p, f)
574 const char *p;
575 const formatdef *f;
576{
577 double x;
578 memcpy((char *)&x, p, sizeof(double));
579 return PyFloat_FromDouble(x);
580}
581
582static int
583np_byte(p, v, f)
584 char *p;
585 PyObject *v;
586 const formatdef *f;
587{
588 long x;
589 if (get_long(v, &x) < 0)
590 return -1;
591 *p = x;
592 return 0;
593}
594
595static int
596np_char(p, v, f)
597 char *p;
598 PyObject *v;
599 const formatdef *f;
600{
601 if (!PyString_Check(v) || PyString_Size(v) != 1) {
602 PyErr_SetString(StructError,
603 "char format require string of length 1");
604 return -1;
605 }
606 *p = *PyString_AsString(v);
607 return 0;
608}
609
610static int
611np_short(p, v, f)
612 char *p;
613 PyObject *v;
614 const formatdef *f;
615{
616 long x;
617 if (get_long(v, &x) < 0)
618 return -1;
619 * (short *)p = x;
620 return 0;
621}
622
623static int
624np_int(p, v, f)
625 char *p;
626 PyObject *v;
627 const formatdef *f;
628{
629 long x;
630 if (get_long(v, &x) < 0)
631 return -1;
632 * (int *)p = x;
633 return 0;
634}
635
636static int
Guido van Rossum60c50611996-12-31 16:29:52 +0000637np_uint(p, v, f)
638 char *p;
639 PyObject *v;
640 const formatdef *f;
641{
642 unsigned long x;
643 if (get_ulong(v, &x) < 0)
644 return -1;
645 * (unsigned int *)p = x;
646 return 0;
647}
648
649static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000650np_long(p, v, f)
651 char *p;
652 PyObject *v;
653 const formatdef *f;
654{
655 long x;
656 if (get_long(v, &x) < 0)
657 return -1;
658 * (long *)p = x;
659 return 0;
660}
661
662static int
Guido van Rossum60c50611996-12-31 16:29:52 +0000663np_ulong(p, v, f)
664 char *p;
665 PyObject *v;
666 const formatdef *f;
667{
668 unsigned long x;
669 if (get_ulong(v, &x) < 0)
670 return -1;
671 * (unsigned long *)p = x;
672 return 0;
673}
674
675static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000676np_float(p, v, f)
677 char *p;
678 PyObject *v;
679 const formatdef *f;
680{
681 float x = (float)PyFloat_AsDouble(v);
682 if (x == -1 && PyErr_Occurred()) {
683 PyErr_SetString(StructError,
684 "required argument is not a float");
685 return -1;
686 }
687 memcpy(p, (char *)&x, sizeof(float));
688 return 0;
689}
690
691static int
692np_double(p, v, f)
693 char *p;
694 PyObject *v;
695 const formatdef *f;
696{
697 double x = PyFloat_AsDouble(v);
698 if (x == -1 && PyErr_Occurred()) {
699 PyErr_SetString(StructError,
700 "required argument is not a float");
701 return -1;
702 }
703 memcpy(p, (char *)&x, sizeof(double));
704 return 0;
705}
706
707static formatdef native_table[] = {
708 {'x', sizeof(char), 0, NULL},
709 {'b', sizeof(char), 0, nu_byte, np_byte},
710 {'B', sizeof(char), 0, nu_ubyte, np_byte},
711 {'c', sizeof(char), 0, nu_char, np_char},
712 {'s', sizeof(char), 0, NULL},
713 {'h', sizeof(short), SHORT_ALIGN, nu_short, np_short},
714 {'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_short},
715 {'i', sizeof(int), INT_ALIGN, nu_int, np_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000716 {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000717 {'l', sizeof(long), LONG_ALIGN, nu_long, np_long},
Guido van Rossum60c50611996-12-31 16:29:52 +0000718 {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000719 {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
720 {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
721 {0}
722};
723
724static PyObject *
725bu_int(p, f)
726 const char *p;
727 const formatdef *f;
728{
729 long x = 0;
730 int i = f->size;
731 do {
732 x = (x<<8) | (*p++ & 0xFF);
733 } while (--i > 0);
734 i = 8*(sizeof(long) - f->size);
735 if (i) {
736 x <<= i;
737 x >>= i;
738 }
739 return PyInt_FromLong(x);
740}
741
742static PyObject *
743bu_uint(p, f)
744 const char *p;
745 const formatdef *f;
746{
747 long x = 0;
748 int i = f->size;
749 do {
750 x = (x<<8) | (*p++ & 0xFF);
751 } while (--i > 0);
752 if (f->size == sizeof(long))
753 return make_ulong(x);
754 else
755 return PyLong_FromLong(x);
756}
757
Guido van Rossum74679b41997-01-02 22:21:36 +0000758static PyObject *
759bu_float(p, f)
760 const char *p;
761 const formatdef *f;
762{
763 return unpack_float(p, 1);
764}
765
766static PyObject *
767bu_double(p, f)
768 const char *p;
769 const formatdef *f;
770{
771 return unpack_double(p, 1);
772}
773
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000774static int
775bp_int(p, v, f)
776 char *p;
777 PyObject *v;
778 const formatdef *f;
779{
780 long x;
781 int i;
782 if (get_long(v, &x) < 0)
783 return -1;
784 i = f->size;
785 do {
786 p[--i] = x;
787 x >>= 8;
788 } while (i > 0);
789 return 0;
790}
791
Guido van Rossum60c50611996-12-31 16:29:52 +0000792static int
793bp_uint(p, v, f)
794 char *p;
795 PyObject *v;
796 const formatdef *f;
797{
798 unsigned long x;
799 int i;
800 if (get_ulong(v, &x) < 0)
801 return -1;
802 i = f->size;
803 do {
804 p[--i] = x;
805 x >>= 8;
806 } while (i > 0);
807 return 0;
808}
809
Guido van Rossum74679b41997-01-02 22:21:36 +0000810static int
811bp_float(p, v, f)
812 char *p;
813 PyObject *v;
814 const formatdef *f;
815{
816 double x = PyFloat_AsDouble(v);
817 if (x == -1 && PyErr_Occurred()) {
818 PyErr_SetString(StructError,
819 "required argument is not a float");
820 return -1;
821 }
822 return pack_float(x, p, 1);
823}
824
825static int
826bp_double(p, v, f)
827 char *p;
828 PyObject *v;
829 const formatdef *f;
830{
831 double x = PyFloat_AsDouble(v);
832 if (x == -1 && PyErr_Occurred()) {
833 PyErr_SetString(StructError,
834 "required argument is not a float");
835 return -1;
836 }
837 return pack_double(x, p, 1);
838}
839
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000840static formatdef bigendian_table[] = {
841 {'x', 1, 0, NULL},
842 {'b', 1, 0, bu_int, bp_int},
843 {'B', 1, 0, bu_uint, bp_int},
844 {'c', 1, 0, nu_char, np_char},
845 {'s', 1, 0, NULL},
846 {'h', 2, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000847 {'H', 2, 0, bu_uint, bp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000848 {'i', 4, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000849 {'I', 4, 0, bu_uint, bp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000850 {'l', 4, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000851 {'L', 4, 0, bu_uint, bp_uint},
Guido van Rossum74679b41997-01-02 22:21:36 +0000852 {'f', 4, 0, bu_float, bp_float},
853 {'d', 8, 0, bu_double, bp_double},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000854 {0}
855};
856
857static PyObject *
858lu_int(p, f)
859 const char *p;
860 const formatdef *f;
861{
862 long x = 0;
863 int i = f->size;
864 do {
865 x = (x<<8) | (p[--i] & 0xFF);
866 } while (i > 0);
867 i = 8*(sizeof(long) - f->size);
868 if (i) {
869 x <<= i;
870 x >>= i;
871 }
872 return PyInt_FromLong(x);
873}
874
875static PyObject *
876lu_uint(p, f)
877 const char *p;
878 const formatdef *f;
879{
880 long x = 0;
881 int i = f->size;
882 do {
883 x = (x<<8) | (p[--i] & 0xFF);
884 } while (i > 0);
885 if (f->size == sizeof(long))
886 return make_ulong(x);
887 else
888 return PyLong_FromLong(x);
889}
890
Guido van Rossum74679b41997-01-02 22:21:36 +0000891static PyObject *
892lu_float(p, f)
893 const char *p;
894 const formatdef *f;
895{
896 return unpack_float(p+3, -1);
897}
898
899static PyObject *
900lu_double(p, f)
901 const char *p;
902 const formatdef *f;
903{
904 return unpack_double(p+7, -1);
905}
906
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000907static int
908lp_int(p, v, f)
909 char *p;
910 PyObject *v;
911 const formatdef *f;
912{
913 long x;
914 int i;
915 if (get_long(v, &x) < 0)
916 return -1;
917 i = f->size;
918 do {
919 *p++ = x;
920 x >>= 8;
921 } while (--i > 0);
922 return 0;
923}
924
Guido van Rossum60c50611996-12-31 16:29:52 +0000925static int
926lp_uint(p, v, f)
927 char *p;
928 PyObject *v;
929 const formatdef *f;
930{
931 unsigned long x;
932 int i;
933 if (get_ulong(v, &x) < 0)
934 return -1;
935 i = f->size;
936 do {
937 *p++ = x;
938 x >>= 8;
939 } while (--i > 0);
940 return 0;
941}
942
Guido van Rossum74679b41997-01-02 22:21:36 +0000943static int
944lp_float(p, v, f)
945 char *p;
946 PyObject *v;
947 const formatdef *f;
948{
949 double x = PyFloat_AsDouble(v);
950 if (x == -1 && PyErr_Occurred()) {
951 PyErr_SetString(StructError,
952 "required argument is not a float");
953 return -1;
954 }
955 return pack_float(x, p+3, -1);
956}
957
958static int
959lp_double(p, v, f)
960 char *p;
961 PyObject *v;
962 const formatdef *f;
963{
964 double x = PyFloat_AsDouble(v);
965 if (x == -1 && PyErr_Occurred()) {
966 PyErr_SetString(StructError,
967 "required argument is not a float");
968 return -1;
969 }
970 return pack_double(x, p+7, -1);
971}
972
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000973static formatdef lilendian_table[] = {
974 {'x', 1, 0, NULL},
975 {'b', 1, 0, lu_int, lp_int},
976 {'B', 1, 0, lu_uint, lp_int},
977 {'c', 1, 0, nu_char, np_char},
978 {'s', 1, 0, NULL},
979 {'h', 2, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000980 {'H', 2, 0, lu_uint, lp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000981 {'i', 4, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000982 {'I', 4, 0, lu_uint, lp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000983 {'l', 4, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000984 {'L', 4, 0, lu_uint, lp_uint},
Guido van Rossum74679b41997-01-02 22:21:36 +0000985 {'f', 4, 0, lu_float, lp_float},
986 {'d', 8, 0, lu_double, lp_double},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000987 {0}
988};
989
990
991static const formatdef *
992whichtable(pfmt)
993 const char **pfmt;
994{
995 const char *fmt = (*pfmt)++; /* May be backed out of later */
996 switch (*fmt) {
997 case '<':
998 return lilendian_table;
999 case '>':
1000 case '!': /* Network byte order is big-endian */
1001 return bigendian_table;
1002 case '=': { /* Host byte order -- different from native in aligment! */
1003 int n = 1;
1004 char *p = (char *) &n;
1005 if (*p == 1)
1006 return lilendian_table;
1007 else
1008 return bigendian_table;
1009 }
1010 default:
1011 --*pfmt; /* Back out of pointer increment */
1012 /* Fall through */
1013 case '@':
1014 return native_table;
1015 }
1016}
1017
1018
1019/* Get the table entry for a format code */
1020
1021static const formatdef *
1022getentry(c, f)
1023 int c;
1024 const formatdef *f;
1025{
1026 for (; f->format != '\0'; f++) {
1027 if (f->format == c) {
1028 return f;
1029 }
1030 }
1031 PyErr_SetString(StructError, "bad char in struct format");
1032 return NULL;
1033}
1034
1035
Guido van Rossum02975121992-08-17 08:55:12 +00001036/* Align a size according to a format code */
1037
1038static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001039align(size, c, e)
Guido van Rossum02975121992-08-17 08:55:12 +00001040 int size;
1041 int c;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001042 const formatdef *e;
Guido van Rossum02975121992-08-17 08:55:12 +00001043{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001044 if (e->format == c) {
1045 if (e->alignment) {
1046 size = ((size + e->alignment - 1)
1047 / e->alignment)
1048 * e->alignment;
1049 }
Guido van Rossum02975121992-08-17 08:55:12 +00001050 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001051 return size;
Guido van Rossum02975121992-08-17 08:55:12 +00001052}
1053
1054
1055/* calculate the size of a format string */
1056
1057static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001058calcsize(fmt, f)
1059 const char *fmt;
1060 const formatdef *f;
Guido van Rossum02975121992-08-17 08:55:12 +00001061{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001062 const formatdef *e;
1063 const char *s;
Guido van Rossum02975121992-08-17 08:55:12 +00001064 char c;
1065 int size, num, itemsize, x;
1066
1067 s = fmt;
1068 size = 0;
1069 while ((c = *s++) != '\0') {
1070 if ('0' <= c && c <= '9') {
1071 num = c - '0';
1072 while ('0' <= (c = *s++) && c <= '9') {
1073 x = num*10 + (c - '0');
1074 if (x/10 != num) {
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001075 PyErr_SetString(
1076 StructError,
1077 "overflow in item count");
Guido van Rossum02975121992-08-17 08:55:12 +00001078 return -1;
1079 }
1080 num = x;
1081 }
1082 if (c == '\0')
1083 break;
1084 }
1085 else
1086 num = 1;
1087
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001088 e = getentry(c, f);
1089 if (e == NULL)
Guido van Rossum02975121992-08-17 08:55:12 +00001090 return -1;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001091 itemsize = e->size;
1092 size = align(size, c, e);
Guido van Rossum02975121992-08-17 08:55:12 +00001093 x = num * itemsize;
1094 size += x;
1095 if (x/itemsize != num || size < 0) {
Barry Warsaw30695fa1996-12-12 23:32:31 +00001096 PyErr_SetString(StructError,
1097 "total struct size too long");
Guido van Rossum02975121992-08-17 08:55:12 +00001098 return -1;
1099 }
Guido van Rossum02975121992-08-17 08:55:12 +00001100 }
1101
1102 return size;
1103}
1104
1105
1106/* pack(fmt, v1, v2, ...) --> string */
1107
Barry Warsaw30695fa1996-12-12 23:32:31 +00001108static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +00001109struct_calcsize(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +00001110 PyObject *self; /* Not used */
1111 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +00001112{
1113 char *fmt;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001114 const formatdef *f;
Guido van Rossum02975121992-08-17 08:55:12 +00001115 int size;
1116
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001117 if (!PyArg_ParseTuple(args, "s", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +00001118 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001119 f = whichtable(&fmt);
1120 size = calcsize(fmt, f);
Guido van Rossum02975121992-08-17 08:55:12 +00001121 if (size < 0)
1122 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001123 return PyInt_FromLong((long)size);
Guido van Rossum02975121992-08-17 08:55:12 +00001124}
1125
1126
1127/* pack(fmt, v1, v2, ...) --> string */
1128
Barry Warsaw30695fa1996-12-12 23:32:31 +00001129static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +00001130struct_pack(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +00001131 PyObject *self; /* Not used */
1132 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +00001133{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001134 const formatdef *f, *e;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001135 PyObject *format, *result, *v;
Guido van Rossum02975121992-08-17 08:55:12 +00001136 char *fmt;
1137 int size, num;
1138 int i, n;
1139 char *s, *res, *restart;
1140 char c;
Guido van Rossum02975121992-08-17 08:55:12 +00001141
Barry Warsaw30695fa1996-12-12 23:32:31 +00001142 if (args == NULL || !PyTuple_Check(args) ||
1143 (n = PyTuple_Size(args)) < 1)
1144 {
1145 PyErr_BadArgument();
Guido van Rossum02975121992-08-17 08:55:12 +00001146 return NULL;
1147 }
Barry Warsaw30695fa1996-12-12 23:32:31 +00001148 format = PyTuple_GetItem(args, 0);
1149 if (!PyArg_Parse(format, "s", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +00001150 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001151 f = whichtable(&fmt);
1152 size = calcsize(fmt, f);
Guido van Rossum02975121992-08-17 08:55:12 +00001153 if (size < 0)
1154 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001155 result = PyString_FromStringAndSize((char *)NULL, size);
Guido van Rossum02975121992-08-17 08:55:12 +00001156 if (result == NULL)
1157 return NULL;
1158
1159 s = fmt;
1160 i = 1;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001161 res = restart = PyString_AsString(result);
Guido van Rossum02975121992-08-17 08:55:12 +00001162
1163 while ((c = *s++) != '\0') {
1164 if ('0' <= c && c <= '9') {
1165 num = c - '0';
1166 while ('0' <= (c = *s++) && c <= '9')
1167 num = num*10 + (c - '0');
1168 if (c == '\0')
1169 break;
1170 }
1171 else
1172 num = 1;
1173
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001174 e = getentry(c, f);
1175 if (e == NULL)
1176 goto fail;
1177 res = restart + align((int)(res-restart), c, e);
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001178 if (num == 0 && c != 's')
1179 continue;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001180 do {
1181 if (c == 'x') {
1182 /* doesn't consume arguments */
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001183 memset(res, '\0', num);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001184 res += num;
Guido van Rossum02975121992-08-17 08:55:12 +00001185 break;
Guido van Rossum02975121992-08-17 08:55:12 +00001186 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001187 if (i >= n) {
1188 PyErr_SetString(StructError,
1189 "insufficient arguments to pack");
1190 goto fail;
1191 }
1192 v = PyTuple_GetItem(args, i++);
1193 if (v == NULL)
1194 goto fail;
1195 if (c == 's') {
1196 /* num is string size, not repeat count */
1197 int n;
1198 if (!PyString_Check(v)) {
1199 PyErr_SetString(StructError,
1200 "argument for 's' must be a string");
1201 goto fail;
1202 }
1203 n = PyString_Size(v);
1204 if (n > num)
1205 n = num;
1206 if (n > 0)
1207 memcpy(res, PyString_AsString(v), n);
1208 if (n < num)
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001209 memset(res+n, '\0', num-n);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001210 res += num;
1211 break;
1212 }
1213 else {
1214 if (e->pack(res, v, e) < 0)
1215 goto fail;
1216 res += e->size;
1217 }
1218 } while (--num > 0);
Guido van Rossum02975121992-08-17 08:55:12 +00001219 }
1220
1221 if (i < n) {
Barry Warsaw30695fa1996-12-12 23:32:31 +00001222 PyErr_SetString(StructError,
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001223 "too many arguments for pack format");
Guido van Rossum02975121992-08-17 08:55:12 +00001224 goto fail;
1225 }
1226
1227 return result;
1228
1229 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +00001230 Py_DECREF(result);
Guido van Rossum02975121992-08-17 08:55:12 +00001231 return NULL;
1232}
1233
1234
1235/* unpack(fmt, string) --> (v1, v2, ...) */
1236
Barry Warsaw30695fa1996-12-12 23:32:31 +00001237static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +00001238struct_unpack(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +00001239 PyObject *self; /* Not used */
1240 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +00001241{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001242 const formatdef *f, *e;
Guido van Rossum02975121992-08-17 08:55:12 +00001243 char *str, *start, *fmt, *s;
1244 char c;
1245 int len, size, num, x;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001246 PyObject *res, *v;
Guido van Rossum02975121992-08-17 08:55:12 +00001247
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001248 if (!PyArg_ParseTuple(args, "ss#", &fmt, &start, &len))
Guido van Rossum02975121992-08-17 08:55:12 +00001249 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001250 f = whichtable(&fmt);
1251 size = calcsize(fmt, f);
1252 if (size < 0)
1253 return NULL;
Guido van Rossum02975121992-08-17 08:55:12 +00001254 if (size != len) {
Barry Warsaw30695fa1996-12-12 23:32:31 +00001255 PyErr_SetString(StructError,
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001256 "unpack str size does not match format");
Guido van Rossum02975121992-08-17 08:55:12 +00001257 return NULL;
1258 }
Barry Warsaw30695fa1996-12-12 23:32:31 +00001259 res = PyList_New(0);
Guido van Rossum02975121992-08-17 08:55:12 +00001260 if (res == NULL)
1261 return NULL;
1262 str = start;
1263 s = fmt;
1264 while ((c = *s++) != '\0') {
1265 if ('0' <= c && c <= '9') {
1266 num = c - '0';
1267 while ('0' <= (c = *s++) && c <= '9')
1268 num = num*10 + (c - '0');
1269 if (c == '\0')
1270 break;
1271 }
1272 else
1273 num = 1;
1274
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001275 e = getentry(c, f);
1276 if (e == NULL)
1277 goto fail;
1278 str = start + align((int)(str-start), c, e);
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001279 if (num == 0 && c != 's')
1280 continue;
Guido van Rossum02975121992-08-17 08:55:12 +00001281
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001282 do {
1283 if (c == 'x') {
1284 str += num;
Guido van Rossum02975121992-08-17 08:55:12 +00001285 break;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001286 }
1287 if (c == 's') {
1288 /* num is string size, not repeat count */
1289 v = PyString_FromStringAndSize(str, num);
1290 if (v == NULL)
1291 goto fail;
1292 str += num;
1293 num = 0;
1294 }
1295 else {
1296 v = e->unpack(str, e);
1297 if (v == NULL)
1298 goto fail;
1299 str += e->size;
Guido van Rossum02975121992-08-17 08:55:12 +00001300 }
Barry Warsaw30695fa1996-12-12 23:32:31 +00001301 if (v == NULL || PyList_Append(res, v) < 0)
Guido van Rossum02975121992-08-17 08:55:12 +00001302 goto fail;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001303 Py_DECREF(v);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001304 } while (--num > 0);
Guido van Rossum02975121992-08-17 08:55:12 +00001305 }
1306
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001307 v = PyList_AsTuple(res);
1308 Py_DECREF(res);
1309 return v;
Guido van Rossum02975121992-08-17 08:55:12 +00001310
1311 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +00001312 Py_DECREF(res);
Guido van Rossum02975121992-08-17 08:55:12 +00001313 return NULL;
1314}
1315
Guido van Rossum90ddb7b1992-08-19 16:44:15 +00001316
Guido van Rossum02975121992-08-17 08:55:12 +00001317/* List of functions */
1318
Barry Warsaw30695fa1996-12-12 23:32:31 +00001319static PyMethodDef struct_methods[] = {
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001320 {"calcsize", struct_calcsize, METH_VARARGS},
1321 {"pack", struct_pack, METH_VARARGS},
1322 {"unpack", struct_unpack, METH_VARARGS},
Guido van Rossum02975121992-08-17 08:55:12 +00001323 {NULL, NULL} /* sentinel */
1324};
1325
1326
1327/* Module initialization */
1328
1329void
1330initstruct()
1331{
Barry Warsaw30695fa1996-12-12 23:32:31 +00001332 PyObject *m, *d;
Guido van Rossum02975121992-08-17 08:55:12 +00001333
1334 /* Create the module and add the functions */
Barry Warsaw30695fa1996-12-12 23:32:31 +00001335 m = Py_InitModule("struct", struct_methods);
Guido van Rossum02975121992-08-17 08:55:12 +00001336
1337 /* Add some symbolic constants to the module */
Barry Warsaw30695fa1996-12-12 23:32:31 +00001338 d = PyModule_GetDict(m);
1339 StructError = PyString_FromString("struct.error");
1340 PyDict_SetItemString(d, "error", StructError);
Guido van Rossum02975121992-08-17 08:55:12 +00001341
1342 /* Check for errors */
Barry Warsaw30695fa1996-12-12 23:32:31 +00001343 if (PyErr_Occurred())
1344 Py_FatalError("can't initialize module struct");
Guido van Rossum02975121992-08-17 08:55:12 +00001345}