KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > python > modules > struct


1 /*
2  * Copyright 1999 Finn Bock.
3  *
4  * This program contains material copyrighted by:
5  * Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
6  * The Netherlands.
7  */

8
9 package org.python.modules;
10
11 import org.python.core.Py;
12 import org.python.core.PyException;
13 import org.python.core.PyFloat;
14 import org.python.core.PyInteger;
15 import org.python.core.PyList;
16 import org.python.core.PyLong;
17 import org.python.core.PyObject;
18 import org.python.core.PyString;
19 import org.python.core.PyTuple;
20 import org.python.core.__builtin__;
21
22 import java.math.BigInteger JavaDoc;
23
24 /**
25  * This module performs conversions between Python values and C
26  * structs represented as Python strings. It uses <i>format strings</i>
27  * (explained below) as compact descriptions of the lay-out of the C
28  * structs and the intended conversion to/from Python values.
29  *
30  * <P>
31  * The module defines the following exception and functions:
32  *
33  * <P>
34  * <dl><dt><b><tt>error</tt></b>
35  * <dd>
36  * Exception raised on various occasions; argument is a string
37  * describing what is wrong.
38  * </dl>
39  *
40  * <P>
41  * <dl><dt><b><tt>pack</tt></b> (<var>fmt, v1, v2, ...</var>)
42  * <dd>
43  * Return a string containing the values
44  * <tt><i>v1</i>, <i>v2</i>, ...</tt> packed according to the given
45  * format. The arguments must match the values required by the format
46  * exactly.
47  * </dl>
48  *
49  * <P>
50  * <dl><dt><b><tt>unpack</tt>></b> (<var>fmt, string</var>)
51  * <dd>
52  * Unpack the string (presumably packed by <tt>pack(<i>fmt</i>,
53  * ...)</tt>) according to the given format. The result is a
54  * tuple even if it contains exactly one item. The string must contain
55  * exactly the amount of data required by the format (i.e.
56  * <tt>len(<i>string</i>)</tt> must equal <tt>calcsize(<i>fmt</i>)</tt>).
57  * </dl>
58  *
59  * <P>
60  * <dl><dt><b><tt>calcsize</tt></b> (<var>fmt</var>)
61  * <dd>
62  * Return the size of the struct (and hence of the string)
63  * corresponding to the given format.
64  * </dl>
65  *
66  * <P>
67  * Format characters have the following meaning; the conversion between
68  * C and Python values should be obvious given their types:
69  *
70  * <P>
71  * <table border align=center>
72  * <tr><th><b>Format</b></th>
73  * <th align=left><b>C Type</b></th>
74  * <th align=left><b>Python</b></th>
75  * <tr><td align=center><samp>x</samp></td>
76  * <td>pad byte</td>
77  * <td>no value</td>
78  * <tr><td align=center><samp>c</samp></td>
79  * <td><tt>char</tt></td>
80  * <td>string of length 1</td>
81  * <tr><td align=center><samp>b</samp></td>
82  * <td><tt>signed char</tt></td>
83  * <td>integer</td>
84  * <tr><td align=center><samp>B</samp></td>
85  * <td><tt>unsigned char</tt></td>
86  * <td>integer</td>
87  * <tr><td align=center><samp>h</samp></td>
88  * <td><tt>short</tt></td>
89  * <td>integer</td>
90  * <tr><td align=center><samp>H</samp></td>
91  * <td><tt>unsigned short</tt></td>
92  * <td>integer</td>
93  * <tr><td align=center><samp>i</samp></td>
94  * <td><tt>int</tt></td>
95  * <td>integer</td>
96  * <tr><td align=center><samp>I</samp></td>
97  * <td><tt>unsigned int</tt></td>
98  * <td>integer</td>
99  * <tr><td align=center><samp>l</samp></td>
100  * <td><tt>long</tt></td>
101  * <td>integer</td>
102  * <tr><td align=center><samp>L</samp></td>
103  * <td><tt>unsigned long</tt></td>
104  * <td>integer</td>
105  * <tr><td align=center><samp>f</samp></td>
106  * <td><tt>float</tt></td>
107  * <td>float</td>
108  * <tr><td align=center><samp>d</samp></td>
109  * <td><tt>double</tt></td>
110  * <td>float</td>
111  * <tr><td align=center><samp>s</samp></td>
112  * <td><tt>char[]</tt></td>
113  * <td>string</td>
114  * <tr><td align=center><samp>p</samp></td>
115  * <td><tt>char[]</tt></td>
116  * <td>string</td>
117  * </table>
118  *
119  * <P>
120  * A format character may be preceded by an integral repeat count;
121  * e.g. the format string <tt>'4h'</tt> means exactly the same as
122  * <tt>'hhhh'</tt>.
123  *
124  * <P>
125  * Whitespace characters between formats are ignored; a count and its
126  * format must not contain whitespace though.
127  *
128  * <P>
129  * For the "<tt>s</tt>" format character, the count is interpreted as the
130  * size of the string, not a repeat count like for the other format
131  * characters; e.g. <tt>'10s'</tt> means a single 10-byte string, while
132  * <tt>'10c'</tt> means 10 characters. For packing, the string is
133  * truncated or padded with null bytes as appropriate to make it fit.
134  * For unpacking, the resulting string always has exactly the specified
135  * number of bytes. As a special case, <tt>'0s'</tt> means a single, empty
136  * string (while <tt>'0c'</tt> means 0 characters).
137  *
138  * <P>
139  * The "<tt>p</tt>" format character can be used to encode a Pascal
140  * string. The first byte is the length of the stored string, with the
141  * bytes of the string following. If count is given, it is used as the
142  * total number of bytes used, including the length byte. If the string
143  * passed in to <tt>pack()</tt> is too long, the stored representation
144  * is truncated. If the string is too short, padding is used to ensure
145  * that exactly enough bytes are used to satisfy the count.
146  *
147  * <P>
148  * For the "<tt>I</tt>" and "<tt>L</tt>" format characters, the return
149  * value is a Python long integer.
150  *
151  * <P>
152  * By default, C numbers are represented in the machine's native format
153  * and byte order, and properly aligned by skipping pad bytes if
154  * necessary (according to the rules used by the C compiler).
155  *
156  * <P>
157  * Alternatively, the first character of the format string can be used to
158  * indicate the byte order, size and alignment of the packed data,
159  * according to the following table:
160  *
161  * <P>
162  * <table border align=center>
163  *
164  * <tr><th><b>Character</b></th>
165  * <th align=left><b>Byte order</b></th>
166  * <th align=left><b>Size and alignment</b></th>
167  * <tr><td align=center><samp>@</samp></td>
168  * <td>native</td>
169  * <td>native</td>
170  * <tr><td align=center><samp>=</samp></td>
171  * <td>native</td>
172  * <td>standard</td>
173  * <tr><td align=center><samp>&lt;</samp></td>
174  * <td>little-endian</td>
175  * <td>standard</td>
176  * <tr><td align=center><samp>&gt;</samp></td>
177  * <td>big-endian</td>
178  * <td>standard</td>
179  * <tr><td align=center><samp>!</samp></td>
180  * <td>network (= big-endian)</td>
181  * <td>standard</td>
182  *
183  * </table>
184  *
185  * <P>
186  * If the first character is not one of these, "<tt>@</tt>" is assumed.
187  *
188  * <P>
189  * Native byte order is big-endian or little-endian, depending on the
190  * host system (e.g. Motorola and Sun are big-endian; Intel and DEC are
191  * little-endian).
192  *
193  * <P>
194  * Native size and alignment are defined as follows: <tt>short</tt> is
195  * 2 bytes; <tt>int</tt> and <tt>long</tt> are 4 bytes; <tt>float</tt>
196  * are 4 bytes and <tt>double</tt> are 8 bytes. Native byte order is
197  * chosen as big-endian.
198  *
199  * <P>
200  * Standard size and alignment are as follows: no alignment is required
201  * for any type (so you have to use pad bytes); <tt>short</tt> is 2 bytes;
202  * <tt>int</tt> and <tt>long</tt> are 4 bytes. <tt>float</tt> and
203  * <tt>double</tt> are 32-bit and 64-bit IEEE floating point numbers,
204  * respectively.
205  *
206  * <P>
207  * Note the difference between "<tt>@</tt>" and "<tt>=</tt>": both use
208  * native byte order, but the size and alignment of the latter is
209  * standardized.
210  *
211  * <P>
212  * The form "<tt>!</tt>" is available for those poor souls who claim they
213  * can't remember whether network byte order is big-endian or
214  * little-endian.
215  *
216  * <P>
217  * There is no way to indicate non-native byte order (i.e. force
218  * byte-swapping); use the appropriate choice of "<tt>&lt;</tt>" or
219  * "<tt>&gt;</tt>".
220  *
221  * <P>
222  * Examples (all using native byte order, size and alignment, on a
223  * big-endian machine):
224  *
225  * <P>
226  * <dl><dd><pre>
227  * &gt;&gt;&gt; from struct import *
228  * &gt;&gt;&gt; pack('hhl', 1, 2, 3)
229  * '\000\001\000\002\000\000\000\003'
230  * &gt;&gt;&gt; unpack('hhl', '\000\001\000\002\000\000\000\003')
231  * (1, 2, 3)
232  * &gt;&gt;&gt; calcsize('hhl')
233  * 8
234  * &gt;&gt;&gt;
235  * </pre></dl>
236  *
237  * <P>
238  * Hint: to align the end of a structure to the alignment requirement of
239  * a particular type, end the format with the code for that type with a
240  * repeat count of zero, e.g. the format <tt>'llh0l'</tt> specifies two
241  * pad bytes at the end, assuming longs are aligned on 4-byte boundaries.
242  * This only works when native size and alignment are in effect;
243  * standard size and alignment does not enforce any alignment.
244  *
245  * For the complete documentation on the struct module, please see the
246  * "Python Library Reference"
247  * <p><hr><p>
248  *
249  * The module is based on the original structmodule.c except that all
250  * mistakes and errors are my own. Original author unknown.
251  * <p>
252  * @author Finn Bock, bckfnn@pipmail.dknet.dk
253  * @version struct.java,v 1.6 1999/04/17 12:04:34 fb Exp
254  */

