blob: 1ae2320a5ef7043c39fe1783497cdb38de4bd150 [file] [log] [blame]
Bob Ippolito232f3c92006-05-23 19:12:41 +00001/* struct module -- pack values into and (out of) strings */
2
3/* New version supporting byte order, alignment and size options,
4 character strings, and unsigned numbers */
5
6#include "Python.h"
7#include "structseq.h"
8#include "structmember.h"
9#include <ctype.h>
10
Bob Ippolitod3611eb2006-05-23 19:31:23 +000011static PyTypeObject PyStructType;
Bob Ippolito232f3c92006-05-23 19:12:41 +000012
13/* compatibility macros */
14#if (PY_VERSION_HEX < 0x02050000)
15typedef int Py_ssize_t;
16#endif
17
Martin Blais2856e5f2006-05-26 12:03:27 +000018
Bob Ippolito94f68ee2006-05-25 18:44:50 +000019/* PY_USE_INT_WHEN_POSSIBLE is an experimental flag that changes the
20 struct API to return int instead of long when possible. This is
21 often a significant performance improvement. */
22/*
23#define PY_USE_INT_WHEN_POSSIBLE 1
24*/
Bob Ippolito232f3c92006-05-23 19:12:41 +000025
26
27/* The translation function for each format character is table driven */
Bob Ippolito232f3c92006-05-23 19:12:41 +000028typedef struct _formatdef {
29 char format;
30 int size;
31 int alignment;
32 PyObject* (*unpack)(const char *,
33 const struct _formatdef *);
34 int (*pack)(char *, PyObject *,
35 const struct _formatdef *);
36} formatdef;
37
38typedef struct _formatcode {
39 const struct _formatdef *fmtdef;
40 int offset;
Bob Ippolitoeb621272006-05-24 15:32:06 +000041 int size;
Bob Ippolito232f3c92006-05-23 19:12:41 +000042} formatcode;
43
44/* Struct object interface */
45
46typedef struct {
47 PyObject_HEAD
48 int s_size;
49 int s_len;
50 formatcode *s_codes;
51 PyObject *s_format;
52 PyObject *weakreflist; /* List of weak references */
53} PyStructObject;
54
Bob Ippolitoeb621272006-05-24 15:32:06 +000055
Bob Ippolito07c023b2006-05-23 19:32:25 +000056#define PyStruct_Check(op) PyObject_TypeCheck(op, &PyStructType)
57#define PyStruct_CheckExact(op) ((op)->ob_type == &PyStructType)
Bob Ippolito232f3c92006-05-23 19:12:41 +000058
59
60/* Exception */
61
62static PyObject *StructError;
63
64
65/* Define various structs to figure out the alignments of types */
66
67
68typedef struct { char c; short x; } st_short;
69typedef struct { char c; int x; } st_int;
70typedef struct { char c; long x; } st_long;
71typedef struct { char c; float x; } st_float;
72typedef struct { char c; double x; } st_double;
73typedef struct { char c; void *x; } st_void_p;
74
75#define SHORT_ALIGN (sizeof(st_short) - sizeof(short))
76#define INT_ALIGN (sizeof(st_int) - sizeof(int))
77#define LONG_ALIGN (sizeof(st_long) - sizeof(long))
78#define FLOAT_ALIGN (sizeof(st_float) - sizeof(float))
79#define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double))
80#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
81
82/* We can't support q and Q in native mode unless the compiler does;
83 in std mode, they're 8 bytes on all platforms. */
84#ifdef HAVE_LONG_LONG
85typedef struct { char c; PY_LONG_LONG x; } s_long_long;
86#define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(PY_LONG_LONG))
87#endif
88
89#define STRINGIFY(x) #x
90
91#ifdef __powerc
92#pragma options align=reset
93#endif
94
95/* Helper to get a PyLongObject by hook or by crook. Caller should decref. */
96
97static PyObject *
98get_pylong(PyObject *v)
99{
100 PyNumberMethods *m;
101
102 assert(v != NULL);
103 if (PyInt_Check(v))
104 return PyLong_FromLong(PyInt_AS_LONG(v));
105 if (PyLong_Check(v)) {
106 Py_INCREF(v);
107 return v;
108 }
109 m = v->ob_type->tp_as_number;
110 if (m != NULL && m->nb_long != NULL) {
111 v = m->nb_long(v);
112 if (v == NULL)
113 return NULL;
114 if (PyLong_Check(v))
115 return v;
116 Py_DECREF(v);
117 }
118 PyErr_SetString(StructError,
119 "cannot convert argument to long");
120 return NULL;
121}
122
123/* Helper routine to get a Python integer and raise the appropriate error
124 if it isn't one */
125
126static int
127get_long(PyObject *v, long *p)
128{
129 long x = PyInt_AsLong(v);
130 if (x == -1 && PyErr_Occurred()) {
131 if (PyErr_ExceptionMatches(PyExc_TypeError))
132 PyErr_SetString(StructError,
133 "required argument is not an integer");
134 return -1;
135 }
136 *p = x;
137 return 0;
138}
139
140
141/* Same, but handling unsigned long */
142
143static int
144get_ulong(PyObject *v, unsigned long *p)
145{
146 if (PyLong_Check(v)) {
147 unsigned long x = PyLong_AsUnsignedLong(v);
148 if (x == (unsigned long)(-1) && PyErr_Occurred())
149 return -1;
150 *p = x;
151 return 0;
152 }
153 else {
154 return get_long(v, (long *)p);
155 }
156}
157
158#ifdef HAVE_LONG_LONG
159
160/* Same, but handling native long long. */
161
162static int
163get_longlong(PyObject *v, PY_LONG_LONG *p)
164{
165 PY_LONG_LONG x;
166
167 v = get_pylong(v);
168 if (v == NULL)
169 return -1;
170 assert(PyLong_Check(v));
171 x = PyLong_AsLongLong(v);
172 Py_DECREF(v);
173 if (x == (PY_LONG_LONG)-1 && PyErr_Occurred())
174 return -1;
175 *p = x;
176 return 0;
177}
178
179/* Same, but handling native unsigned long long. */
180
181static int
182get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
183{
184 unsigned PY_LONG_LONG x;
185
186 v = get_pylong(v);
187 if (v == NULL)
188 return -1;
189 assert(PyLong_Check(v));
190 x = PyLong_AsUnsignedLongLong(v);
191 Py_DECREF(v);
192 if (x == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
193 return -1;
194 *p = x;
195 return 0;
196}
197
198#endif
199
200/* Floating point helpers */
201
202static PyObject *
203unpack_float(const char *p, /* start of 4-byte string */
204 int le) /* true for little-endian, false for big-endian */
205{
206 double x;
207
208 x = _PyFloat_Unpack4((unsigned char *)p, le);
209 if (x == -1.0 && PyErr_Occurred())
210 return NULL;
211 return PyFloat_FromDouble(x);
212}
213
214static PyObject *
215unpack_double(const char *p, /* start of 8-byte string */
216 int le) /* true for little-endian, false for big-endian */
217{
218 double x;
219
220 x = _PyFloat_Unpack8((unsigned char *)p, le);
221 if (x == -1.0 && PyErr_Occurred())
222 return NULL;
223 return PyFloat_FromDouble(x);
224}
225
226
227/* A large number of small routines follow, with names of the form
228
229 [bln][up]_TYPE
230
231 [bln] distiguishes among big-endian, little-endian and native.
232 [pu] distiguishes between pack (to struct) and unpack (from struct).
233 TYPE is one of char, byte, ubyte, etc.
234*/
235
236/* Native mode routines. ****************************************************/
237/* NOTE:
238 In all n[up]_<type> routines handling types larger than 1 byte, there is
239 *no* guarantee that the p pointer is properly aligned for each type,
240 therefore memcpy is called. An intermediate variable is used to
241 compensate for big-endian architectures.
242 Normally both the intermediate variable and the memcpy call will be
243 skipped by C optimisation in little-endian architectures (gcc >= 2.91
244 does this). */
245
246static PyObject *
247nu_char(const char *p, const formatdef *f)
248{
249 return PyString_FromStringAndSize(p, 1);
250}
251
252static PyObject *
253nu_byte(const char *p, const formatdef *f)
254{
255 return PyInt_FromLong((long) *(signed char *)p);
256}
257
258static PyObject *
259nu_ubyte(const char *p, const formatdef *f)
260{
261 return PyInt_FromLong((long) *(unsigned char *)p);
262}
263
264static PyObject *
265nu_short(const char *p, const formatdef *f)
266{
267 short x;
268 memcpy((char *)&x, p, sizeof x);
269 return PyInt_FromLong((long)x);
270}
271
272static PyObject *
273nu_ushort(const char *p, const formatdef *f)
274{
275 unsigned short x;
276 memcpy((char *)&x, p, sizeof x);
277 return PyInt_FromLong((long)x);
278}
279
280static PyObject *
281nu_int(const char *p, const formatdef *f)
282{
283 int x;
284 memcpy((char *)&x, p, sizeof x);
285 return PyInt_FromLong((long)x);
286}
287
288static PyObject *
289nu_uint(const char *p, const formatdef *f)
290{
291 unsigned int x;
292 memcpy((char *)&x, p, sizeof x);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000293#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000294 if (x <= LONG_MAX)
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000295 return PyInt_FromLong((long)x);
296#endif
Bob Ippolito232f3c92006-05-23 19:12:41 +0000297 return PyLong_FromUnsignedLong((unsigned long)x);
298}
299
300static PyObject *
301nu_long(const char *p, const formatdef *f)
302{
303 long x;
304 memcpy((char *)&x, p, sizeof x);
305 return PyInt_FromLong(x);
306}
307
308static PyObject *
309nu_ulong(const char *p, const formatdef *f)
310{
311 unsigned long x;
312 memcpy((char *)&x, p, sizeof x);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000313#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000314 if (x <= LONG_MAX)
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000315 return PyInt_FromLong((long)x);
316#endif
Bob Ippolito232f3c92006-05-23 19:12:41 +0000317 return PyLong_FromUnsignedLong(x);
318}
319
320/* Native mode doesn't support q or Q unless the platform C supports
321 long long (or, on Windows, __int64). */
322
323#ifdef HAVE_LONG_LONG
324
325static PyObject *
326nu_longlong(const char *p, const formatdef *f)
327{
328 PY_LONG_LONG x;
329 memcpy((char *)&x, p, sizeof x);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000330#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000331 if (x >= LONG_MIN && x <= LONG_MAX)
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000332 return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
333#endif
Bob Ippolito232f3c92006-05-23 19:12:41 +0000334 return PyLong_FromLongLong(x);
335}
336
337static PyObject *
338nu_ulonglong(const char *p, const formatdef *f)
339{
340 unsigned PY_LONG_LONG x;
341 memcpy((char *)&x, p, sizeof x);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000342#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000343 if (x <= LONG_MAX)
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000344 return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
345#endif
Bob Ippolito232f3c92006-05-23 19:12:41 +0000346 return PyLong_FromUnsignedLongLong(x);
347}
348
349#endif
350
351static PyObject *
352nu_float(const char *p, const formatdef *f)
353{
354 float x;
355 memcpy((char *)&x, p, sizeof x);
356 return PyFloat_FromDouble((double)x);
357}
358
359static PyObject *
360nu_double(const char *p, const formatdef *f)
361{
362 double x;
363 memcpy((char *)&x, p, sizeof x);
364 return PyFloat_FromDouble(x);
365}
366
367static PyObject *
368nu_void_p(const char *p, const formatdef *f)
369{
370 void *x;
371 memcpy((char *)&x, p, sizeof x);
372 return PyLong_FromVoidPtr(x);
373}
374
375static int
376np_byte(char *p, PyObject *v, const formatdef *f)
377{
378 long x;
379 if (get_long(v, &x) < 0)
380 return -1;
381 if (x < -128 || x > 127){
382 PyErr_SetString(StructError,
383 "byte format requires -128<=number<=127");
384 return -1;
385 }
386 *p = (char)x;
387 return 0;
388}
389
390static int
391np_ubyte(char *p, PyObject *v, const formatdef *f)
392{
393 long x;
394 if (get_long(v, &x) < 0)
395 return -1;
396 if (x < 0 || x > 255){
397 PyErr_SetString(StructError,
398 "ubyte format requires 0<=number<=255");
399 return -1;
400 }
401 *p = (char)x;
402 return 0;
403}
404
405static int
406np_char(char *p, PyObject *v, const formatdef *f)
407{
408 if (!PyString_Check(v) || PyString_Size(v) != 1) {
409 PyErr_SetString(StructError,
410 "char format require string of length 1");
411 return -1;
412 }
413 *p = *PyString_AsString(v);
414 return 0;
415}
416
417static int
418np_short(char *p, PyObject *v, const formatdef *f)
419{
420 long x;
421 short y;
422 if (get_long(v, &x) < 0)
423 return -1;
424 if (x < SHRT_MIN || x > SHRT_MAX){
425 PyErr_SetString(StructError,
426 "short format requires " STRINGIFY(SHRT_MIN)
427 "<=number<=" STRINGIFY(SHRT_MAX));
428 return -1;
429 }
430 y = (short)x;
431 memcpy(p, (char *)&y, sizeof y);
432 return 0;
433}
434
435static int
436np_ushort(char *p, PyObject *v, const formatdef *f)
437{
438 long x;
439 unsigned short y;
440 if (get_long(v, &x) < 0)
441 return -1;
442 if (x < 0 || x > USHRT_MAX){
443 PyErr_SetString(StructError,
444 "short format requires 0<=number<=" STRINGIFY(USHRT_MAX));
445 return -1;
446 }
447 y = (unsigned short)x;
448 memcpy(p, (char *)&y, sizeof y);
449 return 0;
450}
451
452static int
453np_int(char *p, PyObject *v, const formatdef *f)
454{
455 long x;
456 int y;
457 if (get_long(v, &x) < 0)
458 return -1;
459 y = (int)x;
460 memcpy(p, (char *)&y, sizeof y);
461 return 0;
462}
463
464static int
465np_uint(char *p, PyObject *v, const formatdef *f)
466{
467 unsigned long x;
468 unsigned int y;
469 if (get_ulong(v, &x) < 0)
470 return -1;
471 y = (unsigned int)x;
472 memcpy(p, (char *)&y, sizeof y);
473 return 0;
474}
475
476static int
477np_long(char *p, PyObject *v, const formatdef *f)
478{
479 long x;
480 if (get_long(v, &x) < 0)
481 return -1;
482 memcpy(p, (char *)&x, sizeof x);
483 return 0;
484}
485
486static int
487np_ulong(char *p, PyObject *v, const formatdef *f)
488{
489 unsigned long x;
490 if (get_ulong(v, &x) < 0)
491 return -1;
492 memcpy(p, (char *)&x, sizeof x);
493 return 0;
494}
495
496#ifdef HAVE_LONG_LONG
497
498static int
499np_longlong(char *p, PyObject *v, const formatdef *f)
500{
501 PY_LONG_LONG x;
502 if (get_longlong(v, &x) < 0)
503 return -1;
504 memcpy(p, (char *)&x, sizeof x);
505 return 0;
506}
507
508static int
509np_ulonglong(char *p, PyObject *v, const formatdef *f)
510{
511 unsigned PY_LONG_LONG x;
512 if (get_ulonglong(v, &x) < 0)
513 return -1;
514 memcpy(p, (char *)&x, sizeof x);
515 return 0;
516}
517#endif
518
519static int
520np_float(char *p, PyObject *v, const formatdef *f)
521{
522 float x = (float)PyFloat_AsDouble(v);
523 if (x == -1 && PyErr_Occurred()) {
524 PyErr_SetString(StructError,
525 "required argument is not a float");
526 return -1;
527 }
528 memcpy(p, (char *)&x, sizeof x);
529 return 0;
530}
531
532static int
533np_double(char *p, PyObject *v, const formatdef *f)
534{
535 double x = PyFloat_AsDouble(v);
536 if (x == -1 && PyErr_Occurred()) {
537 PyErr_SetString(StructError,
538 "required argument is not a float");
539 return -1;
540 }
541 memcpy(p, (char *)&x, sizeof(double));
542 return 0;
543}
544
545static int
546np_void_p(char *p, PyObject *v, const formatdef *f)
547{
548 void *x;
549
550 v = get_pylong(v);
551 if (v == NULL)
552 return -1;
553 assert(PyLong_Check(v));
554 x = PyLong_AsVoidPtr(v);
555 Py_DECREF(v);
556 if (x == NULL && PyErr_Occurred())
557 return -1;
558 memcpy(p, (char *)&x, sizeof x);
559 return 0;
560}
561
562static formatdef native_table[] = {
563 {'x', sizeof(char), 0, NULL},
564 {'b', sizeof(char), 0, nu_byte, np_byte},
565 {'B', sizeof(char), 0, nu_ubyte, np_ubyte},
566 {'c', sizeof(char), 0, nu_char, np_char},
567 {'s', sizeof(char), 0, NULL},
568 {'p', sizeof(char), 0, NULL},
569 {'h', sizeof(short), SHORT_ALIGN, nu_short, np_short},
570 {'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_ushort},
571 {'i', sizeof(int), INT_ALIGN, nu_int, np_int},
572 {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint},
573 {'l', sizeof(long), LONG_ALIGN, nu_long, np_long},
574 {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong},
Bob Ippolito232f3c92006-05-23 19:12:41 +0000575#ifdef HAVE_LONG_LONG
576 {'q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong},
577 {'Q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong},
578#endif
Bob Ippolitoa99865b2006-05-25 19:56:56 +0000579 {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
580 {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
581 {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p},
Bob Ippolito232f3c92006-05-23 19:12:41 +0000582 {0}
583};
584
585/* Big-endian routines. *****************************************************/
586
587static PyObject *
588bu_int(const char *p, const formatdef *f)
589{
590 long x = 0;
591 int i = f->size;
592 do {
593 x = (x<<8) | (*p++ & 0xFF);
594 } while (--i > 0);
595 /* Extend the sign bit. */
596 if (SIZEOF_LONG > f->size)
597 x |= -(x & (1L << (8*f->size - 1)));
598 return PyInt_FromLong(x);
599}
600
601static PyObject *
602bu_uint(const char *p, const formatdef *f)
603{
604 unsigned long x = 0;
605 int i = f->size;
606 do {
607 x = (x<<8) | (*p++ & 0xFF);
608 } while (--i > 0);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000609#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000610 if (x <= LONG_MAX)
Bob Ippolito232f3c92006-05-23 19:12:41 +0000611 return PyInt_FromLong((long)x);
Bob Ippolito3b0cae92006-05-25 19:15:27 +0000612#else
613 if (SIZEOF_LONG > f->size)
614 return PyInt_FromLong((long)x);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000615#endif
616 return PyLong_FromUnsignedLong(x);
Bob Ippolito232f3c92006-05-23 19:12:41 +0000617}
618
619static PyObject *
620bu_longlong(const char *p, const formatdef *f)
621{
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000622#if HAVE_LONG_LONG
623 PY_LONG_LONG x = 0;
624 int i = f->size;
625 do {
626 x = (x<<8) | (*p++ & 0xFF);
627 } while (--i > 0);
628 /* Extend the sign bit. */
629 if (SIZEOF_LONG_LONG > f->size)
630 x |= -(x & (1L << (8 * f->size - 1)));
631#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000632 if (x >= LONG_MIN && x <= LONG_MAX)
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000633 return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
634#endif
635 return PyLong_FromLongLong(x);
636#else
Bob Ippolito232f3c92006-05-23 19:12:41 +0000637 return _PyLong_FromByteArray((const unsigned char *)p,
638 8,
639 0, /* little-endian */
640 1 /* signed */);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000641#endif
Bob Ippolito232f3c92006-05-23 19:12:41 +0000642}
643
644static PyObject *
645bu_ulonglong(const char *p, const formatdef *f)
646{
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000647#if HAVE_LONG_LONG
648 unsigned PY_LONG_LONG x = 0;
649 int i = f->size;
650 do {
651 x = (x<<8) | (*p++ & 0xFF);
652 } while (--i > 0);
653#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000654 if (x <= LONG_MAX)
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000655 return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
656#endif
657 return PyLong_FromUnsignedLongLong(x);
658#else
Bob Ippolito232f3c92006-05-23 19:12:41 +0000659 return _PyLong_FromByteArray((const unsigned char *)p,
660 8,
661 0, /* little-endian */
662 0 /* signed */);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000663#endif
Bob Ippolito232f3c92006-05-23 19:12:41 +0000664}
665
666static PyObject *
667bu_float(const char *p, const formatdef *f)
668{
669 return unpack_float(p, 0);
670}
671
672static PyObject *
673bu_double(const char *p, const formatdef *f)
674{
675 return unpack_double(p, 0);
676}
677
678static int
679bp_int(char *p, PyObject *v, const formatdef *f)
680{
681 long x;
682 int i;
683 if (get_long(v, &x) < 0)
684 return -1;
685 i = f->size;
686 do {
687 p[--i] = (char)x;
688 x >>= 8;
689 } while (i > 0);
690 return 0;
691}
692
693static int
694bp_uint(char *p, PyObject *v, const formatdef *f)
695{
696 unsigned long x;
697 int i;
698 if (get_ulong(v, &x) < 0)
699 return -1;
700 i = f->size;
701 do {
702 p[--i] = (char)x;
703 x >>= 8;
704 } while (i > 0);
705 return 0;
706}
707
708static int
709bp_longlong(char *p, PyObject *v, const formatdef *f)
710{
711 int res;
712 v = get_pylong(v);
713 if (v == NULL)
714 return -1;
715 res = _PyLong_AsByteArray((PyLongObject *)v,
716 (unsigned char *)p,
717 8,
718 0, /* little_endian */
719 1 /* signed */);
720 Py_DECREF(v);
721 return res;
722}
723
724static int
725bp_ulonglong(char *p, PyObject *v, const formatdef *f)
726{
727 int res;
728 v = get_pylong(v);
729 if (v == NULL)
730 return -1;
731 res = _PyLong_AsByteArray((PyLongObject *)v,
732 (unsigned char *)p,
733 8,
734 0, /* little_endian */
735 0 /* signed */);
736 Py_DECREF(v);
737 return res;
738}
739
740static int
741bp_float(char *p, PyObject *v, const formatdef *f)
742{
743 double x = PyFloat_AsDouble(v);
744 if (x == -1 && PyErr_Occurred()) {
745 PyErr_SetString(StructError,
746 "required argument is not a float");
747 return -1;
748 }
749 return _PyFloat_Pack4(x, (unsigned char *)p, 0);
750}
751
752static int
753bp_double(char *p, PyObject *v, const formatdef *f)
754{
755 double x = PyFloat_AsDouble(v);
756 if (x == -1 && PyErr_Occurred()) {
757 PyErr_SetString(StructError,
758 "required argument is not a float");
759 return -1;
760 }
761 return _PyFloat_Pack8(x, (unsigned char *)p, 0);
762}
763
764static formatdef bigendian_table[] = {
765 {'x', 1, 0, NULL},
766 {'b', 1, 0, bu_int, bp_int},
767 {'B', 1, 0, bu_uint, bp_int},
768 {'c', 1, 0, nu_char, np_char},
769 {'s', 1, 0, NULL},
770 {'p', 1, 0, NULL},
771 {'h', 2, 0, bu_int, bp_int},
772 {'H', 2, 0, bu_uint, bp_uint},
773 {'i', 4, 0, bu_int, bp_int},
774 {'I', 4, 0, bu_uint, bp_uint},
775 {'l', 4, 0, bu_int, bp_int},
776 {'L', 4, 0, bu_uint, bp_uint},
777 {'q', 8, 0, bu_longlong, bp_longlong},
778 {'Q', 8, 0, bu_ulonglong, bp_ulonglong},
779 {'f', 4, 0, bu_float, bp_float},
780 {'d', 8, 0, bu_double, bp_double},
781 {0}
782};
783
784/* Little-endian routines. *****************************************************/
785
786static PyObject *
787lu_int(const char *p, const formatdef *f)
788{
789 long x = 0;
790 int i = f->size;
791 do {
792 x = (x<<8) | (p[--i] & 0xFF);
793 } while (i > 0);
794 /* Extend the sign bit. */
795 if (SIZEOF_LONG > f->size)
796 x |= -(x & (1L << (8*f->size - 1)));
797 return PyInt_FromLong(x);
798}
799
800static PyObject *
801lu_uint(const char *p, const formatdef *f)
802{
803 unsigned long x = 0;
804 int i = f->size;
805 do {
806 x = (x<<8) | (p[--i] & 0xFF);
807 } while (i > 0);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000808#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000809 if (x <= LONG_MAX)
Bob Ippolito232f3c92006-05-23 19:12:41 +0000810 return PyInt_FromLong((long)x);
Bob Ippolito3b0cae92006-05-25 19:15:27 +0000811#else
812 if (SIZEOF_LONG > f->size)
813 return PyInt_FromLong((long)x);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000814#endif
815 return PyLong_FromUnsignedLong((long)x);
Bob Ippolito232f3c92006-05-23 19:12:41 +0000816}
817
818static PyObject *
819lu_longlong(const char *p, const formatdef *f)
820{
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000821#if HAVE_LONG_LONG
822 PY_LONG_LONG x = 0;
823 int i = f->size;
824 do {
825 x = (x<<8) | (p[--i] & 0xFF);
826 } while (i > 0);
827 /* Extend the sign bit. */
828 if (SIZEOF_LONG_LONG > f->size)
829 x |= -(x & (1L << (8 * f->size - 1)));
830#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000831 if (x >= LONG_MIN && x <= LONG_MAX)
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000832 return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
833#endif
834 return PyLong_FromLongLong(x);
835#else
Bob Ippolito232f3c92006-05-23 19:12:41 +0000836 return _PyLong_FromByteArray((const unsigned char *)p,
837 8,
838 1, /* little-endian */
839 1 /* signed */);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000840#endif
Bob Ippolito232f3c92006-05-23 19:12:41 +0000841}
842
843static PyObject *
844lu_ulonglong(const char *p, const formatdef *f)
845{
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000846#if HAVE_LONG_LONG
847 unsigned PY_LONG_LONG x = 0;
848 int i = f->size;
849 do {
850 x = (x<<8) | (p[--i] & 0xFF);
851 } while (i > 0);
852#ifdef PY_USE_INT_WHEN_POSSIBLE
Bob Ippolito04ab9942006-05-25 19:33:38 +0000853 if (x <= LONG_MAX)
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000854 return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
855#endif
856 return PyLong_FromUnsignedLongLong(x);
857#else
Bob Ippolito232f3c92006-05-23 19:12:41 +0000858 return _PyLong_FromByteArray((const unsigned char *)p,
859 8,
860 1, /* little-endian */
861 0 /* signed */);
Bob Ippolito94f68ee2006-05-25 18:44:50 +0000862#endif
Bob Ippolito232f3c92006-05-23 19:12:41 +0000863}
864
865static PyObject *
866lu_float(const char *p, const formatdef *f)
867{
868 return unpack_float(p, 1);
869}
870
871static PyObject *
872lu_double(const char *p, const formatdef *f)
873{
874 return unpack_double(p, 1);
875}
876
877static int
878lp_int(char *p, PyObject *v, const formatdef *f)
879{
880 long x;
881 int i;
882 if (get_long(v, &x) < 0)
883 return -1;
884 i = f->size;
885 do {
886 *p++ = (char)x;
887 x >>= 8;
888 } while (--i > 0);
889 return 0;
890}
891
892static int
893lp_uint(char *p, PyObject *v, const formatdef *f)
894{
895 unsigned long x;
896 int i;
897 if (get_ulong(v, &x) < 0)
898 return -1;
899 i = f->size;
900 do {
901 *p++ = (char)x;
902 x >>= 8;
903 } while (--i > 0);
904 return 0;
905}
906
907static int
908lp_longlong(char *p, PyObject *v, const formatdef *f)
909{
910 int res;
911 v = get_pylong(v);
912 if (v == NULL)
913 return -1;
914 res = _PyLong_AsByteArray((PyLongObject*)v,
915 (unsigned char *)p,
916 8,
917 1, /* little_endian */
918 1 /* signed */);
919 Py_DECREF(v);
920 return res;
921}
922
923static int
924lp_ulonglong(char *p, PyObject *v, const formatdef *f)
925{
926 int res;
927 v = get_pylong(v);
928 if (v == NULL)
929 return -1;
930 res = _PyLong_AsByteArray((PyLongObject*)v,
931 (unsigned char *)p,
932 8,
933 1, /* little_endian */
934 0 /* signed */);
935 Py_DECREF(v);
936 return res;
937}
938
939static int
940lp_float(char *p, PyObject *v, const formatdef *f)
941{
942 double x = PyFloat_AsDouble(v);
943 if (x == -1 && PyErr_Occurred()) {
944 PyErr_SetString(StructError,
945 "required argument is not a float");
946 return -1;
947 }
948 return _PyFloat_Pack4(x, (unsigned char *)p, 1);
949}
950
951static int
952lp_double(char *p, PyObject *v, const formatdef *f)
953{
954 double x = PyFloat_AsDouble(v);
955 if (x == -1 && PyErr_Occurred()) {
956 PyErr_SetString(StructError,
957 "required argument is not a float");
958 return -1;
959 }
960 return _PyFloat_Pack8(x, (unsigned char *)p, 1);
961}
962
963static formatdef lilendian_table[] = {
964 {'x', 1, 0, NULL},
965 {'b', 1, 0, lu_int, lp_int},
966 {'B', 1, 0, lu_uint, lp_int},
967 {'c', 1, 0, nu_char, np_char},
968 {'s', 1, 0, NULL},
969 {'p', 1, 0, NULL},
970 {'h', 2, 0, lu_int, lp_int},
971 {'H', 2, 0, lu_uint, lp_uint},
972 {'i', 4, 0, lu_int, lp_int},
973 {'I', 4, 0, lu_uint, lp_uint},
974 {'l', 4, 0, lu_int, lp_int},
975 {'L', 4, 0, lu_uint, lp_uint},
976 {'q', 8, 0, lu_longlong, lp_longlong},
977 {'Q', 8, 0, lu_ulonglong, lp_ulonglong},
978 {'f', 4, 0, lu_float, lp_float},
979 {'d', 8, 0, lu_double, lp_double},
980 {0}
981};
982
983
984static const formatdef *
985whichtable(char **pfmt)
986{
987 const char *fmt = (*pfmt)++; /* May be backed out of later */
988 switch (*fmt) {
989 case '<':
990 return lilendian_table;
991 case '>':
992 case '!': /* Network byte order is big-endian */
993 return bigendian_table;
994 case '=': { /* Host byte order -- different from native in aligment! */
995 int n = 1;
996 char *p = (char *) &n;
997 if (*p == 1)
998 return lilendian_table;
999 else
1000 return bigendian_table;
1001 }
1002 default:
1003 --*pfmt; /* Back out of pointer increment */
1004 /* Fall through */
1005 case '@':
1006 return native_table;
1007 }
1008}
1009
1010
1011/* Get the table entry for a format code */
1012
1013static const formatdef *
1014getentry(int c, const formatdef *f)
1015{
1016 for (; f->format != '\0'; f++) {
1017 if (f->format == c) {
1018 return f;
1019 }
1020 }
1021 PyErr_SetString(StructError, "bad char in struct format");
1022 return NULL;
1023}
1024
1025
1026/* Align a size according to a format code */
1027
1028static int
1029align(int size, int c, const formatdef *e)
1030{
1031 if (e->format == c) {
1032 if (e->alignment) {
1033 size = ((size + e->alignment - 1)
1034 / e->alignment)
1035 * e->alignment;
1036 }
1037 }
1038 return size;
1039}
1040
1041
1042/* calculate the size of a format string */
1043
1044static int
1045prepare_s(PyStructObject *self)
1046{
1047 const formatdef *f;
1048 const formatdef *e;
1049 formatcode *codes;
1050
1051 const char *s;
1052 const char *fmt;
1053 char c;
Bob Ippolitoeb621272006-05-24 15:32:06 +00001054 int size, len, num, itemsize, x;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001055
1056 fmt = PyString_AS_STRING(self->s_format);
1057
1058 f = whichtable((char **)&fmt);
1059
1060 s = fmt;
1061 size = 0;
1062 len = 0;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001063 while ((c = *s++) != '\0') {
1064 if (isspace(Py_CHARMASK(c)))
1065 continue;
1066 if ('0' <= c && c <= '9') {
1067 num = c - '0';
1068 while ('0' <= (c = *s++) && c <= '9') {
1069 x = num*10 + (c - '0');
1070 if (x/10 != num) {
1071 PyErr_SetString(
1072 StructError,
1073 "overflow in item count");
1074 return -1;
1075 }
1076 num = x;
1077 }
1078 if (c == '\0')
1079 break;
1080 }
1081 else
1082 num = 1;
1083
1084 e = getentry(c, f);
1085 if (e == NULL)
1086 return -1;
1087
1088 switch (c) {
1089 case 's': /* fall through */
1090 case 'p': len++; break;
1091 case 'x': break;
1092 default: len += num; break;
1093 }
Bob Ippolito232f3c92006-05-23 19:12:41 +00001094
1095 itemsize = e->size;
1096 size = align(size, c, e);
1097 x = num * itemsize;
1098 size += x;
1099 if (x/itemsize != num || size < 0) {
1100 PyErr_SetString(StructError,
1101 "total struct size too long");
1102 return -1;
1103 }
1104 }
1105
1106 self->s_size = size;
1107 self->s_len = len;
Bob Ippolitoeb621272006-05-24 15:32:06 +00001108 codes = PyMem_MALLOC((len + 1) * sizeof(formatcode));
Bob Ippolito232f3c92006-05-23 19:12:41 +00001109 if (codes == NULL) {
1110 PyErr_NoMemory();
1111 return -1;
1112 }
1113 self->s_codes = codes;
1114
1115 s = fmt;
1116 size = 0;
1117 while ((c = *s++) != '\0') {
1118 if (isspace(Py_CHARMASK(c)))
1119 continue;
1120 if ('0' <= c && c <= '9') {
1121 num = c - '0';
1122 while ('0' <= (c = *s++) && c <= '9')
1123 num = num*10 + (c - '0');
1124 if (c == '\0')
1125 break;
1126 }
1127 else
1128 num = 1;
1129
1130 e = getentry(c, f);
1131
1132 size = align(size, c, e);
Bob Ippolitoeb621272006-05-24 15:32:06 +00001133 if (c == 's' || c == 'p') {
Bob Ippolito232f3c92006-05-23 19:12:41 +00001134 codes->offset = size;
Bob Ippolitoeb621272006-05-24 15:32:06 +00001135 codes->size = num;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001136 codes->fmtdef = e;
1137 codes++;
Bob Ippolitoeb621272006-05-24 15:32:06 +00001138 size += num;
1139 } else if (c == 'x') {
1140 size += num;
1141 } else {
1142 while (--num >= 0) {
1143 codes->offset = size;
1144 codes->size = e->size;
1145 codes->fmtdef = e;
1146 codes++;
1147 size += e->size;
1148 }
Bob Ippolito232f3c92006-05-23 19:12:41 +00001149 }
Bob Ippolito232f3c92006-05-23 19:12:41 +00001150 }
1151 codes->fmtdef = NULL;
Bob Ippolitoeb621272006-05-24 15:32:06 +00001152 codes->offset = size;
1153 codes->size = 0;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001154
1155 return 0;
1156}
1157
1158static PyObject *
1159s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1160{
1161 PyObject *self;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001162
1163 assert(type != NULL && type->tp_alloc != NULL);
1164
1165 self = type->tp_alloc(type, 0);
1166 if (self != NULL) {
1167 PyStructObject *s = (PyStructObject*)self;
1168 Py_INCREF(Py_None);
1169 s->s_format = Py_None;
1170 s->s_codes = NULL;
1171 s->s_size = -1;
1172 s->s_len = -1;
1173 }
1174 return self;
1175}
1176
1177static int
1178s_init(PyObject *self, PyObject *args, PyObject *kwds)
1179{
1180 PyStructObject *soself = (PyStructObject *)self;
1181 PyObject *o_format = NULL;
1182 int ret = 0;
1183 static char *kwlist[] = {"format", 0};
1184
1185 assert(PyStruct_Check(self));
1186
1187 if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:Struct", kwlist,
1188 &o_format))
1189 return -1;
1190
1191 Py_INCREF(o_format);
1192 Py_XDECREF(soself->s_format);
1193 soself->s_format = o_format;
1194
1195 ret = prepare_s(soself);
1196 return ret;
1197}
1198
1199static void
1200s_dealloc(PyStructObject *s)
1201{
Bob Ippolito232f3c92006-05-23 19:12:41 +00001202 if (s->weakreflist != NULL)
1203 PyObject_ClearWeakRefs((PyObject *)s);
1204 if (s->s_codes != NULL) {
1205 PyMem_FREE(s->s_codes);
1206 }
1207 Py_XDECREF(s->s_format);
1208 s->ob_type->tp_free((PyObject *)s);
1209}
1210
Bob Ippolitoeb621272006-05-24 15:32:06 +00001211static PyObject *
1212s_unpack_internal(PyStructObject *soself, char *startfrom) {
1213 formatcode *code;
1214 Py_ssize_t i = 0;
1215 PyObject *result = PyTuple_New(soself->s_len);
1216 if (result == NULL)
1217 return NULL;
1218
1219 for (code = soself->s_codes; code->fmtdef != NULL; code++) {
1220 PyObject *v;
1221 const formatdef *e = code->fmtdef;
1222 const char *res = startfrom + code->offset;
1223 if (e->format == 's') {
1224 v = PyString_FromStringAndSize(res, code->size);
1225 if (v == NULL)
1226 goto fail;
1227 PyTuple_SET_ITEM(result, i++, v);
1228 } else if (e->format == 'p') {
1229 Py_ssize_t n = *(unsigned char*)res;
1230 if (n >= code->size)
1231 n = code->size - 1;
1232 v = PyString_FromStringAndSize(res + 1, n);
1233 if (v == NULL)
1234 goto fail;
1235 PyTuple_SET_ITEM(result, i++, v);
1236 } else {
1237 v = e->unpack(res, e);
1238 if (v == NULL)
1239 goto fail;
1240 PyTuple_SET_ITEM(result, i++, v);
1241 }
1242 }
1243
1244 return result;
1245fail:
1246 Py_DECREF(result);
1247 return NULL;
1248};
1249
1250
Bob Ippolito232f3c92006-05-23 19:12:41 +00001251PyDoc_STRVAR(s_unpack__doc__,
1252"unpack(str) -> (v1, v2, ...)\n\
1253\n\
1254Return tuple containing values unpacked according to this Struct's format.\n\
1255Requires len(str) == self.size. See struct.__doc__ for more on format\n\
1256strings.");
1257
1258static PyObject *
1259s_unpack(PyObject *self, PyObject *inputstr)
1260{
Bob Ippolitoeb621272006-05-24 15:32:06 +00001261 PyStructObject *soself = (PyStructObject *)self;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001262 assert(PyStruct_Check(self));
1263 assert(soself->s_codes != NULL);
1264 if (inputstr == NULL || !PyString_Check(inputstr) ||
Bob Ippolitoeb621272006-05-24 15:32:06 +00001265 PyString_GET_SIZE(inputstr) != soself->s_size) {
Bob Ippolito232f3c92006-05-23 19:12:41 +00001266 PyErr_Format(StructError,
1267 "unpack requires a string argument of length %d", soself->s_size);
1268 return NULL;
1269 }
Bob Ippolitoeb621272006-05-24 15:32:06 +00001270 return s_unpack_internal(soself, PyString_AS_STRING(inputstr));
1271}
1272
1273PyDoc_STRVAR(s_unpack_from__doc__,
1274"unpack_from(buffer[, offset]) -> (v1, v2, ...)\n\
1275\n\
1276Return tuple containing values unpacked according to this Struct's format.\n\
1277Unlike unpack, unpack_from can unpack values from any object supporting\n\
1278the buffer API, not just str. Requires len(buffer[offset:]) >= self.size.\n\
1279See struct.__doc__ for more on format strings.");
1280
1281static PyObject *
1282s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
1283{
1284 static char *kwlist[] = {"buffer", "offset", 0};
1285#if (PY_VERSION_HEX < 0x02050000)
1286 static char *fmt = "z#|i:unpack_from";
1287#else
1288 static char *fmt = "z#|n:unpack_from";
1289#endif
1290 Py_ssize_t buffer_len = 0, offset = 0;
1291 char *buffer = NULL;
1292 PyStructObject *soself = (PyStructObject *)self;
1293 assert(PyStruct_Check(self));
1294 assert(soself->s_codes != NULL);
1295
1296 if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist,
1297 &buffer, &buffer_len, &offset))
1298 return NULL;
1299
1300 if (buffer == NULL) {
1301 PyErr_Format(StructError,
1302 "unpack_from requires a buffer argument");
Bob Ippolito232f3c92006-05-23 19:12:41 +00001303 return NULL;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001304 }
Bob Ippolitoeb621272006-05-24 15:32:06 +00001305
1306 if (offset < 0)
1307 offset += buffer_len;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001308
Bob Ippolitoeb621272006-05-24 15:32:06 +00001309 if (offset < 0 || (buffer_len - offset) < soself->s_size) {
1310 PyErr_Format(StructError,
1311 "unpack_from requires a buffer of at least %d bytes",
1312 soself->s_size);
1313 return NULL;
1314 }
1315 return s_unpack_internal(soself, buffer + offset);
1316}
Bob Ippolito232f3c92006-05-23 19:12:41 +00001317
Bob Ippolito232f3c92006-05-23 19:12:41 +00001318
Martin Blais2856e5f2006-05-26 12:03:27 +00001319/*
1320 * Guts of the pack function.
1321 *
1322 * Takes a struct object, a tuple of arguments, and offset in that tuple of
1323 * argument for where to start processing the arguments for packing, and a
1324 * character buffer for writing the packed string. The caller must insure
1325 * that the buffer may contain the required length for packing the arguments.
1326 * 0 is returned on success, 1 is returned if there is an error.
1327 *
1328 */
1329static int
1330s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf)
Bob Ippolito232f3c92006-05-23 19:12:41 +00001331{
Bob Ippolito232f3c92006-05-23 19:12:41 +00001332 formatcode *code;
1333 Py_ssize_t i;
Martin Blais2856e5f2006-05-26 12:03:27 +00001334
1335 memset(buf, '\0', soself->s_size);
1336 i = offset;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001337 for (code = soself->s_codes; code->fmtdef != NULL; code++) {
1338 Py_ssize_t n;
1339 PyObject *v;
1340 const formatdef *e = code->fmtdef;
Martin Blais2856e5f2006-05-26 12:03:27 +00001341 char *res = buf + code->offset;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001342 if (e->format == 's') {
1343 v = PyTuple_GET_ITEM(args, i++);
1344 if (!PyString_Check(v)) {
1345 PyErr_SetString(StructError,
1346 "argument for 's' must be a string");
Martin Blais2856e5f2006-05-26 12:03:27 +00001347 return -1;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001348 }
1349 n = PyString_GET_SIZE(v);
Bob Ippolitoeb621272006-05-24 15:32:06 +00001350 if (n > code->size)
1351 n = code->size;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001352 if (n > 0)
1353 memcpy(res, PyString_AS_STRING(v), n);
1354 } else if (e->format == 'p') {
1355 v = PyTuple_GET_ITEM(args, i++);
1356 if (!PyString_Check(v)) {
1357 PyErr_SetString(StructError,
1358 "argument for 'p' must be a string");
Martin Blais2856e5f2006-05-26 12:03:27 +00001359 return -1;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001360 }
1361 n = PyString_GET_SIZE(v);
Bob Ippolitoeb621272006-05-24 15:32:06 +00001362 if (n > (code->size - 1))
1363 n = code->size - 1;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001364 if (n > 0)
1365 memcpy(res + 1, PyString_AS_STRING(v), n);
1366 if (n > 255)
1367 n = 255;
1368 *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char);
1369 } else {
Bob Ippolitoeb621272006-05-24 15:32:06 +00001370 v = PyTuple_GET_ITEM(args, i++);
1371 if (e->pack(res, v, e) < 0)
Martin Blais2856e5f2006-05-26 12:03:27 +00001372 return -1;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001373 }
1374 }
1375
Martin Blais2856e5f2006-05-26 12:03:27 +00001376 /* Success */
1377 return 0;
1378}
Bob Ippolito232f3c92006-05-23 19:12:41 +00001379
Martin Blais2856e5f2006-05-26 12:03:27 +00001380
1381PyDoc_STRVAR(s_pack__doc__,
1382"pack(v1, v2, ...) -> string\n\
1383\n\
1384Return a string containing values v1, v2, ... packed according to this\n\
1385Struct's format. See struct.__doc__ for more on format strings.");
1386
1387static PyObject *
1388s_pack(PyObject *self, PyObject *args)
1389{
1390 PyStructObject *soself;
1391 PyObject *result;
1392
1393 /* Validate arguments. */
1394 soself = (PyStructObject *)self;
1395 assert(PyStruct_Check(self));
1396 assert(soself->s_codes != NULL);
1397 if (args == NULL || !PyTuple_Check(args) ||
1398 PyTuple_GET_SIZE(args) != soself->s_len)
1399 {
1400 PyErr_Format(StructError,
1401 "pack requires exactly %d arguments", soself->s_len);
1402 return NULL;
1403 }
Bob Ippolito232f3c92006-05-23 19:12:41 +00001404
Martin Blais2856e5f2006-05-26 12:03:27 +00001405 /* Allocate a new string */
1406 result = PyString_FromStringAndSize((char *)NULL, soself->s_size);
1407 if (result == NULL)
1408 return NULL;
1409
1410 /* Call the guts */
1411 if ( s_pack_internal(soself, args, 0, PyString_AS_STRING(result)) != 0 ) {
1412 Py_DECREF(result);
1413 return NULL;
1414 }
1415
1416 return result;
1417}
1418
1419PyDoc_STRVAR(s_pack_to__doc__,
1420"pack_to(buffer, offset, v1, v2, ...)\n\
1421\n\
1422Pack the values v2, v2, ... according to this Struct's format, write \n\
1423the packed bytes into the given buffer at the given offset. Note that \n\
1424the offset is not an optional argument. See struct.__doc__ for \n\
1425more on format strings.");
1426
1427static PyObject *
1428s_pack_to(PyObject *self, PyObject *args)
1429{
1430 PyStructObject *soself;
1431 char *buffer;
1432 Py_ssize_t buffer_len, offset;
1433
1434 /* Validate arguments. +1 is for the first arg as buffer. */
1435 soself = (PyStructObject *)self;
1436 assert(PyStruct_Check(self));
1437 assert(soself->s_codes != NULL);
1438 if (args == NULL || !PyTuple_Check(args) ||
1439 PyTuple_GET_SIZE(args) != (soself->s_len + 2))
1440 {
1441 PyErr_Format(StructError,
1442 "pack_to requires exactly %d arguments",
1443 (soself->s_len + 2));
1444 return NULL;
1445 }
1446
1447 /* Extract a writable memory buffer from the first argument */
1448 if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0),
1449 (void**)&buffer, &buffer_len) == -1 ) {
1450 return NULL;
1451 }
1452 assert( buffer_len >= 0 );
1453
1454 /* Extract the offset from the first argument */
1455 offset = PyInt_AsLong(PyTuple_GET_ITEM(args, 1));
1456
1457 /* Support negative offsets. */
1458 if (offset < 0)
1459 offset += buffer_len;
1460
1461 /* Check boundaries */
1462 if (offset < 0 || (buffer_len - offset) < soself->s_size) {
1463 PyErr_Format(StructError,
1464 "pack_to requires a buffer of at least %d bytes",
1465 soself->s_size);
1466 return NULL;
1467 }
1468
1469 /* Call the guts */
1470 if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) {
1471 return NULL;
1472 }
1473
1474 return Py_None;
Bob Ippolito232f3c92006-05-23 19:12:41 +00001475}
1476
1477
1478/* List of functions */
1479
1480static struct PyMethodDef s_methods[] = {
Bob Ippolitoeb621272006-05-24 15:32:06 +00001481 {"pack", (PyCFunction)s_pack, METH_VARARGS, s_pack__doc__},
Martin Blais2856e5f2006-05-26 12:03:27 +00001482 {"pack_to", (PyCFunction)s_pack_to, METH_VARARGS, s_pack_to__doc__},
Bob Ippolitoeb621272006-05-24 15:32:06 +00001483 {"unpack", (PyCFunction)s_unpack, METH_O, s_unpack__doc__},
1484 {"unpack_from", (PyCFunction)s_unpack_from, METH_KEYWORDS, s_unpack_from__doc__},
Bob Ippolito232f3c92006-05-23 19:12:41 +00001485 {NULL, NULL} /* sentinel */
1486};
1487
1488PyDoc_STRVAR(s__doc__, "Compiled struct object");
1489
1490#define OFF(x) offsetof(PyStructObject, x)
1491
1492static PyMemberDef s_memberlist[] = {
1493 {"format", T_OBJECT, OFF(s_format), RO,
1494 "struct format string"},
1495 {"size", T_INT, OFF(s_size), RO,
1496 "struct size in bytes"},
1497 {"_len", T_INT, OFF(s_len), RO,
1498 "number of items expected in tuple"},
1499 {NULL} /* Sentinel */
1500};
1501
1502
1503static
1504PyTypeObject PyStructType = {
Bob Ippolito3fc2bb92006-05-25 19:03:19 +00001505 PyObject_HEAD_INIT(NULL)
Bob Ippolito232f3c92006-05-23 19:12:41 +00001506 0,
1507 "Struct",
1508 sizeof(PyStructObject),
1509 0,
1510 (destructor)s_dealloc, /* tp_dealloc */
1511 0, /* tp_print */
1512 0, /* tp_getattr */
1513 0, /* tp_setattr */
1514 0, /* tp_compare */
1515 0, /* tp_repr */
1516 0, /* tp_as_number */
1517 0, /* tp_as_sequence */
1518 0, /* tp_as_mapping */
1519 0, /* tp_hash */
1520 0, /* tp_call */
1521 0, /* tp_str */
1522 PyObject_GenericGetAttr, /* tp_getattro */
1523 PyObject_GenericSetAttr, /* tp_setattro */
1524 0, /* tp_as_buffer */
1525 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
1526 s__doc__, /* tp_doc */
1527 0, /* tp_traverse */
1528 0, /* tp_clear */
1529 0, /* tp_richcompare */
1530 offsetof(PyStructObject, weakreflist), /* tp_weaklistoffset */
1531 0, /* tp_iter */
1532 0, /* tp_iternext */
1533 s_methods, /* tp_methods */
1534 s_memberlist, /* tp_members */
1535 0, /* tp_getset */
1536 0, /* tp_base */
1537 0, /* tp_dict */
1538 0, /* tp_descr_get */
1539 0, /* tp_descr_set */
1540 0, /* tp_dictoffset */
1541 s_init, /* tp_init */
1542 PyType_GenericAlloc, /* tp_alloc */
1543 s_new, /* tp_new */
1544 PyObject_Del, /* tp_free */
1545};
1546
1547/* Module initialization */
1548
1549PyMODINIT_FUNC
1550init_struct(void)
1551{
1552 PyObject *m = Py_InitModule("_struct", NULL);
1553 if (m == NULL)
1554 return;
1555
Bob Ippolito3fc2bb92006-05-25 19:03:19 +00001556 PyStructType.ob_type = &PyType_Type;
1557 if (PyType_Ready(&PyStructType) < 0)
1558 return;
1559
Bob Ippolitoa99865b2006-05-25 19:56:56 +00001560 /* Check endian and swap in faster functions */
1561 {
1562 int one = 1;
1563 formatdef *native = native_table;
1564 formatdef *other, *ptr;
1565 if ((int)*(unsigned char*)&one)
1566 other = lilendian_table;
1567 else
1568 other = bigendian_table;
Bob Ippolito964e02a2006-05-25 21:09:45 +00001569 /* Scan through the native table, find a matching
1570 entry in the endian table and swap in the
1571 native implementations whenever possible
1572 (64-bit platforms may not have "standard" sizes) */
Bob Ippolitoa99865b2006-05-25 19:56:56 +00001573 while (native->format != '\0' && other->format != '\0') {
1574 ptr = other;
1575 while (ptr->format != '\0') {
1576 if (ptr->format == native->format) {
Bob Ippolito964e02a2006-05-25 21:09:45 +00001577 /* Match faster when formats are
1578 listed in the same order */
Bob Ippolitoa99865b2006-05-25 19:56:56 +00001579 if (ptr == other)
1580 other++;
Bob Ippolito964e02a2006-05-25 21:09:45 +00001581 /* Only use the trick if the
1582 size matches */
1583 if (ptr->size != native->size)
1584 break;
1585 /* Skip float and double, could be
1586 "unknown" float format */
1587 if (ptr->format == 'd' || ptr->format == 'f')
1588 break;
1589 ptr->pack = native->pack;
1590 ptr->unpack = native->unpack;
Bob Ippolitoa99865b2006-05-25 19:56:56 +00001591 break;
1592 }
1593 ptr++;
1594 }
1595 native++;
1596 }
1597 }
Bob Ippolito04ab9942006-05-25 19:33:38 +00001598
Bob Ippolito232f3c92006-05-23 19:12:41 +00001599 /* Add some symbolic constants to the module */
1600 if (StructError == NULL) {
1601 StructError = PyErr_NewException("struct.error", NULL, NULL);
1602 if (StructError == NULL)
1603 return;
1604 }
Bob Ippolito04ab9942006-05-25 19:33:38 +00001605
Bob Ippolito232f3c92006-05-23 19:12:41 +00001606 Py_INCREF(StructError);
1607 PyModule_AddObject(m, "error", StructError);
Bob Ippolito04ab9942006-05-25 19:33:38 +00001608
Bob Ippolito232f3c92006-05-23 19:12:41 +00001609 Py_INCREF((PyObject*)&PyStructType);
1610 PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType);
1611}