blob: f9eb6b566f4a3a0c39767ebd9d28849b3221bd60 [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
Barry Warsaw30695fa1996-12-12 23:32:31 +000034#include "Python.h"
Guido van Rossum02975121992-08-17 08:55:12 +000035
Barry Warsaw30695fa1996-12-12 23:32:31 +000036static PyObject *StructError;
Guido van Rossum02975121992-08-17 08:55:12 +000037
38
39/* Define various structs to figure out the alignments of types */
40
Jack Jansen971e1df1995-02-02 14:29:10 +000041#ifdef __MWERKS__
42/*
43** XXXX We have a problem here. There are no unique alignment rules
44** on the PowerPC mac.
45*/
46#ifdef __powerc
47#pragma options align=mac68k
48#endif
49#endif /* __MWERKS__ */
50
Guido van Rossum02975121992-08-17 08:55:12 +000051typedef struct { char c; short x; } s_short;
52typedef struct { char c; int x; } s_int;
53typedef struct { char c; long x; } s_long;
54typedef struct { char c; float x; } s_float;
55typedef struct { char c; double x; } s_double;
56
57#define SHORT_ALIGN (sizeof(s_short) - sizeof(short))
58#define INT_ALIGN (sizeof(s_int) - sizeof(int))
59#define LONG_ALIGN (sizeof(s_long) - sizeof(long))
60#define FLOAT_ALIGN (sizeof(s_float) - sizeof(float))
61#define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))
62
Jack Jansen971e1df1995-02-02 14:29:10 +000063#ifdef __powerc
64#pragma options align=reset
65#endif
66
Guido van Rossum02975121992-08-17 08:55:12 +000067
68/* Align a size according to a format code */
69
70static int
71align(size, c)
72 int size;
73 int c;
74{
75 int a;
76
77 switch (c) {
78 case 'h': a = SHORT_ALIGN; break;
79 case 'i': a = INT_ALIGN; break;
80 case 'l': a = LONG_ALIGN; break;
81 case 'f': a = FLOAT_ALIGN; break;
82 case 'd': a = DOUBLE_ALIGN; break;
83 default: return size;
84 }
85 return (size + a - 1) / a * a;
86}
87
88
89/* calculate the size of a format string */
90
91static int
92calcsize(fmt)
93 char *fmt;
94{
95 char *s;
96 char c;
97 int size, num, itemsize, x;
98
99 s = fmt;
100 size = 0;
101 while ((c = *s++) != '\0') {
102 if ('0' <= c && c <= '9') {
103 num = c - '0';
104 while ('0' <= (c = *s++) && c <= '9') {
105 x = num*10 + (c - '0');
106 if (x/10 != num) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000107 PyErr_SetString(StructError,
108 "int overflow in fmt");
Guido van Rossum02975121992-08-17 08:55:12 +0000109 return -1;
110 }
111 num = x;
112 }
113 if (c == '\0')
114 break;
115 }
116 else
117 num = 1;
118
119 size = align(size, c);
120
121 switch (c) {
122
123 case 'x': /* pad byte */
124 case 'b': /* byte-sized int */
125 case 'c': /* char */
126 itemsize = 1;
127 break;
128
129 case 'h': /* short ("half-size)" int */
130 itemsize = sizeof(short);
131 break;
132
133 case 'i': /* natural-size int */
134 itemsize = sizeof(int);
135 break;
136
137 case 'l': /* long int */
138 itemsize = sizeof(long);
139 break;
140
141 case 'f': /* float */
142 itemsize = sizeof(float);
143 break;
144
145 case 'd': /* double */
146 itemsize = sizeof(double);
147 break;
148
149 default:
Barry Warsaw30695fa1996-12-12 23:32:31 +0000150 PyErr_SetString(StructError, "bad char in fmt");
Guido van Rossum02975121992-08-17 08:55:12 +0000151 return -1;
152
153 }
154
155 x = num * itemsize;
156 size += x;
157 if (x/itemsize != num || size < 0) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000158 PyErr_SetString(StructError,
159 "total struct size too long");
Guido van Rossum02975121992-08-17 08:55:12 +0000160 return -1;
161 }
162
163 }
164
165 return size;
166}
167
168
169/* pack(fmt, v1, v2, ...) --> string */
170
Barry Warsaw30695fa1996-12-12 23:32:31 +0000171static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +0000172struct_calcsize(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +0000173 PyObject *self; /* Not used */
174 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +0000175{
176 char *fmt;
177 int size;
178
Barry Warsaw30695fa1996-12-12 23:32:31 +0000179 if (!PyArg_Parse(args, "s", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +0000180 return NULL;
181 size = calcsize(fmt);
182 if (size < 0)
183 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000184 return PyInt_FromLong((long)size);
Guido van Rossum02975121992-08-17 08:55:12 +0000185}
186
187
188/* pack(fmt, v1, v2, ...) --> string */
189
Barry Warsaw30695fa1996-12-12 23:32:31 +0000190static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +0000191struct_pack(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +0000192 PyObject *self; /* Not used */
193 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +0000194{
Barry Warsaw30695fa1996-12-12 23:32:31 +0000195 PyObject *format, *result, *v;
Guido van Rossum02975121992-08-17 08:55:12 +0000196 char *fmt;
197 int size, num;
198 int i, n;
199 char *s, *res, *restart;
200 char c;
201 long ival;
202 double fval;
203
Barry Warsaw30695fa1996-12-12 23:32:31 +0000204 if (args == NULL || !PyTuple_Check(args) ||
205 (n = PyTuple_Size(args)) < 1)
206 {
207 PyErr_BadArgument();
Guido van Rossum02975121992-08-17 08:55:12 +0000208 return NULL;
209 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000210 format = PyTuple_GetItem(args, 0);
211 if (!PyArg_Parse(format, "s", &fmt))
Guido van Rossum02975121992-08-17 08:55:12 +0000212 return NULL;
213 size = calcsize(fmt);
214 if (size < 0)
215 return NULL;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000216 result = PyString_FromStringAndSize((char *)NULL, size);
Guido van Rossum02975121992-08-17 08:55:12 +0000217 if (result == NULL)
218 return NULL;
219
220 s = fmt;
221 i = 1;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000222 res = restart = PyString_AsString(result);
Guido van Rossum02975121992-08-17 08:55:12 +0000223
224 while ((c = *s++) != '\0') {
225 if ('0' <= c && c <= '9') {
226 num = c - '0';
227 while ('0' <= (c = *s++) && c <= '9')
228 num = num*10 + (c - '0');
229 if (c == '\0')
230 break;
231 }
232 else
233 num = 1;
234
235 res = restart + align((int)(res-restart), c);
236
237 while (--num >= 0) {
238 switch (c) {
239
240 case 'x': /* pad byte */
241 *res++ = '\0';
242 break;
243
244 case 'l':
245 case 'i':
246 case 'h':
247 case 'b':
248 if (i >= n) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000249 PyErr_SetString(StructError,
250 "insufficient arguments to pack");
Guido van Rossum02975121992-08-17 08:55:12 +0000251 goto fail;
252 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000253 v = PyTuple_GetItem(args, i++);
254 if (!PyInt_Check(v)) {
255 PyErr_SetString(StructError,
256 "bad argument type to pack");
Guido van Rossum02975121992-08-17 08:55:12 +0000257 goto fail;
258 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000259 ival = PyInt_AsLong(v);
Guido van Rossum02975121992-08-17 08:55:12 +0000260 switch (c) {
261 case 'b':
262 *res++ = ival;
263 break;
264 case 'h':
265 *(short*)res = ival;
266 res += sizeof(short);
267 break;
268 case 'i':
269 *(int*)res = ival;
270 res += sizeof(int);
271 break;
272 case 'l':
273 *(long*)res = ival;
274 res += sizeof(long);
275 break;
276 }
277 break;
278
279 case 'c':
280 if (i >= n) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000281 PyErr_SetString(StructError,
282 "insufficient arguments to pack");
Guido van Rossum02975121992-08-17 08:55:12 +0000283 goto fail;
284 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000285 v = PyTuple_GetItem(args, i++);
286 if (!PyString_Check(v) ||
287 PyString_Size(v) != 1)
288 {
289 PyErr_SetString(StructError,
290 "bad argument type to pack");
Guido van Rossum02975121992-08-17 08:55:12 +0000291 goto fail;
292 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000293 *res++ = PyString_AsString(v)[0];
Guido van Rossum02975121992-08-17 08:55:12 +0000294 break;
295
296 case 'd':
297 case 'f':
298 if (i >= n) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000299 PyErr_SetString(StructError,
300 "insufficient arguments to pack");
Guido van Rossum02975121992-08-17 08:55:12 +0000301 goto fail;
302 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000303 v = PyTuple_GetItem(args, i++);
304 if (!PyFloat_Check(v)) {
305 PyErr_SetString(StructError,
306 "bad argument type to pack");
Guido van Rossum02975121992-08-17 08:55:12 +0000307 goto fail;
308 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000309 fval = PyFloat_AsDouble(v);
Guido van Rossum02975121992-08-17 08:55:12 +0000310 switch (c) {
311 case 'f':
312 *(float*)res = (float)fval;
313 res += sizeof(float);
314 break;
315 case 'd':
Guido van Rossum524b5881995-01-04 19:10:35 +0000316 memcpy(res, (char*)&fval, sizeof fval);
Guido van Rossum02975121992-08-17 08:55:12 +0000317 res += sizeof(double);
318 break;
319 }
320 break;
321
322 default:
Barry Warsaw30695fa1996-12-12 23:32:31 +0000323 PyErr_SetString(StructError,
324 "bad char in fmt");
Guido van Rossum02975121992-08-17 08:55:12 +0000325 goto fail;
326
327 }
328 }
329 }
330
331 if (i < n) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000332 PyErr_SetString(StructError,
333 "too many arguments for pack fmt");
Guido van Rossum02975121992-08-17 08:55:12 +0000334 goto fail;
335 }
336
337 return result;
338
339 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +0000340 Py_DECREF(result);
Guido van Rossum02975121992-08-17 08:55:12 +0000341 return NULL;
342}
343
344
Guido van Rossum90ddb7b1992-08-19 16:44:15 +0000345/* Helper to convert a list to a tuple */
346
Barry Warsaw30695fa1996-12-12 23:32:31 +0000347static PyObject *
Guido van Rossum90ddb7b1992-08-19 16:44:15 +0000348totuple(list)
Barry Warsaw30695fa1996-12-12 23:32:31 +0000349 PyObject *list;
Guido van Rossum90ddb7b1992-08-19 16:44:15 +0000350{
Barry Warsaw30695fa1996-12-12 23:32:31 +0000351 int len = PyList_Size(list);
352 PyObject *tuple = PyTuple_New(len);
Guido van Rossum90ddb7b1992-08-19 16:44:15 +0000353 if (tuple != NULL) {
354 int i;
355 for (i = 0; i < len; i++) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000356 PyObject *v = PyList_GetItem(list, i);
357 Py_INCREF(v);
358 PyTuple_SetItem(tuple, i, v);
Guido van Rossum90ddb7b1992-08-19 16:44:15 +0000359 }
360 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000361 Py_DECREF(list);
Guido van Rossum90ddb7b1992-08-19 16:44:15 +0000362 return tuple;
363}
364
365
Guido van Rossum02975121992-08-17 08:55:12 +0000366/* unpack(fmt, string) --> (v1, v2, ...) */
367
Barry Warsaw30695fa1996-12-12 23:32:31 +0000368static PyObject *
Guido van Rossum02975121992-08-17 08:55:12 +0000369struct_unpack(self, args)
Barry Warsaw30695fa1996-12-12 23:32:31 +0000370 PyObject *self; /* Not used */
371 PyObject *args;
Guido van Rossum02975121992-08-17 08:55:12 +0000372{
373 char *str, *start, *fmt, *s;
374 char c;
375 int len, size, num, x;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000376 PyObject *res, *v;
Guido van Rossum02975121992-08-17 08:55:12 +0000377
Barry Warsaw30695fa1996-12-12 23:32:31 +0000378 if (!PyArg_Parse(args, "(ss#)", &fmt, &start, &len))
Guido van Rossum02975121992-08-17 08:55:12 +0000379 return NULL;
380 size = calcsize(fmt);
381 if (size != len) {
Barry Warsaw30695fa1996-12-12 23:32:31 +0000382 PyErr_SetString(StructError,
383 "unpack str size does not match fmt");
Guido van Rossum02975121992-08-17 08:55:12 +0000384 return NULL;
385 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000386 res = PyList_New(0);
Guido van Rossum02975121992-08-17 08:55:12 +0000387 if (res == NULL)
388 return NULL;
389 str = start;
390 s = fmt;
391 while ((c = *s++) != '\0') {
392 if ('0' <= c && c <= '9') {
393 num = c - '0';
394 while ('0' <= (c = *s++) && c <= '9')
395 num = num*10 + (c - '0');
396 if (c == '\0')
397 break;
398 }
399 else
400 num = 1;
401
402 str = start + align((int)(str-start), c);
403
404 while (--num >= 0) {
405 switch (c) {
406
407 case 'x':
408 str++;
409 continue;
410
411 case 'b':
412 x = *str++;
413 if (x >= 128)
414 x -= 256;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000415 v = PyInt_FromLong((long)x);
Guido van Rossum02975121992-08-17 08:55:12 +0000416 break;
417
418 case 'c':
Barry Warsaw30695fa1996-12-12 23:32:31 +0000419 v = PyString_FromStringAndSize(str, 1);
Guido van Rossum02975121992-08-17 08:55:12 +0000420 str++;
421 break;
422
423 case 'h':
Barry Warsaw30695fa1996-12-12 23:32:31 +0000424 v = PyInt_FromLong((long)*(short*)str);
Guido van Rossum02975121992-08-17 08:55:12 +0000425 str += sizeof(short);
426 break;
427
428 case 'i':
Barry Warsaw30695fa1996-12-12 23:32:31 +0000429 v = PyInt_FromLong((long)*(int*)str);
Guido van Rossum02975121992-08-17 08:55:12 +0000430 str += sizeof(int);
431 break;
432
433 case 'l':
Barry Warsaw30695fa1996-12-12 23:32:31 +0000434 v = PyInt_FromLong(*(long*)str);
Guido van Rossum02975121992-08-17 08:55:12 +0000435 str += sizeof(long);
436 break;
437
438 case 'f':
Barry Warsaw30695fa1996-12-12 23:32:31 +0000439 v = PyFloat_FromDouble((double)*(float*)str);
Guido van Rossum02975121992-08-17 08:55:12 +0000440 str += sizeof(float);
441 break;
442
443 case 'd':
Guido van Rossum524b5881995-01-04 19:10:35 +0000444 {
445 double d;
446 memcpy((char *)&d, str, sizeof d);
Barry Warsaw30695fa1996-12-12 23:32:31 +0000447 v = PyFloat_FromDouble(d);
Guido van Rossum02975121992-08-17 08:55:12 +0000448 str += sizeof(double);
449 break;
Guido van Rossum524b5881995-01-04 19:10:35 +0000450 }
Guido van Rossum02975121992-08-17 08:55:12 +0000451
452 default:
Barry Warsaw30695fa1996-12-12 23:32:31 +0000453 PyErr_SetString(StructError,
454 "bad char in fmt");
Guido van Rossum02975121992-08-17 08:55:12 +0000455 goto fail;
456
457 }
Barry Warsaw30695fa1996-12-12 23:32:31 +0000458 if (v == NULL || PyList_Append(res, v) < 0)
Guido van Rossum02975121992-08-17 08:55:12 +0000459 goto fail;
Barry Warsaw30695fa1996-12-12 23:32:31 +0000460 Py_DECREF(v);
Guido van Rossum02975121992-08-17 08:55:12 +0000461 }
462 }
463
Guido van Rossum90ddb7b1992-08-19 16:44:15 +0000464 return totuple(res);
Guido van Rossum02975121992-08-17 08:55:12 +0000465
466 fail:
Barry Warsaw30695fa1996-12-12 23:32:31 +0000467 Py_DECREF(res);
Guido van Rossum02975121992-08-17 08:55:12 +0000468 return NULL;
469}
470
Guido van Rossum90ddb7b1992-08-19 16:44:15 +0000471
Guido van Rossum02975121992-08-17 08:55:12 +0000472/* List of functions */
473
Barry Warsaw30695fa1996-12-12 23:32:31 +0000474static PyMethodDef struct_methods[] = {
Guido van Rossum02975121992-08-17 08:55:12 +0000475 {"calcsize", struct_calcsize},
476 {"pack", struct_pack, 1/*varargs*/},
477 {"unpack", struct_unpack},
478 {NULL, NULL} /* sentinel */
479};
480
481
482/* Module initialization */
483
484void
485initstruct()
486{
Barry Warsaw30695fa1996-12-12 23:32:31 +0000487 PyObject *m, *d;
Guido van Rossum02975121992-08-17 08:55:12 +0000488
489 /* Create the module and add the functions */
Barry Warsaw30695fa1996-12-12 23:32:31 +0000490 m = Py_InitModule("struct", struct_methods);
Guido van Rossum02975121992-08-17 08:55:12 +0000491
492 /* Add some symbolic constants to the module */
Barry Warsaw30695fa1996-12-12 23:32:31 +0000493 d = PyModule_GetDict(m);
494 StructError = PyString_FromString("struct.error");
495 PyDict_SetItemString(d, "error", StructError);
Guido van Rossum02975121992-08-17 08:55:12 +0000496
497 /* Check for errors */
Barry Warsaw30695fa1996-12-12 23:32:31 +0000498 if (PyErr_Occurred())
499 Py_FatalError("can't initialize module struct");
Guido van Rossum02975121992-08-17 08:55:12 +0000500}