255 public class struct {
256
257     /**
258      * Exception raised on various occasions; argument is a
259      * string describing what is wrong.
260      */

261     public static PyString error = new PyString("struct.error");
262
263     public static String JavaDoc __doc__ =
264         "Functions to convert between Python values and C structs.\n" +
265         "Python strings are used to hold the data representing the C\n" +
266         "struct and also as format strings to describe the layout of\n" +
267         "data in the C struct.\n" +
268         "\n" +
269         "The optional first format char indicates byte ordering and\n" +
270         "alignment:\n" +
271         " @: native w/native alignment(default)\n" +
272         " =: native w/standard alignment\n" +
273         " <: little-endian, std. alignment\n" +
274         " >: big-endian, std. alignment\n" +
275         " !: network, std (same as >)\n" +
276         "\n" +
277         "The remaining chars indicate types of args and must match\n" +
278         "exactly; these can be preceded by a decimal repeat count:\n" +
279         " x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n" +
280         " h:short; H:unsigned short; i:int; I:unsigned int;\n" +
281         " l:long; L:unsigned long; f:float; d:double.\n" +
282         "Special cases (preceding decimal count indicates length):\n" +
283         " s:string (array of char); p: pascal string (w. count byte).\n" +
284         "Whitespace between formats is ignored.\n" +
285         "\n" +
286         "The variable struct.error is an exception raised on errors.";
287
288
289     static class FormatDef {
290         char name;
291         int size;
292         int alignment;
293
294         FormatDef init(char name, int size, int alignment) {
295             this.name = name;
296             this.size = size;
297             this.alignment = alignment;
298             return this;
299         }
300
301         void pack(ByteStream buf, PyObject value) {}
302
303         Object JavaDoc unpack(ByteStream buf) {
304             return null;
305         }
306
307         int doPack(ByteStream buf, int count, int pos, PyObject[] args) {
308             if (pos + count > args.length)
309                 throw StructError("insufficient arguments to pack");
310
311             int cnt = count;
312             while (count-- > 0)
313                 pack(buf, args[pos++]);
314             return cnt;
315         }
316
317         void doUnpack(ByteStream buf, int count, PyList list) {
318             while (count-- > 0)
319                 list.append(Py.java2py(unpack(buf)));
320         }
321
322
323         int get_int(PyObject value) {
324             try {
325                 return ((PyInteger)value.__int__()).getValue();
326             } catch (PyException ex) {
327                 throw StructError("required argument is not an integer");
328             }
329         }
330
331         long get_long(PyObject value) {
332             if (value instanceof PyLong){
333                 Object JavaDoc v = value.__tojava__(Long.TYPE);
334                 if (v == Py.NoConversion)
335                 throw Py.OverflowError("long int too long to convert");
336                 return ((Long JavaDoc) v).longValue();
337             } else
338                 return get_int(value);
339         }
340
341         BigInteger JavaDoc get_ulong(PyObject value) {
342             if (value instanceof PyLong){
343                 BigInteger JavaDoc v = (BigInteger JavaDoc)value.__tojava__(BigInteger JavaDoc.class);
344                 if (v.compareTo(PyLong.maxULong) > 0){
345                     throw Py.OverflowError("unsigned long int too long to convert");
346                 }
347                 return v;
348             } else
349                 return BigInteger.valueOf(get_int(value));
350         }
351
352         double get_float(PyObject value) {
353             if (!(value instanceof PyFloat))
354                 throw StructError("required argument is not an float");
355             return value.__float__().getValue();
356         }
357
358
359         void BEwriteInt(ByteStream buf, int v) {
360             buf.writeByte((int)(v >>> 24) & 0xFF);
361             buf.writeByte((int)(v >>> 16) & 0xFF);
362             buf.writeByte((int)(v >>> 8) & 0xFF);
363             buf.writeByte((int)(v >>> 0) & 0xFF);
364         }
365
366         void LEwriteInt(ByteStream buf, int v) {
367             buf.writeByte((int)(v >>> 0) & 0xFF);
368             buf.writeByte((int)(v >>> 8) & 0xFF);
369             buf.writeByte((int)(v >>> 16) & 0xFF);
370             buf.writeByte((int)(v >>> 24) & 0xFF);
371         }
372
373         int BEreadInt(ByteStream buf) {
374             int b1 = buf.readByte();
375             int b2 = buf.readByte();
376             int b3 = buf.readByte();
377             int b4 = buf.readByte();
378             return ((b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0));
379         }
380
381         int LEreadInt(ByteStream buf) {
382             int b1 = buf.readByte();
383             int b2 = buf.readByte();
384             int b3 = buf.readByte();
385             int b4 = buf.readByte();
386             return ((b1 << 0) + (b2 << 8) + (b3 << 16) + (b4 << 24));
387         }
388     }
389
390
391     static class ByteStream {
392         char[] data;
393         int len;
394         int pos;
395
396         ByteStream() {
397             data = new char[10];
398             len = 0;
399             pos = 0;
400         }
401
402         ByteStream(String JavaDoc s) {
403             int l = s.length();
404             data = new char[l];
405             s.getChars(0, l, data, 0);
406             len = l;
407             pos = 0;
408         }
409
410         int readByte() {
411             return data[pos++] & 0xFF;
412         }
413
414         void read(char[] buf, int pos, int len) {
415             System.arraycopy(data, this.pos, buf, pos, len);
416             this.pos += len;
417         }
418
419
420         String JavaDoc readString(int l) {
421             char[] data = new char[l];
422             read(data, 0, l);
423             return new String JavaDoc(data);
424         }
425
426
427         private void ensureCapacity(int l) {
428             if (pos + l >= data.length) {
429                 char[] b = new char[(pos + l) * 2];
430                 System.arraycopy(data, 0, b, 0, pos);
431                 data = b;
432             }
433         }
434
435
436         void writeByte(int b) {
437             ensureCapacity(1);
438             data[pos++] = (char)(b & 0xFF);
439         }
440
441
442         void write(char[] buf, int pos, int len) {
443             ensureCapacity(len);
444             System.arraycopy(buf, pos, data, this.pos, len);
445             this.pos += len;
446         }
447
448         void writeString(String JavaDoc s, int pos, int len) {
449             char[] data = new char[len];
450             s.getChars(pos, len, data, 0);
451             write(data, 0, len);
452         }
453
454
455         int skip(int l) {
456             pos += l;
457             return pos;
458         }
459
460         int size() {
461             return pos;
462         }
463
464         public String JavaDoc toString() {
465             return new String JavaDoc(data, 0, pos);
466         }
467     }
468
469
470     static class PadFormatDef extends FormatDef {
471         int doPack(ByteStream buf, int count, int pos, PyObject[] args) {
472             while (count-- > 0)
473                 buf.writeByte(0);
474             return 0;
475         }
476
477         void doUnpack(ByteStream buf, int count, PyList list) {
478             while (count-- > 0)
479                 buf.readByte();
480         }
481     }
482
483
484     static class StringFormatDef extends FormatDef {
485         int doPack(ByteStream buf, int count, int pos, PyObject[] args) {
486             PyObject value = args[pos];
487
488             if (!(value instanceof PyString))
489                 throw StructError("argument for 's' must be a string");
490
491             String JavaDoc s = value.toString();
492             int len = s.length();
493             buf.writeString(s, 0, Math.min(count, len));
494             if (len < count) {
495                 count -= len;
496                 for (int i = 0; i < count; i++)
497                     buf.writeByte(0);
498             }
499             return 1;
500         }
501
502         void doUnpack(ByteStream buf, int count, PyList list) {
503             list.append(Py.newString(buf.readString(count)));
504         }
505     }
506
507
508     static class PascalStringFormatDef extends StringFormatDef {
509         int doPack(ByteStream buf, int count, int pos, PyObject[] args) {
510             PyObject value = args[pos];
511
512             if (!(value instanceof PyString))
513                 throw StructError("argument for 'p' must be a string");
514
515             buf.writeByte(Math.min(0xFF, Math.min(value.toString().length(), count-1)));
516             return super.doPack(buf, count-1, pos, args);
517         }
518
519         void doUnpack(ByteStream buf, int count, PyList list) {
520             int n = buf.readByte();
521             if (n >= count)
522                 n = count-1;
523             super.doUnpack(buf, n, list);
524             buf.skip(Math.max(count-n-1, 0));
525         }
526     }
527
528
529     static class CharFormatDef extends FormatDef {
530         void pack(ByteStream buf, PyObject value) {
531             if (!(value instanceof PyString) || value.__len__() != 1)
532                 throw StructError("char format require string of length 1");
533             buf.writeByte(value.toString().charAt(0));
534         }
535
536         Object JavaDoc unpack(ByteStream buf) {
537             return Py.newString((char)buf.readByte());
538         }
539     }
540
541
542     static class ByteFormatDef extends FormatDef {
543         void pack(ByteStream buf, PyObject value) {
544             buf.writeByte(get_int(value));
545         }
546
547         Object JavaDoc unpack(ByteStream buf) {
548             int b = buf.readByte();
549             if (b > Byte.MAX_VALUE)
550                 b -= 0x100;
551             return Py.newInteger(b);
552         }
553     }
554
555     static class UnsignedByteFormatDef extends ByteFormatDef {
556         Object JavaDoc unpack(ByteStream buf) {
557             return Py.newInteger(buf.readByte());
558         }
559     }
560
561     static class LEShortFormatDef extends FormatDef {
562         void pack(ByteStream buf, PyObject value) {
563             int v = get_int(value);
564             buf.writeByte(v & 0xFF);
565             buf.writeByte((v >> 8) & 0xFF);
566         }
567
568         Object JavaDoc unpack(ByteStream buf) {
569             int v = buf.readByte() |
570                    (buf.readByte() << 8);
571             if (v > Short.MAX_VALUE)
572                 v -= 0x10000 ;
573             return Py.newInteger(v);
574         }
575     }
576
577     static class LEUnsignedShortFormatDef extends LEShortFormatDef {
578         Object JavaDoc unpack(ByteStream buf) {
579             int v = buf.readByte() |
580                    (buf.readByte() << 8);
581             return Py.newInteger(v);
582         }
583     }
584
585
586     static class BEShortFormatDef extends FormatDef {
587         void pack(ByteStream buf, PyObject value) {
588             int v = get_int(value);
589             buf.writeByte((v >> 8) & 0xFF);
590             buf.writeByte(v & 0xFF);
591         }
592
593         Object JavaDoc unpack(ByteStream buf) {
594             int v = (buf.readByte() << 8) |
595                      buf.readByte();
596             if (v > Short.MAX_VALUE)
597                 v -= 0x10000;
598             return Py.newInteger(v);
599         }
600     }
601
602
603     static class BEUnsignedShortFormatDef extends BEShortFormatDef {
604         Object JavaDoc unpack(ByteStream buf) {
605             int v = (buf.readByte() << 8) |
606                      buf.readByte();
607             return Py.newInteger(v);
608         }
609     }
610
611
612     static class LEIntFormatDef extends FormatDef {
613         void pack(ByteStream buf, PyObject value) {
614             LEwriteInt(buf, get_int(value));
615         }
616
617         Object JavaDoc unpack(ByteStream buf) {
618             int v = LEreadInt(buf);
619             return Py.newInteger(v);
620         }
621     }
622
623
624     static class LEUnsignedIntFormatDef extends FormatDef {
625         void pack(ByteStream buf, PyObject value) {
626             LEwriteInt(buf, (int)(get_long(value) & 0xFFFFFFFF));
627         }
628
629         Object JavaDoc unpack(ByteStream buf) {
630             long v = LEreadInt(buf);
631             if (v < 0)
632                 v += 0x100000000L;
633             return new PyLong(v);
634         }
635     }
636
637
638     static class BEIntFormatDef extends FormatDef {
639         void pack(ByteStream buf, PyObject value) {
640             BEwriteInt(buf, get_int(value));
641         }
642
643         Object JavaDoc unpack(ByteStream buf) {
644             return Py.newInteger(BEreadInt(buf));
645         }
646     }
647
648
649     static class BEUnsignedIntFormatDef extends FormatDef {
650         void pack(ByteStream buf, PyObject value) {
651             BEwriteInt(buf, (int)(get_long(value) & 0xFFFFFFFF));
652         }
653         Object JavaDoc unpack(ByteStream buf) {
654             long v = BEreadInt(buf);
655             if (v < 0)
656                 v += 0x100000000L;
657             return new PyLong(v);
658         }
659     }
660
661     static class LEUnsignedLongFormatDef extends FormatDef {
662         void pack(ByteStream buf, PyObject value) {
663             BigInteger JavaDoc bi = get_ulong(value);
664             if (bi.compareTo(BigInteger.valueOf(0)) < 0) {
665                 throw StructError("can't convert negative long to unsigned");
666             }
667             long lvalue = bi.longValue(); // underflow is OK -- the bits are correct
668
int high = (int) ( (lvalue & 0xFFFFFFFF00000000L)>>32 );
669             int low = (int) ( lvalue & 0x00000000FFFFFFFFL );
670             LEwriteInt( buf, low );
671             LEwriteInt( buf, high );
672         }
673
674         Object JavaDoc unpack(ByteStream buf) {
675             long low = ( LEreadInt( buf ) & 0X00000000FFFFFFFFL );
676             long high = ( LEreadInt( buf ) & 0X00000000FFFFFFFFL );
677                 java.math.BigInteger JavaDoc result=java.math.BigInteger.valueOf(high);
678             result=result.multiply(java.math.BigInteger.valueOf(0x100000000L));
679             result=result.add(java.math.BigInteger.valueOf(low));
680             return new PyLong(result);
681         }
682     }
683
684
685     static class BEUnsignedLongFormatDef extends FormatDef {
686         void pack(ByteStream buf, PyObject value) {
687             BigInteger JavaDoc bi = get_ulong(value);
688             if (bi.compareTo(BigInteger.valueOf(0)) < 0) {
689                 throw StructError("can't convert negative long to unsigned");
690             }
691             long lvalue = bi.longValue(); // underflow is OK -- the bits are correct
692
int high = (int) ( (lvalue & 0xFFFFFFFF00000000L)>>32 );
693             int low = (int) ( lvalue & 0x00000000FFFFFFFFL );
694             BEwriteInt( buf, high );
695             BEwriteInt( buf, low );
696         }
697
698         Object JavaDoc unpack(ByteStream buf) {
699             long high = ( BEreadInt( buf ) & 0X00000000FFFFFFFFL );
700             long low = ( BEreadInt( buf ) & 0X00000000FFFFFFFFL );
701             java.math.BigInteger JavaDoc result=java.math.BigInteger.valueOf(high);
702             result=result.multiply(java.math.BigInteger.valueOf(0x100000000L));
703             result=result.add(java.math.BigInteger.valueOf(low));
704             return new PyLong(result);
705         }
706     }
707
708
709     static class LELongFormatDef extends FormatDef {
710         void pack(ByteStream buf, PyObject value) {
711             long lvalue = get_long( value );
712             int high = (int) ( (lvalue & 0xFFFFFFFF00000000L)>>32 );
713             int low = (int) ( lvalue & 0x00000000FFFFFFFFL );
714             LEwriteInt( buf, low );
715             LEwriteInt( buf, high );
716         }
717
718         Object JavaDoc unpack(ByteStream buf) {
719             long low = LEreadInt(buf) & 0x00000000FFFFFFFFL;
720             long high = ((long)(LEreadInt(buf))<<32) & 0xFFFFFFFF00000000L;
721             long result=(high|low);
722             return new PyLong(result);
723         }
724     }
725
726
727     static class BELongFormatDef extends FormatDef {
728         void pack(ByteStream buf, PyObject value) {
729             long lvalue = get_long( value );
730             int high = (int) ( (lvalue & 0xFFFFFFFF00000000L)>>32 );
731             int low = (int) ( lvalue & 0x00000000FFFFFFFFL );
732             BEwriteInt( buf, high );
733             BEwriteInt( buf, low );
734         }
735
736         Object JavaDoc unpack(ByteStream buf) {
737             long high = ((long)(BEreadInt(buf))<<32) & 0xFFFFFFFF00000000L;
738             long low = BEreadInt(buf) & 0x00000000FFFFFFFFL;
739             long result=(high|low);
740             return new PyLong(result);
741         }
742     }
743
744
745     static class LEFloatFormatDef extends FormatDef {
746         void pack(ByteStream buf, PyObject value) {
747             int bits = Float.floatToIntBits((float)get_float(value));
748             LEwriteInt(buf, bits);
749         }
750
751         Object JavaDoc unpack(ByteStream buf) {
752             int v = LEreadInt(buf);
753             return Py.newFloat(Float.intBitsToFloat(v));
754         }
755     }
756
757     static class LEDoubleFormatDef extends FormatDef {
758         void pack(ByteStream buf, PyObject value) {
759             long bits = Double.doubleToLongBits(get_float(value));
760             LEwriteInt(buf, (int)(bits & 0xFFFFFFFF));
761             LEwriteInt(buf, (int)(bits >>> 32));
762         }
763
764         Object JavaDoc unpack(ByteStream buf) {
765             long bits = (LEreadInt(buf) & 0xFFFFFFFFL) +
766                         (((long)LEreadInt(buf)) << 32);
767             return Py.newFloat(Double.longBitsToDouble(bits));
768         }
769     }
770
771
772     static class BEFloatFormatDef extends FormatDef {
773         void pack(ByteStream buf, PyObject value) {
774             int bits = Float.floatToIntBits((float)get_float(value));
775             BEwriteInt(buf, bits);
776         }
777
778         Object JavaDoc unpack(ByteStream buf) {
779             int v = BEreadInt(buf);
780             return Py.newFloat(Float.intBitsToFloat(v));
781         }
782     }
783
784     static class BEDoubleFormatDef extends FormatDef {
785         void pack(ByteStream buf, PyObject value) {
786             long bits = Double.doubleToLongBits(get_float(value));
787             BEwriteInt(buf, (int)(bits >>> 32));
788             BEwriteInt(buf, (int)(bits & 0xFFFFFFFF));
789         }
790
791         Object JavaDoc unpack(ByteStream buf) {
792             long bits = (((long)BEreadInt(buf)) << 32) +
793                         (BEreadInt(buf) & 0xFFFFFFFFL);
794             return Py.newFloat(Double.longBitsToDouble(bits));
795         }
796     }
797
798
799     private static FormatDef[] lilendian_table = {
800         new PadFormatDef() .init('x', 1, 0),
801         new ByteFormatDef() .init('b', 1, 0),
802         new UnsignedByteFormatDef() .init('B', 1, 0),
803         new CharFormatDef() .init('c', 1, 0),
804         new StringFormatDef() .init('s', 1, 0),
805         new PascalStringFormatDef() .init('p', 1, 0),
806         new LEShortFormatDef() .init('h', 2, 0),
807         new LEUnsignedShortFormatDef() .init('H', 2, 0),
808         new LEIntFormatDef() .init('i', 4, 0),
809         new LEUnsignedIntFormatDef() .init('I', 4, 0),
810         new LEIntFormatDef() .init('l', 4, 0),
811         new LEUnsignedIntFormatDef() .init('L', 4, 0),
812         new LELongFormatDef() .init('q', 8, 8),
813         new LEUnsignedLongFormatDef() .init('Q', 8, 8),
814         new LEFloatFormatDef() .init('f', 4, 0),
815         new LEDoubleFormatDef() .init('d', 8, 0),
816     };
817
818     private static FormatDef[] bigendian_table = {
819         new PadFormatDef() .init('x', 1, 0),
820         new ByteFormatDef() .init('b', 1, 0),
821         new UnsignedByteFormatDef() .init('B', 1, 0),
822         new CharFormatDef() .init('c', 1, 0),
823         new StringFormatDef() .init('s', 1, 0),
824         new PascalStringFormatDef() .init('p', 1, 0),
825         new BEShortFormatDef() .init('h', 2, 0),
826         new BEUnsignedShortFormatDef() .init('H', 2, 0),
827         new BEIntFormatDef() .init('i', 4, 0),
828         new BEUnsignedIntFormatDef() .init('I', 4, 0),
829         new BEIntFormatDef() .init('l', 4, 0),
830         new BEUnsignedIntFormatDef() .init('L', 4, 0),
831         new BELongFormatDef() .init('q', 8, 8),
832         new BEUnsignedLongFormatDef() .init('Q', 8, 8),
833         new BEFloatFormatDef() .init('f', 4, 0),
834         new BEDoubleFormatDef() .init('d', 8, 0),
835     };
836
837     private static FormatDef[] native_table = {
838         new PadFormatDef() .init('x', 1, 0),
839         new ByteFormatDef() .init('b', 1, 0),
840         new UnsignedByteFormatDef() .init('B', 1, 0),
841         new CharFormatDef() .init('c', 1, 0),
842         new StringFormatDef() .init('s', 1, 0),
843         new PascalStringFormatDef() .init('p', 1, 0),
844         new BEShortFormatDef() .init('h', 2, 2),
845         new BEUnsignedShortFormatDef() .init('H', 2, 2),
846         new BEIntFormatDef() .init('i', 4, 4),
847         new BEUnsignedIntFormatDef() .init('I', 4, 4),
848         new BEIntFormatDef() .init('l', 4, 4),
849         new BEUnsignedIntFormatDef() .init('L', 4, 4),
850         new BELongFormatDef() .init('q', 8, 8),
851         new BEUnsignedLongFormatDef() .init('Q', 8, 8),
852         new BEFloatFormatDef() .init('f', 4, 4),
853         new BEDoubleFormatDef() .init('d', 8, 8),
854     };
855
856
857
858     private static FormatDef[] whichtable(String JavaDoc pfmt) {
859         char c = pfmt.charAt(0);
860         switch (c) {
861         case '<' :
862             return lilendian_table;
863         case '>':
864         case '!':
865             // Network byte order is big-endian
866
return bigendian_table;
867         case '=':
868             return bigendian_table;
869         case '@':
870         default:
871             return native_table;
872         }
873     }
874
875
876     private static FormatDef getentry(char c, FormatDef[] f) {
877         for (int i = 0; i < f.length; i++) {
878             if (f[i].name == c)
879                 return f[i];
880         }
881         throw StructError("bad char in struct format");
882     }
883
884
885
886     private static int align(int size, FormatDef e) {
887         if (e.alignment != 0) {
888             size = ((size + e.alignment - 1)
889                                 / e.alignment)
890                                 * e.alignment;
891         }
892         return size;
893     }
894
895
896
897     private static int calcsize(String JavaDoc format, FormatDef[] f) {
898         int size = 0;
899
900         int len = format.length();
901         for (int j = 0; j < len; j++) {
902             char c = format.charAt(j);
903             if (j == 0 && (c=='@' || c=='<' || c=='>' || c=='=' || c=='!'))
904                 continue;
905             if (Character.isWhitespace(c))
906                 continue;
907             int num = 1;
908             if (Character.isDigit(c)) {
909                 num = Character.digit(c, 10);
910                 while (++j < len &&
911                           Character.isDigit((c = format.charAt(j)))) {
912                     int x = num*10 + Character.digit(c, 10);
913                     if (x/10 != num)
914                         throw StructError("overflow in item count");
915                     num = x;
916                 }
917                 if (j >= len)
918                     break;
919             }
920
921             FormatDef e = getentry(c, f);
922
923             int itemsize = e.size;
924             size = align(size, e);
925             int x = num * itemsize;
926             size += x;
927             if (x/itemsize != num || size < 0)
928                 throw StructError("total struct size too long");
929         }
930         return size;
931     }
932
933
934     /**
935      * Return the size of the struct (and hence of the string)
936      * corresponding to the given format.
937      */

938     static public int calcsize(String JavaDoc format) {
939         FormatDef[] f = whichtable(format);
940         return calcsize(format, f);
941     }
942
943
944     /**
945      * Return a string containing the values v1, v2, ... packed according
946      * to the given format. The arguments must match the
947      * values required by the format exactly.
948      */

949     static public String JavaDoc pack(PyObject[] args) {
950         if (args.length < 1)
951             Py.TypeError("illegal argument type for built-in operation");
952
953         String JavaDoc format = args[0].toString();
954
955         FormatDef[] f = whichtable(format);
956         int size = calcsize(format, f);
957
958         ByteStream res = new ByteStream();
959
960         int i = 1;
961         int len = format.length();
962         for (int j = 0; j < len; j++) {
963             char c = format.charAt(j);
964             if (j == 0 && (c=='@' || c=='<' || c=='>' || c=='=' || c=='!'))
965                 continue;
966             if (Character.isWhitespace(c))
967                 continue;
968             int num = 1;
969             if (Character.isDigit(c)) {
970                 num = Character.digit(c, 10);
971                 while (++j < len && Character.isDigit((c = format.charAt(j))))
972                     num = num*10 + Character.digit(c, 10);
973                 if (j >= len)
974                     break;
975             }
976
977             FormatDef e = getentry(c, f);
978
979             // Fill padd bytes with zeros
980
int nres = align(res.size(), e) - res.size();
981             while (nres-- > 0)
982                 res.writeByte(0);
983             i += e.doPack(res, num, i, args);
984         }
985
986         if (i < args.length)
987             throw StructError("too many arguments for pack format");
988
989         return res.toString();
990     }
991
992
993
994     /**
995      * Unpack the string (presumably packed by pack(fmt, ...)) according
996      * to the given format. The result is a tuple even if it contains
997      * exactly one item.
998      * The string must contain exactly the amount of data required by
999      * the format (i.e. len(string) must equal calcsize(fmt)).
1000     */

1001    public static PyTuple unpack(String JavaDoc format, String JavaDoc string) {
1002        int len = string.length();
1003
1004        FormatDef[] f = whichtable(format);
1005        int size = calcsize(format, f);
1006
1007        if (size != len)
1008            throw StructError("unpack str size does not match format");
1009
1010        PyList res = new PyList();
1011
1012        ByteStream str = new ByteStream(string);
1013
1014        int flen = format.length();
1015        for (int j = 0; j < flen; j++) {
1016            char c = format.charAt(j);
1017            if (j == 0 && (c=='@' || c=='<' || c=='>' || c=='=' || c=='!'))
1018                continue;
1019            if (Character.isWhitespace(c))
1020                continue;
1021            int num = 1;
1022            if (Character.isDigit(c)) {
1023                num = Character.digit(c, 10);
1024                while (++j < flen &&
1025                           Character.isDigit((c = format.charAt(j))))
1026                    num = num*10 + Character.digit(c, 10);
1027                if (j > flen)
1028                    break;
1029            }
1030
1031            FormatDef e = getentry(c, f);
1032
1033            str.skip(align(str.size(), e) - str.size());
1034
1035            e.doUnpack(str, num, res);
1036        }
1037        return __builtin__.tuple(res);
1038    }
1039
1040
1041
1042    private static PyException StructError(String JavaDoc explanation) {
1043        return new PyException(error, explanation);
1044    }
1045}
1046
Popular Tags