blob: ef139122d5cd50dc756670ac5ee4f08e5398abb5 [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 */
Guido van Rossum07ef6551997-01-02 22:31:07 +0000405 if (e == 0)
406 e = -126;
407 else {
408 x += 1.0;
409 e -= 127;
410 }
411 x = ldexp(x, e);
Guido van Rossum74679b41997-01-02 22:21:36 +0000412
413 if (s)
414 x = -x;
415
416 return PyFloat_FromDouble(x);
417}
418
419static PyObject *
420unpack_double(p, incr)
421 char *p; /* Where the high order byte is */
422 int incr; /* 1 for big-endian; -1 for little-endian */
423{
424 int s;
425 int e;
426 long fhi, flo;
427 double x;
428
429 /* First byte */
430 s = (*p>>7) & 1;
431 e = (*p & 0x7F) << 4;
432 p += incr;
433
434 /* Second byte */
435 e |= (*p>>4) & 0xF;
436 fhi = (*p & 0xF) << 24;
437 p += incr;
438
439 /* Third byte */
440 fhi |= (*p & 0xFF) << 16;
441 p += incr;
442
443 /* Fourth byte */
444 fhi |= (*p & 0xFF) << 8;
445 p += incr;
446
447 /* Fifth byte */
448 fhi |= *p & 0xFF;
449 p += incr;
450
451 /* Sixth byte */
452 flo = (*p & 0xFF) << 16;
453 p += incr;
454
455 /* Seventh byte */
456 flo |= (*p & 0xFF) << 8;
457 p += incr;
458
459 /* Eighth byte */
460 flo |= *p & 0xFF;
461 p += incr;
462
463 x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
464 x /= 268435456.0; /* 2**28 */
465
466 /* XXX This sadly ignores Inf/NaN */
Guido van Rossum07ef6551997-01-02 22:31:07 +0000467 if (e == 0)
468 e = -1022;
469 else {
470 x += 1.0;
471 e -= 1023;
472 }
473 x = ldexp(x, e);
Guido van Rossum74679b41997-01-02 22:21:36 +0000474
475 if (s)
476 x = -x;
477
478 return PyFloat_FromDouble(x);
479}
480
481
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000482/* The translation function for each format character is table driven */
483
484typedef struct _formatdef {
485 char format;
486 int size;
487 int alignment;
488 PyObject* (*unpack) Py_PROTO((const char *,
489 const struct _formatdef *));
490 int (*pack) Py_PROTO((char *,
491 PyObject *,
492 const struct _formatdef *));
493} formatdef;
494
495static PyObject *
496nu_char(p, f)
497 const char *p;
498 const formatdef *f;
499{
500 return PyString_FromStringAndSize(p, 1);
501}
502
503static PyObject *
504nu_byte(p, f)
505 const char *p;
506 const formatdef *f;
507{
508 return PyInt_FromLong((long) *(signed char *)p);
509}
510
511static PyObject *
512nu_ubyte(p, f)
513 const char *p;
514 const formatdef *f;
515{
516 return PyInt_FromLong((long) *(unsigned char *)p);
517}
518
519static PyObject *
520nu_short(p, f)
521 const char *p;
522 const formatdef *f;
523{
524 return PyInt_FromLong((long) *(short *)p);
525}
526
527static PyObject *
528nu_ushort(p, f)
529 const char *p;
530 const formatdef *f;
531{
532 return PyInt_FromLong((long) *(unsigned short *)p);
533}
534
535static PyObject *
536nu_int(p, f)
537 const char *p;
538 const formatdef *f;
539{
540 return PyInt_FromLong((long) *(int *)p);
541}
542
543static PyObject *
544nu_uint(p, f)
545 const char *p;
546 const formatdef *f;
547{
548 unsigned int x = *(unsigned int *)p;
549#if INT_MAX == LONG_MAX
550 return make_ulong((long)x);
551#else
552 return PyInt_FromLong((long)x);
553#endif
554}
555
556static PyObject *
557nu_long(p, f)
558 const char *p;
559 const formatdef *f;
560{
561 return PyInt_FromLong(*(long *)p);
562}
563
564static PyObject *
565nu_ulong(p, f)
566 const char *p;
567 const formatdef *f;
568{
569 return make_ulong(*(long *)p);
570}
571
572static PyObject *
573nu_float(p, f)
574 const char *p;
575 const formatdef *f;
576{
577 float x;
578 memcpy((char *)&x, p, sizeof(float));
579 return PyFloat_FromDouble((double)x);
580}
581
582static PyObject *
583nu_double(p, f)
584 const char *p;
585 const formatdef *f;
586{
587 double x;
588 memcpy((char *)&x, p, sizeof(double));
589 return PyFloat_FromDouble(x);
590}
591
592static int
593np_byte(p, v, f)
594 char *p;
595 PyObject *v;
596 const formatdef *f;
597{
598 long x;
599 if (get_long(v, &x) < 0)
600 return -1;
601 *p = x;
602 return 0;
603}
604
605static int
606np_char(p, v, f)
607 char *p;
608 PyObject *v;
609 const formatdef *f;
610{
611 if (!PyString_Check(v) || PyString_Size(v) != 1) {
612 PyErr_SetString(StructError,
613 "char format require string of length 1");
614 return -1;
615 }
616 *p = *PyString_AsString(v);
617 return 0;
618}
619
620static int
621np_short(p, v, f)
622 char *p;
623 PyObject *v;
624 const formatdef *f;
625{
626 long x;
627 if (get_long(v, &x) < 0)
628 return -1;
629 * (short *)p = x;
630 return 0;
631}
632
633static int
634np_int(p, v, f)
635 char *p;
636 PyObject *v;
637 const formatdef *f;
638{
639 long x;
640 if (get_long(v, &x) < 0)
641 return -1;
642 * (int *)p = x;
643 return 0;
644}
645
646static int
Guido van Rossum60c50611996-12-31 16:29:52 +0000647np_uint(p, v, f)
648 char *p;
649 PyObject *v;
650 const formatdef *f;
651{
652 unsigned long x;
653 if (get_ulong(v, &x) < 0)
654 return -1;
655 * (unsigned int *)p = x;
656 return 0;
657}
658
659static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000660np_long(p, v, f)
661 char *p;
662 PyObject *v;
663 const formatdef *f;
664{
665 long x;
666 if (get_long(v, &x) < 0)
667 return -1;
668 * (long *)p = x;
669 return 0;
670}
671
672static int
Guido van Rossum60c50611996-12-31 16:29:52 +0000673np_ulong(p, v, f)
674 char *p;
675 PyObject *v;
676 const formatdef *f;
677{
678 unsigned long x;
679 if (get_ulong(v, &x) < 0)
680 return -1;
681 * (unsigned long *)p = x;
682 return 0;
683}
684
685static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000686np_float(p, v, f)
687 char *p;
688 PyObject *v;
689 const formatdef *f;
690{
691 float x = (float)PyFloat_AsDouble(v);
692 if (x == -1 && PyErr_Occurred()) {
693 PyErr_SetString(StructError,
694 "required argument is not a float");
695 return -1;
696 }
697 memcpy(p, (char *)&x, sizeof(float));
698 return 0;
699}
700
701static int
702np_double(p, v, f)
703 char *p;
704 PyObject *v;
705 const formatdef *f;
706{
707 double x = PyFloat_AsDouble(v);
708 if (x == -1 && PyErr_Occurred()) {
709 PyErr_SetString(StructError,
710 "required argument is not a float");
711 return -1;
712 }
713 memcpy(p, (char *)&x, sizeof(double));
714 return 0;
715}
716
717static formatdef native_table[] = {
718 {'x', sizeof(char), 0, NULL},
719 {'b', sizeof(char), 0, nu_byte, np_byte},
720 {'B', sizeof(char), 0, nu_ubyte, np_byte},
721 {'c', sizeof(char), 0, nu_char, np_char},
722 {'s', sizeof(char), 0, NULL},
723 {'h', sizeof(short), SHORT_ALIGN, nu_short, np_short},
724 {'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_short},
725 {'i', sizeof(int), INT_ALIGN, nu_int, np_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000726 {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000727 {'l', sizeof(long), LONG_ALIGN, nu_long, np_long},
Guido van Rossum60c50611996-12-31 16:29:52 +0000728 {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000729 {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
730 {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
731 {0}
732};
733
734static PyObject *
735bu_int(p, f)
736 const char *p;
737 const formatdef *f;
738{
739 long x = 0;
740 int i = f->size;
741 do {
742 x = (x<<8) | (*p++ & 0xFF);
743 } while (--i > 0);
744 i = 8*(sizeof(long) - f->size);
745 if (i) {
746 x <<= i;
747 x >>= i;
748 }
749 return PyInt_FromLong(x);
750}
751
752static PyObject *
753bu_uint(p, f)
754 const char *p;
755 const formatdef *f;
756{
757 long x = 0;
758 int i = f->size;
759 do {
760 x = (x<<8) | (*p++ & 0xFF);
761 } while (--i > 0);
762 if (f->size == sizeof(long))
763 return make_ulong(x);
764 else
765 return PyLong_FromLong(x);
766}
767
Guido van Rossum74679b41997-01-02 22:21:36 +0000768static PyObject *
769bu_float(p, f)
770 const char *p;
771 const formatdef *f;
772{
773 return unpack_float(p, 1);
774}
775
776static PyObject *
777bu_double(p, f)
778 const char *p;
779 const formatdef *f;
780{
781 return unpack_double(p, 1);
782}
783
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000784static int
785bp_int(p, v, f)
786 char *p;
787 PyObject *v;
788 const formatdef *f;
789{
790 long x;
791 int i;
792 if (get_long(v, &x) < 0)
793 return -1;
794 i = f->size;
795 do {
796 p[--i] = x;
797 x >>= 8;
798 } while (i > 0);
799 return 0;
800}
801
Guido van Rossum60c50611996-12-31 16:29:52 +0000802static int
803bp_uint(p, v, f)
804 char *p;
805 PyObject *v;
806 const formatdef *f;
807{
808 unsigned long x;
809 int i;
810 if (get_ulong(v, &x) < 0)
811 return -1;
812 i = f->size;
813 do {
814 p[--i] = x;
815 x >>= 8;
816 } while (i > 0);
817 return 0;
818}
819
Guido van Rossum74679b41997-01-02 22:21:36 +0000820static int
821bp_float(p, v, f)
822 char *p;
823 PyObject *v;
824 const formatdef *f;
825{
826 double x = PyFloat_AsDouble(v);
827 if (x == -1 && PyErr_Occurred()) {
828 PyErr_SetString(StructError,
829 "required argument is not a float");
830 return -1;
831 }
832 return pack_float(x, p, 1);
833}
834
835static int
836bp_double(p, v, f)
837 char *p;
838 PyObject *v;
839 const formatdef *f;
840{
841 double x = PyFloat_AsDouble(v);
842 if (x == -1 && PyErr_Occurred()) {
843 PyErr_SetString(StructError,
844 "required argument is not a float");
845 return -1;
846 }
847 return pack_double(x, p, 1);
848}
849
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000850static formatdef bigendian_table[] = {
851 {'x', 1, 0, NULL},
852 {'b', 1, 0, bu_int, bp_int},
853 {'B', 1, 0, bu_uint, bp_int},
854 {'c', 1, 0, nu_char, np_char},
855 {'s', 1, 0, NULL},
856 {'h', 2, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000857 {'H', 2, 0, bu_uint, bp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000858 {'i', 4, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000859 {'I', 4, 0, bu_uint, bp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000860 {'l', 4, 0, bu_int, bp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000861 {'L', 4, 0, bu_uint, bp_uint},
Guido van Rossum74679b41997-01-02 22:21:36 +0000862 {'f', 4, 0, bu_float, bp_float},
863 {'d', 8, 0, bu_double, bp_double},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000864 {0}
865};
866
867static PyObject *
868lu_int(p, f)
869 const char *p;
870 const formatdef *f;
871{
872 long x = 0;
873 int i = f->size;
874 do {
875 x = (x<<8) | (p[--i] & 0xFF);
876 } while (i > 0);
877 i = 8*(sizeof(long) - f->size);
878 if (i) {
879 x <<= i;
880 x >>= i;
881 }
882 return PyInt_FromLong(x);
883}
884
885static PyObject *
886lu_uint(p, f)
887 const char *p;
888 const formatdef *f;
889{
890 long x = 0;
891 int i = f->size;
892 do {
893 x = (x<<8) | (p[--i] & 0xFF);
894 } while (i > 0);
895 if (f->size == sizeof(long))
896 return make_ulong(x);
897 else
898 return PyLong_FromLong(x);
899}
900
Guido van Rossum74679b41997-01-02 22:21:36 +0000901static PyObject *
902lu_float(p, f)
903 const char *p;
904 const formatdef *f;
905{
906 return unpack_float(p+3, -1);
907}
908
909static PyObject *
910lu_double(p, f)
911 const char *p;
912 const formatdef *f;
913{
914 return unpack_double(p+7, -1);
915}
916
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000917static int
918lp_int(p, v, f)
919 char *p;
920 PyObject *v;
921 const formatdef *f;
922{
923 long x;
924 int i;
925 if (get_long(v, &x) < 0)
926 return -1;
927 i = f->size;
928 do {
929 *p++ = x;
930 x >>= 8;
931 } while (--i > 0);
932 return 0;
933}
934
Guido van Rossum60c50611996-12-31 16:29:52 +0000935static int
936lp_uint(p, v, f)
937 char *p;
938 PyObject *v;
939 const formatdef *f;
940{
941 unsigned long x;
942 int i;
943 if (get_ulong(v, &x) < 0)
944 return -1;
945 i = f->size;
946 do {
947 *p++ = x;
948 x >>= 8;
949 } while (--i > 0);
950 return 0;
951}
952
Guido van Rossum74679b41997-01-02 22:21:36 +0000953static int
954lp_float(p, v, f)
955 char *p;
956 PyObject *v;
957 const formatdef *f;
958{
959 double x = PyFloat_AsDouble(v);
960 if (x == -1 && PyErr_Occurred()) {
961 PyErr_SetString(StructError,
962 "required argument is not a float");
963 return -1;
964 }
965 return pack_float(x, p+3, -1);
966}
967
968static int
969lp_double(p, v, f)
970 char *p;
971 PyObject *v;
972 const formatdef *f;
973{
974 double x = PyFloat_AsDouble(v);
975 if (x == -1 && PyErr_Occurred()) {
976 PyErr_SetString(StructError,
977 "required argument is not a float");
978 return -1;
979 }
980 return pack_double(x, p+7, -1);
981}
982
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000983static formatdef lilendian_table[] = {
984 {'x', 1, 0, NULL},
985 {'b', 1, 0, lu_int, lp_int},
986 {'B', 1, 0, lu_uint, lp_int},
987 {'c', 1, 0, nu_char, np_char},
988 {'s', 1, 0, NULL},
989 {'h', 2, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000990 {'H', 2, 0, lu_uint, lp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000991 {'i', 4, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000992 {'I', 4, 0, lu_uint, lp_uint},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000993 {'l', 4, 0, lu_int, lp_int},
Guido van Rossum60c50611996-12-31 16:29:52 +0000994 {'L', 4, 0, lu_uint, lp_uint},
Guido van Rossum74679b41997-01-02 22:21:36 +0000995 {'f', 4, 0, lu_float, lp_float},
996 {'d', 8, 0, lu_double, lp_double},
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +0000997 {0}
998};
999
1000
1001static const formatdef *
1002whichtable(pfmt)
1003 const char **pfmt;
1004{
1005 const char *fmt = (*pfmt)++; /* May be backed out of later */
1006 switch (*fmt) {
1007 case '<':
1008 return lilendian_table;
1009 case '>':
1010 case '!': /* Network byte order is big-endian */
1011 return bigendian_table;
1012 case '=': { /* Host byte order -- different from native in aligment! */
1013 int n = 1;
1014 char *p = (char *) &n;
1015 if (*p == 1)
1016 return lilendian_table;
1017 else
1018 return bigendian_table;
1019 }
1020 default:
1021 --*pfmt; /* Back out of pointer increment */
1022 /* Fall through */
1023 case '@':
1024 return native_table;
1025 }
1026}
1027
1028
1029/* Get the table entry for a format code */
1030
1031static const formatdef *
1032getentry(c, f)
1033 int c;
1034 const formatdef *f;
1035{
1036 for (; f->format != '\0'; f++) {
1037 if (f->format == c) {
1038 return f;
1039 }
1040 }
1041 PyErr_SetString(StructError, "bad char in struct format");
1042 return NULL;
1043}
1044
1045
Guido van Rossum02975121992-08-17 08:55:12 +00001046/* Align a size according to a format code */
1047
1048static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001049align(size, c, e)
Guido van Rossum02975121992-08-17 08:55:12 +00001050 int size;
1051 int c;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001052 const formatdef *e;
Guido van Rossum02975121992-08-17 08:55:12 +00001053{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001054 if (e->format == c) {
1055 if (e->alignment) {
1056 size = ((size + e->alignment - 1)
1057 / e->alignment)
1058 * e->alignment;
1059 }
Guido van Rossum02975121992-08-17 08:55:12 +00001060 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001061 return size;
Guido van Rossum02975121992-08-17 08:55:12 +00001062}
1063
1064
1065/* calculate the size of a format string */
1066
1067static int
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001068calcsize(fmt, f)
1069 const char *fmt;
1070 const formatdef *f;
Guido van Rossum02975121992-08-17 08:55:12 +00001071{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001072 const formatdef *e;
1073 const char *s;
Guido van Rossum02975121992-08-17 08:55:12 +00001074 char c;
1075 int size, num, itemsize, x;
1076
1077 s = fmt;
1078 size = 0;
1079 while ((c = *s++) != '\0') {
1080 if ('0' <= c && c <= '9') {
1081 num = c - '0';
1082 while ('0' <= (c = *s++) && c <= '9') {
1083 x = num*10 + (c - '0');
1084 if (x/10 != num) {
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001085 PyErr_SetString(
1086 StructError,
1087 "overflow in item count");
Guido van Rossum02975121992-08-17 08:55:12 +00001088 return -1;
1089 }
1090 num = x;
1091 }
1092 if (c == '\0')
1093 break;
1094 }
1095 else
1096 num = 1;
1097
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001098 e = getentry(c, f);
1099 if (e == NULL)
Guido van Rossum02975121992-08-17 08:55:12 +00001100 return -1;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001101 itemsize = e->size;
1102 size = align(size, c, e);
Guido van Rossum02975121992-08-17 08:55:12 +00001103 x = num * itemsize;
1104 size += x;
1105 if (x/itemsize != num || size < 0) {
Barry Warsaw30695fa1996-12-12 23:32:31 +00001106 PyErr_SetString(StructError,
1107 "total struct size too long");
Guido van Rossum02975121992-08-17 08:55:12 +00001108 return -1;
1109 }
Guido van Rossum02975121992-08-17 08:55:12 +00001110 }
1111
1112 return size;
1113}
1114
1115
1116/* pack(fmt, v1, v2, ...) --> string */
1117
Barry Warsaw30695fa1996-12-12 23:32:31 +00001118static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +00001119struct_calcsize(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +00001120 PyObject *self; /* Not used */
1121 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +00001122{
1123 char *fmt;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001124 const formatdef *f;
Guido van Rossum02975121992-08-17 08:55:12 +00001125 int size;
1126
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001127 if (!PyArg_ParseTuple(args, "s", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +00001128 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001129 f = whichtable(&fmt);
1130 size = calcsize(fmt, f);
Guido van Rossum02975121992-08-17 08:55:12 +00001131 if (size < 0)
1132 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001133 return PyInt_FromLong((long)size);
Guido van Rossum02975121992-08-17 08:55:12 +00001134}
1135
1136
1137/* pack(fmt, v1, v2, ...) --> string */
1138
Barry Warsaw30695fa1996-12-12 23:32:31 +00001139static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +00001140struct_pack(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +00001141 PyObject *self; /* Not used */
1142 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +00001143{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001144 const formatdef *f, *e;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001145 PyObject *format, *result, *v;
Guido van Rossum02975121992-08-17 08:55:12 +00001146 char *fmt;
1147 int size, num;
1148 int i, n;
1149 char *s, *res, *restart;
1150 char c;
Guido van Rossum02975121992-08-17 08:55:12 +00001151
Barry Warsaw30695fa1996-12-12 23:32:31 +00001152 if (args == NULL || !PyTuple_Check(args) ||
1153 (n = PyTuple_Size(args)) < 1)
1154 {
1155 PyErr_BadArgument();
Guido van Rossum02975121992-08-17 08:55:12 +00001156 return NULL;
1157 }
Barry Warsaw30695fa1996-12-12 23:32:31 +00001158 format = PyTuple_GetItem(args, 0);
1159 if (!PyArg_Parse(format, "s", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +00001160 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001161 f = whichtable(&fmt);
1162 size = calcsize(fmt, f);
Guido van Rossum02975121992-08-17 08:55:12 +00001163 if (size < 0)
1164 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001165 result = PyString_FromStringAndSize((char *)NULL, size);
Guido van Rossum02975121992-08-17 08:55:12 +00001166 if (result == NULL)
1167 return NULL;
1168
1169 s = fmt;
1170 i = 1;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001171 res = restart = PyString_AsString(result);
Guido van Rossum02975121992-08-17 08:55:12 +00001172
1173 while ((c = *s++) != '\0') {
1174 if ('0' <= c && c <= '9') {
1175 num = c - '0';
1176 while ('0' <= (c = *s++) && c <= '9')
1177 num = num*10 + (c - '0');
1178 if (c == '\0')
1179 break;
1180 }
1181 else
1182 num = 1;
1183
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001184 e = getentry(c, f);
1185 if (e == NULL)
1186 goto fail;
1187 res = restart + align((int)(res-restart), c, e);
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001188 if (num == 0 && c != 's')
1189 continue;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001190 do {
1191 if (c == 'x') {
1192 /* doesn't consume arguments */
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001193 memset(res, '\0', num);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001194 res += num;
Guido van Rossum02975121992-08-17 08:55:12 +00001195 break;
Guido van Rossum02975121992-08-17 08:55:12 +00001196 }
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001197 if (i >= n) {
1198 PyErr_SetString(StructError,
1199 "insufficient arguments to pack");
1200 goto fail;
1201 }
1202 v = PyTuple_GetItem(args, i++);
1203 if (v == NULL)
1204 goto fail;
1205 if (c == 's') {
1206 /* num is string size, not repeat count */
1207 int n;
1208 if (!PyString_Check(v)) {
1209 PyErr_SetString(StructError,
1210 "argument for 's' must be a string");
1211 goto fail;
1212 }
1213 n = PyString_Size(v);
1214 if (n > num)
1215 n = num;
1216 if (n > 0)
1217 memcpy(res, PyString_AsString(v), n);
1218 if (n < num)
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001219 memset(res+n, '\0', num-n);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001220 res += num;
1221 break;
1222 }
1223 else {
1224 if (e->pack(res, v, e) < 0)
1225 goto fail;
1226 res += e->size;
1227 }
1228 } while (--num > 0);
Guido van Rossum02975121992-08-17 08:55:12 +00001229 }
1230
1231 if (i < n) {
Barry Warsaw30695fa1996-12-12 23:32:31 +00001232 PyErr_SetString(StructError,
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001233 "too many arguments for pack format");
Guido van Rossum02975121992-08-17 08:55:12 +00001234 goto fail;
1235 }
1236
1237 return result;
1238
1239 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +00001240 Py_DECREF(result);
Guido van Rossum02975121992-08-17 08:55:12 +00001241 return NULL;
1242}
1243
1244
1245/* unpack(fmt, string) --> (v1, v2, ...) */
1246
Barry Warsaw30695fa1996-12-12 23:32:31 +00001247static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +00001248struct_unpack(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +00001249 PyObject *self; /* Not used */
1250 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +00001251{
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001252 const formatdef *f, *e;
Guido van Rossum02975121992-08-17 08:55:12 +00001253 char *str, *start, *fmt, *s;
1254 char c;
1255 int len, size, num, x;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001256 PyObject *res, *v;
Guido van Rossum02975121992-08-17 08:55:12 +00001257
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001258 if (!PyArg_ParseTuple(args, "ss#", &fmt, &start, &len))
Guido van Rossum02975121992-08-17 08:55:12 +00001259 return NULL;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001260 f = whichtable(&fmt);
1261 size = calcsize(fmt, f);
1262 if (size < 0)
1263 return NULL;
Guido van Rossum02975121992-08-17 08:55:12 +00001264 if (size != len) {
Barry Warsaw30695fa1996-12-12 23:32:31 +00001265 PyErr_SetString(StructError,
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001266 "unpack str size does not match format");
Guido van Rossum02975121992-08-17 08:55:12 +00001267 return NULL;
1268 }
Barry Warsaw30695fa1996-12-12 23:32:31 +00001269 res = PyList_New(0);
Guido van Rossum02975121992-08-17 08:55:12 +00001270 if (res == NULL)
1271 return NULL;
1272 str = start;
1273 s = fmt;
1274 while ((c = *s++) != '\0') {
1275 if ('0' <= c && c <= '9') {
1276 num = c - '0';
1277 while ('0' <= (c = *s++) && c <= '9')
1278 num = num*10 + (c - '0');
1279 if (c == '\0')
1280 break;
1281 }
1282 else
1283 num = 1;
1284
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001285 e = getentry(c, f);
1286 if (e == NULL)
1287 goto fail;
1288 str = start + align((int)(str-start), c, e);
Guido van Rossum3aa27fd1996-12-31 02:10:45 +00001289 if (num == 0 && c != 's')
1290 continue;
Guido van Rossum02975121992-08-17 08:55:12 +00001291
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001292 do {
1293 if (c == 'x') {
1294 str += num;
Guido van Rossum02975121992-08-17 08:55:12 +00001295 break;
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001296 }
1297 if (c == 's') {
1298 /* num is string size, not repeat count */
1299 v = PyString_FromStringAndSize(str, num);
1300 if (v == NULL)
1301 goto fail;
1302 str += num;
1303 num = 0;
1304 }
1305 else {
1306 v = e->unpack(str, e);
1307 if (v == NULL)
1308 goto fail;
1309 str += e->size;
Guido van Rossum02975121992-08-17 08:55:12 +00001310 }
Barry Warsaw30695fa1996-12-12 23:32:31 +00001311 if (v == NULL || PyList_Append(res, v) < 0)
Guido van Rossum02975121992-08-17 08:55:12 +00001312 goto fail;
Barry Warsaw30695fa1996-12-12 23:32:31 +00001313 Py_DECREF(v);
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001314 } while (--num > 0);
Guido van Rossum02975121992-08-17 08:55:12 +00001315 }
1316
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001317 v = PyList_AsTuple(res);
1318 Py_DECREF(res);
1319 return v;
Guido van Rossum02975121992-08-17 08:55:12 +00001320
1321 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +00001322 Py_DECREF(res);
Guido van Rossum02975121992-08-17 08:55:12 +00001323 return NULL;
1324}
1325
Guido van Rossum90ddb7b1992-08-19 16:44:15 +00001326
Guido van Rossum02975121992-08-17 08:55:12 +00001327/* List of functions */
1328
Barry Warsaw30695fa1996-12-12 23:32:31 +00001329static PyMethodDef struct_methods[] = {
Guido van Rossumf7e6b4b1996-12-31 01:41:25 +00001330 {"calcsize", struct_calcsize, METH_VARARGS},
1331 {"pack", struct_pack, METH_VARARGS},
1332 {"unpack", struct_unpack, METH_VARARGS},
Guido van Rossum02975121992-08-17 08:55:12 +00001333 {NULL, NULL} /* sentinel */
1334};
1335
1336
1337/* Module initialization */
1338
1339void
1340initstruct()
1341{
Barry Warsaw30695fa1996-12-12 23:32:31 +00001342 PyObject *m, *d;
Guido van Rossum02975121992-08-17 08:55:12 +00001343
1344 /* Create the module and add the functions */
Barry Warsaw30695fa1996-12-12 23:32:31 +00001345 m = Py_InitModule("struct", struct_methods);
Guido van Rossum02975121992-08-17 08:55:12 +00001346
1347 /* Add some symbolic constants to the module */
Barry Warsaw30695fa1996-12-12 23:32:31 +00001348 d = PyModule_GetDict(m);
1349 StructError = PyString_FromString("struct.error");
1350 PyDict_SetItemString(d, "error", StructError);
Guido van Rossum02975121992-08-17 08:55:12 +00001351
1352 /* Check for errors */
Barry Warsaw30695fa1996-12-12 23:32:31 +00001353 if (PyErr_Occurred())
1354 Py_FatalError("can't initialize module struct");
Guido van Rossum02975121992-08-17 08:55:12 +00001355}