0001: /*
0002: * Copyright 1999 Finn Bock.
0003: *
0004: * This program contains material copyrighted by:
0005: * Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
0006: * The Netherlands.
0007: */
0008:
0009: package org.python.modules;
0010:
0011: import org.python.core.Py;
0012: import org.python.core.PyException;
0013: import org.python.core.PyFloat;
0014: import org.python.core.PyInteger;
0015: import org.python.core.PyList;
0016: import org.python.core.PyLong;
0017: import org.python.core.PyObject;
0018: import org.python.core.PyString;
0019: import org.python.core.PyTuple;
0020: import org.python.core.__builtin__;
0021:
0022: import java.math.BigInteger;
0023:
0024: /**
0025: * This module performs conversions between Python values and C
0026: * structs represented as Python strings. It uses <i>format strings</i>
0027: * (explained below) as compact descriptions of the lay-out of the C
0028: * structs and the intended conversion to/from Python values.
0029: *
0030: * <P>
0031: * The module defines the following exception and functions:
0032: *
0033: * <P>
0034: * <dl><dt><b><tt>error</tt></b>
0035: * <dd>
0036: * Exception raised on various occasions; argument is a string
0037: * describing what is wrong.
0038: * </dl>
0039: *
0040: * <P>
0041: * <dl><dt><b><tt>pack</tt></b> (<var>fmt, v1, v2, ...</var>)
0042: * <dd>
0043: * Return a string containing the values
0044: * <tt><i>v1</i>, <i>v2</i>, ...</tt> packed according to the given
0045: * format. The arguments must match the values required by the format
0046: * exactly.
0047: * </dl>
0048: *
0049: * <P>
0050: * <dl><dt><b><tt>unpack</tt>></b> (<var>fmt, string</var>)
0051: * <dd>
0052: * Unpack the string (presumably packed by <tt>pack(<i>fmt</i>,
0053: * ...)</tt>) according to the given format. The result is a
0054: * tuple even if it contains exactly one item. The string must contain
0055: * exactly the amount of data required by the format (i.e.
0056: * <tt>len(<i>string</i>)</tt> must equal <tt>calcsize(<i>fmt</i>)</tt>).
0057: * </dl>
0058: *
0059: * <P>
0060: * <dl><dt><b><tt>calcsize</tt></b> (<var>fmt</var>)
0061: * <dd>
0062: * Return the size of the struct (and hence of the string)
0063: * corresponding to the given format.
0064: * </dl>
0065: *
0066: * <P>
0067: * Format characters have the following meaning; the conversion between
0068: * C and Python values should be obvious given their types:
0069: *
0070: * <P>
0071: * <table border align=center>
0072: * <tr><th><b>Format</b></th>
0073: * <th align=left><b>C Type</b></th>
0074: * <th align=left><b>Python</b></th>
0075: * <tr><td align=center><samp>x</samp></td>
0076: * <td>pad byte</td>
0077: * <td>no value</td>
0078: * <tr><td align=center><samp>c</samp></td>
0079: * <td><tt>char</tt></td>
0080: * <td>string of length 1</td>
0081: * <tr><td align=center><samp>b</samp></td>
0082: * <td><tt>signed char</tt></td>
0083: * <td>integer</td>
0084: * <tr><td align=center><samp>B</samp></td>
0085: * <td><tt>unsigned char</tt></td>
0086: * <td>integer</td>
0087: * <tr><td align=center><samp>h</samp></td>
0088: * <td><tt>short</tt></td>
0089: * <td>integer</td>
0090: * <tr><td align=center><samp>H</samp></td>
0091: * <td><tt>unsigned short</tt></td>
0092: * <td>integer</td>
0093: * <tr><td align=center><samp>i</samp></td>
0094: * <td><tt>int</tt></td>
0095: * <td>integer</td>
0096: * <tr><td align=center><samp>I</samp></td>
0097: * <td><tt>unsigned int</tt></td>
0098: * <td>integer</td>
0099: * <tr><td align=center><samp>l</samp></td>
0100: * <td><tt>long</tt></td>
0101: * <td>integer</td>
0102: * <tr><td align=center><samp>L</samp></td>
0103: * <td><tt>unsigned long</tt></td>
0104: * <td>integer</td>
0105: * <tr><td align=center><samp>f</samp></td>
0106: * <td><tt>float</tt></td>
0107: * <td>float</td>
0108: * <tr><td align=center><samp>d</samp></td>
0109: * <td><tt>double</tt></td>
0110: * <td>float</td>
0111: * <tr><td align=center><samp>s</samp></td>
0112: * <td><tt>char[]</tt></td>
0113: * <td>string</td>
0114: * <tr><td align=center><samp>p</samp></td>
0115: * <td><tt>char[]</tt></td>
0116: * <td>string</td>
0117: * </table>
0118: *
0119: * <P>
0120: * A format character may be preceded by an integral repeat count;
0121: * e.g. the format string <tt>'4h'</tt> means exactly the same as
0122: * <tt>'hhhh'</tt>.
0123: *
0124: * <P>
0125: * Whitespace characters between formats are ignored; a count and its
0126: * format must not contain whitespace though.
0127: *
0128: * <P>
0129: * For the "<tt>s</tt>" format character, the count is interpreted as the
0130: * size of the string, not a repeat count like for the other format
0131: * characters; e.g. <tt>'10s'</tt> means a single 10-byte string, while
0132: * <tt>'10c'</tt> means 10 characters. For packing, the string is
0133: * truncated or padded with null bytes as appropriate to make it fit.
0134: * For unpacking, the resulting string always has exactly the specified
0135: * number of bytes. As a special case, <tt>'0s'</tt> means a single, empty
0136: * string (while <tt>'0c'</tt> means 0 characters).
0137: *
0138: * <P>
0139: * The "<tt>p</tt>" format character can be used to encode a Pascal
0140: * string. The first byte is the length of the stored string, with the
0141: * bytes of the string following. If count is given, it is used as the
0142: * total number of bytes used, including the length byte. If the string
0143: * passed in to <tt>pack()</tt> is too long, the stored representation
0144: * is truncated. If the string is too short, padding is used to ensure
0145: * that exactly enough bytes are used to satisfy the count.
0146: *
0147: * <P>
0148: * For the "<tt>I</tt>" and "<tt>L</tt>" format characters, the return
0149: * value is a Python long integer.
0150: *
0151: * <P>
0152: * By default, C numbers are represented in the machine's native format
0153: * and byte order, and properly aligned by skipping pad bytes if
0154: * necessary (according to the rules used by the C compiler).
0155: *
0156: * <P>
0157: * Alternatively, the first character of the format string can be used to
0158: * indicate the byte order, size and alignment of the packed data,
0159: * according to the following table:
0160: *
0161: * <P>
0162: * <table border align=center>
0163: *
0164: * <tr><th><b>Character</b></th>
0165: * <th align=left><b>Byte order</b></th>
0166: * <th align=left><b>Size and alignment</b></th>
0167: * <tr><td align=center><samp>@</samp></td>
0168: * <td>native</td>
0169: * <td>native</td>
0170: * <tr><td align=center><samp>=</samp></td>
0171: * <td>native</td>
0172: * <td>standard</td>
0173: * <tr><td align=center><samp><</samp></td>
0174: * <td>little-endian</td>
0175: * <td>standard</td>
0176: * <tr><td align=center><samp>></samp></td>
0177: * <td>big-endian</td>
0178: * <td>standard</td>
0179: * <tr><td align=center><samp>!</samp></td>
0180: * <td>network (= big-endian)</td>
0181: * <td>standard</td>
0182: *
0183: * </table>
0184: *
0185: * <P>
0186: * If the first character is not one of these, "<tt>@</tt>" is assumed.
0187: *
0188: * <P>
0189: * Native byte order is big-endian or little-endian, depending on the
0190: * host system (e.g. Motorola and Sun are big-endian; Intel and DEC are
0191: * little-endian).
0192: *
0193: * <P>
0194: * Native size and alignment are defined as follows: <tt>short</tt> is
0195: * 2 bytes; <tt>int</tt> and <tt>long</tt> are 4 bytes; <tt>float</tt>
0196: * are 4 bytes and <tt>double</tt> are 8 bytes. Native byte order is
0197: * chosen as big-endian.
0198: *
0199: * <P>
0200: * Standard size and alignment are as follows: no alignment is required
0201: * for any type (so you have to use pad bytes); <tt>short</tt> is 2 bytes;
0202: * <tt>int</tt> and <tt>long</tt> are 4 bytes. <tt>float</tt> and
0203: * <tt>double</tt> are 32-bit and 64-bit IEEE floating point numbers,
0204: * respectively.
0205: *
0206: * <P>
0207: * Note the difference between "<tt>@</tt>" and "<tt>=</tt>": both use
0208: * native byte order, but the size and alignment of the latter is
0209: * standardized.
0210: *
0211: * <P>
0212: * The form "<tt>!</tt>" is available for those poor souls who claim they
0213: * can't remember whether network byte order is big-endian or
0214: * little-endian.
0215: *
0216: * <P>
0217: * There is no way to indicate non-native byte order (i.e. force
0218: * byte-swapping); use the appropriate choice of "<tt><</tt>" or
0219: * "<tt>></tt>".
0220: *
0221: * <P>
0222: * Examples (all using native byte order, size and alignment, on a
0223: * big-endian machine):
0224: *
0225: * <P>
0226: * <dl><dd><pre>
0227: * >>> from struct import *
0228: * >>> pack('hhl', 1, 2, 3)
0229: * '\000\001\000\002\000\000\000\003'
0230: * >>> unpack('hhl', '\000\001\000\002\000\000\000\003')
0231: * (1, 2, 3)
0232: * >>> calcsize('hhl')
0233: * 8
0234: * >>>
0235: * </pre></dl>
0236: *
0237: * <P>
0238: * Hint: to align the end of a structure to the alignment requirement of
0239: * a particular type, end the format with the code for that type with a
0240: * repeat count of zero, e.g. the format <tt>'llh0l'</tt> specifies two
0241: * pad bytes at the end, assuming longs are aligned on 4-byte boundaries.
0242: * This only works when native size and alignment are in effect;
0243: * standard size and alignment does not enforce any alignment.
0244: *
0245: * For the complete documentation on the struct module, please see the
0246: * "Python Library Reference"
0247: * <p><hr><p>
0248: *
0249: * The module is based on the original structmodule.c except that all
0250: * mistakes and errors are my own. Original author unknown.
0251: * <p>
0252: * @author Finn Bock, bckfnn@pipmail.dknet.dk
0253: * @version struct.java,v 1.6 1999/04/17 12:04:34 fb Exp
0254: */
0255: public class struct {
0256:
0257: /**
0258: * Exception raised on various occasions; argument is a
0259: * string describing what is wrong.
0260: */
0261: public static PyString error = new PyString("struct.error");
0262:
0263: public static String __doc__ = "Functions to convert between Python values and C structs.\n"
0264: + "Python strings are used to hold the data representing the C\n"
0265: + "struct and also as format strings to describe the layout of\n"
0266: + "data in the C struct.\n"
0267: + "\n"
0268: + "The optional first format char indicates byte ordering and\n"
0269: + "alignment:\n"
0270: + " @: native w/native alignment(default)\n"
0271: + " =: native w/standard alignment\n"
0272: + " <: little-endian, std. alignment\n"
0273: + " >: big-endian, std. alignment\n"
0274: + " !: network, std (same as >)\n"
0275: + "\n"
0276: + "The remaining chars indicate types of args and must match\n"
0277: + "exactly; these can be preceded by a decimal repeat count:\n"
0278: + " x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n"
0279: + " h:short; H:unsigned short; i:int; I:unsigned int;\n"
0280: + " l:long; L:unsigned long; f:float; d:double.\n"
0281: + "Special cases (preceding decimal count indicates length):\n"
0282: + " s:string (array of char); p: pascal string (w. count byte).\n"
0283: + "Whitespace between formats is ignored.\n"
0284: + "\n"
0285: + "The variable struct.error is an exception raised on errors.";
0286:
0287: static class FormatDef {
0288: char name;
0289: int size;
0290: int alignment;
0291:
0292: FormatDef init(char name, int size, int alignment) {
0293: this .name = name;
0294: this .size = size;
0295: this .alignment = alignment;
0296: return this ;
0297: }
0298:
0299: void pack(ByteStream buf, PyObject value) {
0300: }
0301:
0302: Object unpack(ByteStream buf) {
0303: return null;
0304: }
0305:
0306: int doPack(ByteStream buf, int count, int pos, PyObject[] args) {
0307: if (pos + count > args.length)
0308: throw StructError("insufficient arguments to pack");
0309:
0310: int cnt = count;
0311: while (count-- > 0)
0312: pack(buf, args[pos++]);
0313: return cnt;
0314: }
0315:
0316: void doUnpack(ByteStream buf, int count, PyList list) {
0317: while (count-- > 0)
0318: list.append(Py.java2py(unpack(buf)));
0319: }
0320:
0321: int get_int(PyObject value) {
0322: try {
0323: return ((PyInteger) value.__int__()).getValue();
0324: } catch (PyException ex) {
0325: throw StructError("required argument is not an integer");
0326: }
0327: }
0328:
0329: long get_long(PyObject value) {
0330: if (value instanceof PyLong) {
0331: Object v = value.__tojava__(Long.TYPE);
0332: if (v == Py.NoConversion)
0333: throw Py
0334: .OverflowError("long int too long to convert");
0335: return ((Long) v).longValue();
0336: } else
0337: return get_int(value);
0338: }
0339:
0340: BigInteger get_ulong(PyObject value) {
0341: if (value instanceof PyLong) {
0342: BigInteger v = (BigInteger) value
0343: .__tojava__(BigInteger.class);
0344: if (v.compareTo(PyLong.maxULong) > 0) {
0345: throw Py
0346: .OverflowError("unsigned long int too long to convert");
0347: }
0348: return v;
0349: } else
0350: return BigInteger.valueOf(get_int(value));
0351: }
0352:
0353: double get_float(PyObject value) {
0354: if (!(value instanceof PyFloat))
0355: throw StructError("required argument is not an float");
0356: return value.__float__().getValue();
0357: }
0358:
0359: void BEwriteInt(ByteStream buf, int v) {
0360: buf.writeByte((int) (v >>> 24) & 0xFF);
0361: buf.writeByte((int) (v >>> 16) & 0xFF);
0362: buf.writeByte((int) (v >>> 8) & 0xFF);
0363: buf.writeByte((int) (v >>> 0) & 0xFF);
0364: }
0365:
0366: void LEwriteInt(ByteStream buf, int v) {
0367: buf.writeByte((int) (v >>> 0) & 0xFF);
0368: buf.writeByte((int) (v >>> 8) & 0xFF);
0369: buf.writeByte((int) (v >>> 16) & 0xFF);
0370: buf.writeByte((int) (v >>> 24) & 0xFF);
0371: }
0372:
0373: int BEreadInt(ByteStream buf) {
0374: int b1 = buf.readByte();
0375: int b2 = buf.readByte();
0376: int b3 = buf.readByte();
0377: int b4 = buf.readByte();
0378: return ((b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0));
0379: }
0380:
0381: int LEreadInt(ByteStream buf) {
0382: int b1 = buf.readByte();
0383: int b2 = buf.readByte();
0384: int b3 = buf.readByte();
0385: int b4 = buf.readByte();
0386: return ((b1 << 0) + (b2 << 8) + (b3 << 16) + (b4 << 24));
0387: }
0388: }
0389:
0390: static class ByteStream {
0391: char[] data;
0392: int len;
0393: int pos;
0394:
0395: ByteStream() {
0396: data = new char[10];
0397: len = 0;
0398: pos = 0;
0399: }
0400:
0401: ByteStream(String s) {
0402: int l = s.length();
0403: data = new char[l];
0404: s.getChars(0, l, data, 0);
0405: len = l;
0406: pos = 0;
0407: }
0408:
0409: int readByte() {
0410: return data[pos++] & 0xFF;
0411: }
0412:
0413: void read(char[] buf, int pos, int len) {
0414: System.arraycopy(data, this .pos, buf, pos, len);
0415: this .pos += len;
0416: }
0417:
0418: String readString(int l) {
0419: char[] data = new char[l];
0420: read(data, 0, l);
0421: return new String(data);
0422: }
0423:
0424: private void ensureCapacity(int l) {
0425: if (pos + l >= data.length) {
0426: char[] b = new char[(pos + l) * 2];
0427: System.arraycopy(data, 0, b, 0, pos);
0428: data = b;
0429: }
0430: }
0431:
0432: void writeByte(int b) {
0433: ensureCapacity(1);
0434: data[pos++] = (char) (b & 0xFF);
0435: }
0436:
0437: void write(char[] buf, int pos, int len) {
0438: ensureCapacity(len);
0439: System.arraycopy(buf, pos, data, this .pos, len);
0440: this .pos += len;
0441: }
0442:
0443: void writeString(String s, int pos, int len) {
0444: char[] data = new char[len];
0445: s.getChars(pos, len, data, 0);
0446: write(data, 0, len);
0447: }
0448:
0449: int skip(int l) {
0450: pos += l;
0451: return pos;
0452: }
0453:
0454: int size() {
0455: return pos;
0456: }
0457:
0458: public String toString() {
0459: return new String(data, 0, pos);
0460: }
0461: }
0462:
0463: static class PadFormatDef extends FormatDef {
0464: int doPack(ByteStream buf, int count, int pos, PyObject[] args) {
0465: while (count-- > 0)
0466: buf.writeByte(0);
0467: return 0;
0468: }
0469:
0470: void doUnpack(ByteStream buf, int count, PyList list) {
0471: while (count-- > 0)
0472: buf.readByte();
0473: }
0474: }
0475:
0476: static class StringFormatDef extends FormatDef {
0477: int doPack(ByteStream buf, int count, int pos, PyObject[] args) {
0478: PyObject value = args[pos];
0479:
0480: if (!(value instanceof PyString))
0481: throw StructError("argument for 's' must be a string");
0482:
0483: String s = value.toString();
0484: int len = s.length();
0485: buf.writeString(s, 0, Math.min(count, len));
0486: if (len < count) {
0487: count -= len;
0488: for (int i = 0; i < count; i++)
0489: buf.writeByte(0);
0490: }
0491: return 1;
0492: }
0493:
0494: void doUnpack(ByteStream buf, int count, PyList list) {
0495: list.append(Py.newString(buf.readString(count)));
0496: }
0497: }
0498:
0499: static class PascalStringFormatDef extends StringFormatDef {
0500: int doPack(ByteStream buf, int count, int pos, PyObject[] args) {
0501: PyObject value = args[pos];
0502:
0503: if (!(value instanceof PyString))
0504: throw StructError("argument for 'p' must be a string");
0505:
0506: buf.writeByte(Math.min(0xFF, Math.min(value.toString()
0507: .length(), count - 1)));
0508: return super .doPack(buf, count - 1, pos, args);
0509: }
0510:
0511: void doUnpack(ByteStream buf, int count, PyList list) {
0512: int n = buf.readByte();
0513: if (n >= count)
0514: n = count - 1;
0515: super .doUnpack(buf, n, list);
0516: buf.skip(Math.max(count - n - 1, 0));
0517: }
0518: }
0519:
0520: static class CharFormatDef extends FormatDef {
0521: void pack(ByteStream buf, PyObject value) {
0522: if (!(value instanceof PyString) || value.__len__() != 1)
0523: throw StructError("char format require string of length 1");
0524: buf.writeByte(value.toString().charAt(0));
0525: }
0526:
0527: Object unpack(ByteStream buf) {
0528: return Py.newString((char) buf.readByte());
0529: }
0530: }
0531:
0532: static class ByteFormatDef extends FormatDef {
0533: void pack(ByteStream buf, PyObject value) {
0534: buf.writeByte(get_int(value));
0535: }
0536:
0537: Object unpack(ByteStream buf) {
0538: int b = buf.readByte();
0539: if (b > Byte.MAX_VALUE)
0540: b -= 0x100;
0541: return Py.newInteger(b);
0542: }
0543: }
0544:
0545: static class UnsignedByteFormatDef extends ByteFormatDef {
0546: Object unpack(ByteStream buf) {
0547: return Py.newInteger(buf.readByte());
0548: }
0549: }
0550:
0551: static class LEShortFormatDef extends FormatDef {
0552: void pack(ByteStream buf, PyObject value) {
0553: int v = get_int(value);
0554: buf.writeByte(v & 0xFF);
0555: buf.writeByte((v >> 8) & 0xFF);
0556: }
0557:
0558: Object unpack(ByteStream buf) {
0559: int v = buf.readByte() | (buf.readByte() << 8);
0560: if (v > Short.MAX_VALUE)
0561: v -= 0x10000;
0562: return Py.newInteger(v);
0563: }
0564: }
0565:
0566: static class LEUnsignedShortFormatDef extends LEShortFormatDef {
0567: Object unpack(ByteStream buf) {
0568: int v = buf.readByte() | (buf.readByte() << 8);
0569: return Py.newInteger(v);
0570: }
0571: }
0572:
0573: static class BEShortFormatDef extends FormatDef {
0574: void pack(ByteStream buf, PyObject value) {
0575: int v = get_int(value);
0576: buf.writeByte((v >> 8) & 0xFF);
0577: buf.writeByte(v & 0xFF);
0578: }
0579:
0580: Object unpack(ByteStream buf) {
0581: int v = (buf.readByte() << 8) | buf.readByte();
0582: if (v > Short.MAX_VALUE)
0583: v -= 0x10000;
0584: return Py.newInteger(v);
0585: }
0586: }
0587:
0588: static class BEUnsignedShortFormatDef extends BEShortFormatDef {
0589: Object unpack(ByteStream buf) {
0590: int v = (buf.readByte() << 8) | buf.readByte();
0591: return Py.newInteger(v);
0592: }
0593: }
0594:
0595: static class LEIntFormatDef extends FormatDef {
0596: void pack(ByteStream buf, PyObject value) {
0597: LEwriteInt(buf, get_int(value));
0598: }
0599:
0600: Object unpack(ByteStream buf) {
0601: int v = LEreadInt(buf);
0602: return Py.newInteger(v);
0603: }
0604: }
0605:
0606: static class LEUnsignedIntFormatDef extends FormatDef {
0607: void pack(ByteStream buf, PyObject value) {
0608: LEwriteInt(buf, (int) (get_long(value) & 0xFFFFFFFF));
0609: }
0610:
0611: Object unpack(ByteStream buf) {
0612: long v = LEreadInt(buf);
0613: if (v < 0)
0614: v += 0x100000000L;
0615: return new PyLong(v);
0616: }
0617: }
0618:
0619: static class BEIntFormatDef extends FormatDef {
0620: void pack(ByteStream buf, PyObject value) {
0621: BEwriteInt(buf, get_int(value));
0622: }
0623:
0624: Object unpack(ByteStream buf) {
0625: return Py.newInteger(BEreadInt(buf));
0626: }
0627: }
0628:
0629: static class BEUnsignedIntFormatDef extends FormatDef {
0630: void pack(ByteStream buf, PyObject value) {
0631: BEwriteInt(buf, (int) (get_long(value) & 0xFFFFFFFF));
0632: }
0633:
0634: Object unpack(ByteStream buf) {
0635: long v = BEreadInt(buf);
0636: if (v < 0)
0637: v += 0x100000000L;
0638: return new PyLong(v);
0639: }
0640: }
0641:
0642: static class LEUnsignedLongFormatDef extends FormatDef {
0643: void pack(ByteStream buf, PyObject value) {
0644: BigInteger bi = get_ulong(value);
0645: if (bi.compareTo(BigInteger.valueOf(0)) < 0) {
0646: throw StructError("can't convert negative long to unsigned");
0647: }
0648: long lvalue = bi.longValue(); // underflow is OK -- the bits are correct
0649: int high = (int) ((lvalue & 0xFFFFFFFF00000000L) >> 32);
0650: int low = (int) (lvalue & 0x00000000FFFFFFFFL);
0651: LEwriteInt(buf, low);
0652: LEwriteInt(buf, high);
0653: }
0654:
0655: Object unpack(ByteStream buf) {
0656: long low = (LEreadInt(buf) & 0X00000000FFFFFFFFL);
0657: long high = (LEreadInt(buf) & 0X00000000FFFFFFFFL);
0658: java.math.BigInteger result = java.math.BigInteger
0659: .valueOf(high);
0660: result = result.multiply(java.math.BigInteger
0661: .valueOf(0x100000000L));
0662: result = result.add(java.math.BigInteger.valueOf(low));
0663: return new PyLong(result);
0664: }
0665: }
0666:
0667: static class BEUnsignedLongFormatDef extends FormatDef {
0668: void pack(ByteStream buf, PyObject value) {
0669: BigInteger bi = get_ulong(value);
0670: if (bi.compareTo(BigInteger.valueOf(0)) < 0) {
0671: throw StructError("can't convert negative long to unsigned");
0672: }
0673: long lvalue = bi.longValue(); // underflow is OK -- the bits are correct
0674: int high = (int) ((lvalue & 0xFFFFFFFF00000000L) >> 32);
0675: int low = (int) (lvalue & 0x00000000FFFFFFFFL);
0676: BEwriteInt(buf, high);
0677: BEwriteInt(buf, low);
0678: }
0679:
0680: Object unpack(ByteStream buf) {
0681: long high = (BEreadInt(buf) & 0X00000000FFFFFFFFL);
0682: long low = (BEreadInt(buf) & 0X00000000FFFFFFFFL);
0683: java.math.BigInteger result = java.math.BigInteger
0684: .valueOf(high);
0685: result = result.multiply(java.math.BigInteger
0686: .valueOf(0x100000000L));
0687: result = result.add(java.math.BigInteger.valueOf(low));
0688: return new PyLong(result);
0689: }
0690: }
0691:
0692: static class LELongFormatDef extends FormatDef {
0693: void pack(ByteStream buf, PyObject value) {
0694: long lvalue = get_long(value);
0695: int high = (int) ((lvalue & 0xFFFFFFFF00000000L) >> 32);
0696: int low = (int) (lvalue & 0x00000000FFFFFFFFL);
0697: LEwriteInt(buf, low);
0698: LEwriteInt(buf, high);
0699: }
0700:
0701: Object unpack(ByteStream buf) {
0702: long low = LEreadInt(buf) & 0x00000000FFFFFFFFL;
0703: long high = ((long) (LEreadInt(buf)) << 32) & 0xFFFFFFFF00000000L;
0704: long result = (high | low);
0705: return new PyLong(result);
0706: }
0707: }
0708:
0709: static class BELongFormatDef extends FormatDef {
0710: void pack(ByteStream buf, PyObject value) {
0711: long lvalue = get_long(value);
0712: int high = (int) ((lvalue & 0xFFFFFFFF00000000L) >> 32);
0713: int low = (int) (lvalue & 0x00000000FFFFFFFFL);
0714: BEwriteInt(buf, high);
0715: BEwriteInt(buf, low);
0716: }
0717:
0718: Object unpack(ByteStream buf) {
0719: long high = ((long) (BEreadInt(buf)) << 32) & 0xFFFFFFFF00000000L;
0720: long low = BEreadInt(buf) & 0x00000000FFFFFFFFL;
0721: long result = (high | low);
0722: return new PyLong(result);
0723: }
0724: }
0725:
0726: static class LEFloatFormatDef extends FormatDef {
0727: void pack(ByteStream buf, PyObject value) {
0728: int bits = Float.floatToIntBits((float) get_float(value));
0729: LEwriteInt(buf, bits);
0730: }
0731:
0732: Object unpack(ByteStream buf) {
0733: int v = LEreadInt(buf);
0734: return Py.newFloat(Float.intBitsToFloat(v));
0735: }
0736: }
0737:
0738: static class LEDoubleFormatDef extends FormatDef {
0739: void pack(ByteStream buf, PyObject value) {
0740: long bits = Double.doubleToLongBits(get_float(value));
0741: LEwriteInt(buf, (int) (bits & 0xFFFFFFFF));
0742: LEwriteInt(buf, (int) (bits >>> 32));
0743: }
0744:
0745: Object unpack(ByteStream buf) {
0746: long bits = (LEreadInt(buf) & 0xFFFFFFFFL)
0747: + (((long) LEreadInt(buf)) << 32);
0748: return Py.newFloat(Double.longBitsToDouble(bits));
0749: }
0750: }
0751:
0752: static class BEFloatFormatDef extends FormatDef {
0753: void pack(ByteStream buf, PyObject value) {
0754: int bits = Float.floatToIntBits((float) get_float(value));
0755: BEwriteInt(buf, bits);
0756: }
0757:
0758: Object unpack(ByteStream buf) {
0759: int v = BEreadInt(buf);
0760: return Py.newFloat(Float.intBitsToFloat(v));
0761: }
0762: }
0763:
0764: static class BEDoubleFormatDef extends FormatDef {
0765: void pack(ByteStream buf, PyObject value) {
0766: long bits = Double.doubleToLongBits(get_float(value));
0767: BEwriteInt(buf, (int) (bits >>> 32));
0768: BEwriteInt(buf, (int) (bits & 0xFFFFFFFF));
0769: }
0770:
0771: Object unpack(ByteStream buf) {
0772: long bits = (((long) BEreadInt(buf)) << 32)
0773: + (BEreadInt(buf) & 0xFFFFFFFFL);
0774: return Py.newFloat(Double.longBitsToDouble(bits));
0775: }
0776: }
0777:
0778: private static FormatDef[] lilendian_table = {
0779: new PadFormatDef().init('x', 1, 0),
0780: new ByteFormatDef().init('b', 1, 0),
0781: new UnsignedByteFormatDef().init('B', 1, 0),
0782: new CharFormatDef().init('c', 1, 0),
0783: new StringFormatDef().init('s', 1, 0),
0784: new PascalStringFormatDef().init('p', 1, 0),
0785: new LEShortFormatDef().init('h', 2, 0),
0786: new LEUnsignedShortFormatDef().init('H', 2, 0),
0787: new LEIntFormatDef().init('i', 4, 0),
0788: new LEUnsignedIntFormatDef().init('I', 4, 0),
0789: new LEIntFormatDef().init('l', 4, 0),
0790: new LEUnsignedIntFormatDef().init('L', 4, 0),
0791: new LELongFormatDef().init('q', 8, 8),
0792: new LEUnsignedLongFormatDef().init('Q', 8, 8),
0793: new LEFloatFormatDef().init('f', 4, 0),
0794: new LEDoubleFormatDef().init('d', 8, 0), };
0795:
0796: private static FormatDef[] bigendian_table = {
0797: new PadFormatDef().init('x', 1, 0),
0798: new ByteFormatDef().init('b', 1, 0),
0799: new UnsignedByteFormatDef().init('B', 1, 0),
0800: new CharFormatDef().init('c', 1, 0),
0801: new StringFormatDef().init('s', 1, 0),
0802: new PascalStringFormatDef().init('p', 1, 0),
0803: new BEShortFormatDef().init('h', 2, 0),
0804: new BEUnsignedShortFormatDef().init('H', 2, 0),
0805: new BEIntFormatDef().init('i', 4, 0),
0806: new BEUnsignedIntFormatDef().init('I', 4, 0),
0807: new BEIntFormatDef().init('l', 4, 0),
0808: new BEUnsignedIntFormatDef().init('L', 4, 0),
0809: new BELongFormatDef().init('q', 8, 8),
0810: new BEUnsignedLongFormatDef().init('Q', 8, 8),
0811: new BEFloatFormatDef().init('f', 4, 0),
0812: new BEDoubleFormatDef().init('d', 8, 0), };
0813:
0814: private static FormatDef[] native_table = {
0815: new PadFormatDef().init('x', 1, 0),
0816: new ByteFormatDef().init('b', 1, 0),
0817: new UnsignedByteFormatDef().init('B', 1, 0),
0818: new CharFormatDef().init('c', 1, 0),
0819: new StringFormatDef().init('s', 1, 0),
0820: new PascalStringFormatDef().init('p', 1, 0),
0821: new BEShortFormatDef().init('h', 2, 2),
0822: new BEUnsignedShortFormatDef().init('H', 2, 2),
0823: new BEIntFormatDef().init('i', 4, 4),
0824: new BEUnsignedIntFormatDef().init('I', 4, 4),
0825: new BEIntFormatDef().init('l', 4, 4),
0826: new BEUnsignedIntFormatDef().init('L', 4, 4),
0827: new BELongFormatDef().init('q', 8, 8),
0828: new BEUnsignedLongFormatDef().init('Q', 8, 8),
0829: new BEFloatFormatDef().init('f', 4, 4),
0830: new BEDoubleFormatDef().init('d', 8, 8), };
0831:
0832: private static FormatDef[] whichtable(String pfmt) {
0833: char c = pfmt.charAt(0);
0834: switch (c) {
0835: case '<':
0836: return lilendian_table;
0837: case '>':
0838: case '!':
0839: // Network byte order is big-endian
0840: return bigendian_table;
0841: case '=':
0842: return bigendian_table;
0843: case '@':
0844: default:
0845: return native_table;
0846: }
0847: }
0848:
0849: private static FormatDef getentry(char c, FormatDef[] f) {
0850: for (int i = 0; i < f.length; i++) {
0851: if (f[i].name == c)
0852: return f[i];
0853: }
0854: throw StructError("bad char in struct format");
0855: }
0856:
0857: private static int align(int size, FormatDef e) {
0858: if (e.alignment != 0) {
0859: size = ((size + e.alignment - 1) / e.alignment)
0860: * e.alignment;
0861: }
0862: return size;
0863: }
0864:
0865: private static int calcsize(String format, FormatDef[] f) {
0866: int size = 0;
0867:
0868: int len = format.length();
0869: for (int j = 0; j < len; j++) {
0870: char c = format.charAt(j);
0871: if (j == 0
0872: && (c == '@' || c == '<' || c == '>' || c == '=' || c == '!'))
0873: continue;
0874: if (Character.isWhitespace(c))
0875: continue;
0876: int num = 1;
0877: if (Character.isDigit(c)) {
0878: num = Character.digit(c, 10);
0879: while (++j < len
0880: && Character.isDigit((c = format.charAt(j)))) {
0881: int x = num * 10 + Character.digit(c, 10);
0882: if (x / 10 != num)
0883: throw StructError("overflow in item count");
0884: num = x;
0885: }
0886: if (j >= len)
0887: break;
0888: }
0889:
0890: FormatDef e = getentry(c, f);
0891:
0892: int itemsize = e.size;
0893: size = align(size, e);
0894: int x = num * itemsize;
0895: size += x;
0896: if (x / itemsize != num || size < 0)
0897: throw StructError("total struct size too long");
0898: }
0899: return size;
0900: }
0901:
0902: /**
0903: * Return the size of the struct (and hence of the string)
0904: * corresponding to the given format.
0905: */
0906: static public int calcsize(String format) {
0907: FormatDef[] f = whichtable(format);
0908: return calcsize(format, f);
0909: }
0910:
0911: /**
0912: * Return a string containing the values v1, v2, ... packed according
0913: * to the given format. The arguments must match the
0914: * values required by the format exactly.
0915: */
0916: static public String pack(PyObject[] args) {
0917: if (args.length < 1)
0918: Py
0919: .TypeError("illegal argument type for built-in operation");
0920:
0921: String format = args[0].toString();
0922:
0923: FormatDef[] f = whichtable(format);
0924: int size = calcsize(format, f);
0925:
0926: ByteStream res = new ByteStream();
0927:
0928: int i = 1;
0929: int len = format.length();
0930: for (int j = 0; j < len; j++) {
0931: char c = format.charAt(j);
0932: if (j == 0
0933: && (c == '@' || c == '<' || c == '>' || c == '=' || c == '!'))
0934: continue;
0935: if (Character.isWhitespace(c))
0936: continue;
0937: int num = 1;
0938: if (Character.isDigit(c)) {
0939: num = Character.digit(c, 10);
0940: while (++j < len
0941: && Character.isDigit((c = format.charAt(j))))
0942: num = num * 10 + Character.digit(c, 10);
0943: if (j >= len)
0944: break;
0945: }
0946:
0947: FormatDef e = getentry(c, f);
0948:
0949: // Fill padd bytes with zeros
0950: int nres = align(res.size(), e) - res.size();
0951: while (nres-- > 0)
0952: res.writeByte(0);
0953: i += e.doPack(res, num, i, args);
0954: }
0955:
0956: if (i < args.length)
0957: throw StructError("too many arguments for pack format");
0958:
0959: return res.toString();
0960: }
0961:
0962: /**
0963: * Unpack the string (presumably packed by pack(fmt, ...)) according
0964: * to the given format. The result is a tuple even if it contains
0965: * exactly one item.
0966: * The string must contain exactly the amount of data required by
0967: * the format (i.e. len(string) must equal calcsize(fmt)).
0968: */
0969: public static PyTuple unpack(String format, String string) {
0970: int len = string.length();
0971:
0972: FormatDef[] f = whichtable(format);
0973: int size = calcsize(format, f);
0974:
0975: if (size != len)
0976: throw StructError("unpack str size does not match format");
0977:
0978: PyList res = new PyList();
0979:
0980: ByteStream str = new ByteStream(string);
0981:
0982: int flen = format.length();
0983: for (int j = 0; j < flen; j++) {
0984: char c = format.charAt(j);
0985: if (j == 0
0986: && (c == '@' || c == '<' || c == '>' || c == '=' || c == '!'))
0987: continue;
0988: if (Character.isWhitespace(c))
0989: continue;
0990: int num = 1;
0991: if (Character.isDigit(c)) {
0992: num = Character.digit(c, 10);
0993: while (++j < flen
0994: && Character.isDigit((c = format.charAt(j))))
0995: num = num * 10 + Character.digit(c, 10);
0996: if (j > flen)
0997: break;
0998: }
0999:
1000: FormatDef e = getentry(c, f);
1001:
1002: str.skip(align(str.size(), e) - str.size());
1003:
1004: e.doUnpack(str, num, res);
1005: }
1006: return __builtin__.tuple(res);
1007: }
1008:
1009: private static PyException StructError(String explanation) {
1010: return new PyException(error, explanation);
1011: }
1012: }
|