/** * Puts the content of this field into the given byte vector. * * @param out where the content of this field must be put. */ void put(final ByteVector out) { int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC)); out.putShort(access & ~mask).putShort(name).putShort(desc); int attributeCount = 0; if (value != 0) { ++attributeCount; } if ((access & Opcodes.ACC_SYNTHETIC) != 0 && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0)) { ++attributeCount; } if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; } if (ClassReader.SIGNATURES && signature != 0) { ++attributeCount; } if (ClassReader.ANNOTATIONS && anns != null) { ++attributeCount; } if (ClassReader.ANNOTATIONS && ianns != null) { ++attributeCount; } if (attrs != null) { attributeCount += attrs.getCount(); } out.putShort(attributeCount); if (value != 0) { out.putShort(cw.newUTF8("ConstantValue")); out.putInt(2).putShort(value); } if ((access & Opcodes.ACC_SYNTHETIC) != 0 && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0)) { out.putShort(cw.newUTF8("Synthetic")).putInt(0); } if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); } if (ClassReader.SIGNATURES && signature != 0) { out.putShort(cw.newUTF8("Signature")); out.putInt(2).putShort(signature); } if (ClassReader.ANNOTATIONS && anns != null) { out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } if (ClassReader.ANNOTATIONS && ianns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } if (attrs != null) { attrs.put(cw, null, 0, -1, -1, out); } }
public void visitEnum(final String name, final String desc, final String value) { ++size; if (named) { bv.putShort(cw.newUTF8(name)); } bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); }
/** * Puts the given annotation lists into the given byte vector. * * @param panns an array of annotation writer lists. * @param out where the annotations must be put. */ static void put(final AnnotationWriter[] panns, final ByteVector out) { int size = 1 + 2 * panns.length; for (int i = 0; i < panns.length; ++i) { size += panns[i] == null ? 0 : panns[i].getSize(); } out.putInt(size).putByte(panns.length); for (int i = 0; i < panns.length; ++i) { AnnotationWriter aw = panns[i]; AnnotationWriter last = null; int n = 0; while (aw != null) { ++n; aw.visitEnd(); // in case user forgot to call visitEnd aw.prev = last; last = aw; aw = aw.next; } out.putShort(n); aw = last; while (aw != null) { out.putByteArray(aw.bv.data, 0, aw.bv.length); aw = aw.prev; } } }
/** * Puts a reference to this label in the bytecode of a method. If the position of the label is * known, the offset is computed and written directly. Otherwise, a null offset is written and a * new forward reference is declared for this label. * * @param owner the code writer that calls this method. * @param out the bytecode of the method. * @param source the position of first byte of the bytecode instruction that contains this label. * @param wideOffset <tt>true</tt> if the reference must be stored in 4 bytes, or <tt>false</tt> * if it must be stored with 2 bytes. * @throws IllegalArgumentException if this label has not been created by the given code writer. */ void put( final CodeWriter owner, final ByteVector out, final int source, final boolean wideOffset) { if (CodeWriter.CHECK) { if (this.owner == null) { this.owner = owner; } else if (this.owner != owner) { throw new IllegalArgumentException(); } } if (resolved) { if (wideOffset) { out.put4(position - source); } else { out.put2(position - source); } } else { if (wideOffset) { addReference(-1 - source, out.length); out.put4(-1); } else { addReference(source, out.length); out.put2(-1); } } }
public void method464(int i, ByteVector class37_sub11, boolean bool, int i_9_) { if ((i ^ 0xffffffff) == -2) anInt2556 = class37_sub11.getTriByte(-26256544); else if ((i ^ 0xffffffff) == -3) { anInt2554 = class37_sub11.getUnsignedShort(); if (anInt2554 == 65535) anInt2554 = -1; } if (bool == false) anInt2553++; }
public AnnotationVisitor visitArray(final String name) { ++size; if (named) { bv.putShort(cw.newUTF8(name)); } // write tag, and reserve space for array size bv.put12('[', 0); return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); }
public AnnotationVisitor visitAnnotation(final String name, final String desc) { ++size; if (named) { bv.putShort(cw.newUTF8(name)); } // write tag and type, and reserve space for values count bv.put12('@', cw.newUTF8(desc)).putShort(0); return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); }
public void visitInnerClass(String name, String outerName, String innerName, int access) { if (innerClasses == null) { innerClasses = new ByteVector(); } ++innerClassesCount; innerClasses.putShort(name == null ? 0 : newClass(name)); innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); innerClasses.putShort(access); }
public AnnotationVisitor visitAnnotation(String desc, boolean visible) { ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(newUTF8(desc)).putShort(0); AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); if (visible) { aw.next = anns; anns = aw; } else { aw.next = ianns; ianns = aw; } return aw; }
@Override public byte[] decompress(final RandomAccessInputStream in, final CodecOptions options) throws FormatException, IOException { final InflaterInputStream i = new InflaterInputStream(in); final ByteVector bytes = new ByteVector(); final byte[] buf = new byte[8192]; int r = 0; // read until eof reached try { while ((r = i.read(buf, 0, buf.length)) > 0) bytes.add(buf, 0, r); } catch (final EOFException e) { } return bytes.toByteArray(); }
@Override public byte[] compress(final byte[] data, final CodecOptions options) throws FormatException { if (data == null || data.length == 0) throw new IllegalArgumentException("No data to compress"); final Deflater deflater = new Deflater(); deflater.setInput(data); deflater.finish(); final byte[] buf = new byte[8192]; final ByteVector bytes = new ByteVector(); int r = 0; // compress until eof reached while ((r = deflater.deflate(buf, 0, buf.length)) > 0) { bytes.add(buf, 0, r); } return bytes.toByteArray(); }
public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(newUTF8(desc)).putShort(0); AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); if (visible) { aw.next = anns; anns = aw; } else { aw.next = ianns; ianns = aw; } return aw; }
/** * Puts a reference to this label in the bytecode of a method. If the position of the label is * known, the offset is computed and written directly. Otherwise, a null offset is written and a * new forward reference is declared for this label. * * @param owner the code writer that calls this method. * @param out the bytecode of the method. * @param source the position of first byte of the bytecode instruction that contains this label. * @param wideOffset <tt>true</tt> if the reference must be stored in 4 bytes, or <tt>false</tt> * if it must be stored with 2 bytes. * @throws IllegalArgumentException if this label has not been created by the given code writer. */ void put( final MethodWriter owner, final ByteVector out, final int source, final boolean wideOffset) { if ((status & RESOLVED) == 0) { if (wideOffset) { addReference(-1 - source, out.length); out.putInt(-1); } else { addReference(source, out.length); out.putShort(-1); } } else { if (wideOffset) { out.putInt(position - source); } else { out.putShort(position - source); } } }
public void visitSource(final String file, final String debug) { if (file != null) { sourceFile = newUTF8(file); } if (debug != null) { sourceDebug = new ByteVector(); sourceDebug.putUTF8(debug); } }
/** * Decodes a PackBits (Macintosh RLE) compressed image. Adapted from the TIFF 6.0 specification, * page 42. * * @param input input data to be decompressed * @return The decompressed data * @throws FormatException if data is not valid compressed data for this decompressor */ public byte[] decompress(byte[] input, Object options) throws FormatException { ByteVector output = new ByteVector(input.length); int pt = 0; while (pt < input.length) { byte n = input[pt++]; if (n >= 0) { // 0 <= n <= 127 int len = pt + n + 1 > input.length ? (input.length - pt) : (n + 1); output.add(input, pt, len); pt += len; } else if (n != -128) { // -127 <= n <= -1 if (pt >= input.length) break; int len = -n + 1; byte inp = input[pt++]; for (int i = 0; i < len; i++) output.add(inp); } } return output.toByteArray(); }
public void method462(boolean bool, ByteVector class37_sub11, int i) { anInt2546++; for (; ; ) { int i_1_ = class37_sub11.getUnsignedByte(122); if ((i_1_ ^ 0xffffffff) == -1) break; method464(i_1_, class37_sub11, false, i); } if (bool != true) anIntArray2562 = null; }
/** * Adds a string to the constant pool of the class being build. Does nothing if the constant pool * already contains a similar item. * * @param value the String value. * @return a new or already existing string item. */ private Item newString(final String value) { key2.set(STR, value, null, null); Item result = get(key2); if (result == null) { pool.put12(STR, newUTF8(value)); result = new Item(index++, key2); put(result); } return result; }
/** * Adds a float to the constant pool of the class being build. Does nothing if the constant pool * already contains a similar item. * * @param value the float value. * @return a new or already existing float item. */ Item newFloat(final float value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(FLOAT).putInt(Float.floatToIntBits(value)); result = new Item(index++, key); put(result); } return result; }
/** * Adds an integer to the constant pool of the class being build. Does nothing if the constant * pool already contains a similar item. * * @param value the int value. * @return a new or already existing int item. */ Item newInteger(final int value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(INT).putInt(value); result = new Item(index++, key); put(result); } return result; }
/** * Adds a class reference to the constant pool of the class being build. Does nothing if the * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} * sub classes, and is normally not needed by class generators or adapters.</i> * * @param value the internal name of the class. * @return a new or already existing class reference item. */ Item newClassItem(final String value) { key2.set(CLASS, value, null, null); Item result = get(key2); if (result == null) { pool.put12(CLASS, newUTF8(value)); result = new Item(index++, key2); put(result); } return result; }
/** * Adds an UTF8 string to the constant pool of the class being build. Does nothing if the constant * pool already contains a similar item. <i>This method is intended for {@link Attribute} sub * classes, and is normally not needed by class generators or adapters.</i> * * @param value the String value. * @return the index of a new or already existing UTF8 item. */ public int newUTF8(final String value) { key.set(UTF8, value, null, null); Item result = get(key); if (result == null) { pool.putByte(UTF8).putUTF8(value); result = new Item(index++, key); put(result); } return result.index; }
/** * Adds a double to the constant pool of the class being build. Does nothing if the constant pool * already contains a similar item. * * @param value the double value. * @return a new or already existing double item. */ Item newDouble(final double value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(DOUBLE).putLong(Double.doubleToLongBits(value)); result = new Item(index, key); put(result); index += 2; } return result; }
/** * Adds a long to the constant pool of the class being build. Does nothing if the constant pool * already contains a similar item. * * @param value the long value. * @return a new or already existing long item. */ Item newLong(final long value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(LONG).putLong(value); result = new Item(index, key); put(result); index += 2; } return result; }
/** * Puts the annotations of this annotation writer list into the given byte vector. * * @param out where the annotations must be put. */ void put(final ByteVector out) { int n = 0; int size = 2; AnnotationWriter aw = this; AnnotationWriter last = null; while (aw != null) { ++n; size += aw.bv.length; aw.visitEnd(); // in case user forgot to call visitEnd aw.prev = last; last = aw; aw = aw.next; } out.putInt(size); out.putShort(n); aw = last; while (aw != null) { out.putByteArray(aw.bv.data, 0, aw.bv.length); aw = aw.prev; } }
/** * Converts a type path in string form, in the format used by {@link #toString()}, into a TypePath * object. * * @param typePath a type path in string form, in the format used by {@link #toString()}. May be * null or empty. * @return the corresponding TypePath object, or null if the path is empty. */ public static TypePath fromString(final String typePath) { if (typePath == null || typePath.length() == 0) { return null; } int n = typePath.length(); ByteVector out = new ByteVector(n); out.putByte(0); for (int i = 0; i < n; ) { char c = typePath.charAt(i++); if (c == '[') { out.put11(ARRAY_ELEMENT, 0); } else if (c == '.') { out.put11(INNER_TYPE, 0); } else if (c == '*') { out.put11(WILDCARD_BOUND, 0); } else if (c >= '0' && c <= '9') { int typeArg = c - '0'; while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') { typeArg = typeArg * 10 + c - '0'; i += 1; } out.put11(TYPE_ARGUMENT, typeArg); } } out.data[0] = (byte) (out.length / 2); return new TypePath(out.data, 0); }
public static void method303( int i, Class20[] class20s, byte[] is, int i_13_, int i_14_, Class67 class67, int i_15_, int i_16_, int i_17_, int i_18_, int i_19_) { try { anInt747++; ByteVector class37_sub11 = new ByteVector(is); if (i_19_ == 967) { int i_20_ = -1; for (; ; ) { int i_21_ = class37_sub11.method961(255); if (i_21_ == 0) break; i_20_ += i_21_; int i_22_ = 0; for (; ; ) { int i_23_ = class37_sub11.method961(255); if (i_23_ == 0) break; i_22_ += i_23_ + -1; int i_24_ = class37_sub11.getUnsignedByte(117); int i_25_ = i_22_ >> 467110028; int i_26_ = 0x3f & i_22_; int i_27_ = 0x3f & i_22_ >> 1114178406; int i_28_ = i_24_ >> 2050158242; int i_29_ = 0x3 & i_24_; if ((i_13_ ^ 0xffffffff) == (i_25_ ^ 0xffffffff) && (i_27_ ^ 0xffffffff) <= (i_14_ ^ 0xffffffff) && (i_27_ ^ 0xffffffff) > (i_14_ - -8 ^ 0xffffffff) && i_26_ >= i_17_ && (8 + i_17_ ^ 0xffffffff) < (i_26_ ^ 0xffffffff)) { Class37_Sub4_Sub11 class37_sub4_sub11 = Class37_Sub9_Sub8.method794(i_20_, 28067); int i_30_ = i - -(Class37_Sub9_Sub33.method903( i_26_ & 0x7, class37_sub4_sub11.anInt2731, class37_sub4_sub11.anInt2743, (byte) -38, i_29_, 0x7 & i_27_, i_18_)); int i_31_ = i_16_ + (Class52_Sub1.method1132( i_18_, i_26_ & 0x7, class37_sub4_sub11.anInt2731, i_29_, (byte) 83, 0x7 & i_27_, class37_sub4_sub11.anInt2743)); if (i_30_ > 0 && i_31_ > 0 && i_30_ < 103 && i_31_ < 103) { Class20 class20 = null; int i_32_ = i_15_; if ((0x2 & (Class1.aByteArrayArrayArray63[1][i_30_][i_31_]) ^ 0xffffffff) == -3) i_32_--; if ((i_32_ ^ 0xffffffff) <= -1) class20 = class20s[i_32_]; Class56.method1144( i_20_, i_28_, 0x3 & i_29_ + i_18_, i_15_, class67, false, i_31_, i_30_, class20); } } } } } } catch (RuntimeException runtimeexception) { throw Class37_Sub4_Sub7_Sub3.method516( runtimeexception, ("jg.E(" + i + ',' + (class20s != null ? "{...}" : "null") + ',' + (is != null ? "{...}" : "null") + ',' + i_13_ + ',' + i_14_ + ',' + (class67 != null ? "{...}" : "null") + ',' + i_15_ + ',' + i_16_ + ',' + i_17_ + ',' + i_18_ + ',' + i_19_ + ')')); } }
/** * Returns the bytecode of the class that was build with this class writer. * * @return the bytecode of the class that was build with this class writer. */ public byte[] toByteArray() { // computes the real size of the bytecode of this class int size = 24 + 2 * interfaceCount; int nbFields = 0; FieldWriter fb = firstField; while (fb != null) { ++nbFields; size += fb.getSize(); fb = fb.next; } int nbMethods = 0; MethodWriter mb = firstMethod; while (mb != null) { ++nbMethods; size += mb.getSize(); mb = mb.next; } int attributeCount = 0; if (signature != 0) { ++attributeCount; size += 8; newUTF8("Signature"); } if (sourceFile != 0) { ++attributeCount; size += 8; newUTF8("SourceFile"); } if (sourceDebug != null) { ++attributeCount; size += sourceDebug.length + 4; newUTF8("SourceDebugExtension"); } if (enclosingMethodOwner != 0) { ++attributeCount; size += 10; newUTF8("EnclosingMethod"); } if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; size += 6; newUTF8("Deprecated"); } if ((access & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xffff) < Opcodes.V1_5) { ++attributeCount; size += 6; newUTF8("Synthetic"); } if (innerClasses != null) { ++attributeCount; size += 8 + innerClasses.length; newUTF8("InnerClasses"); } if (anns != null) { ++attributeCount; size += 8 + anns.getSize(); newUTF8("RuntimeVisibleAnnotations"); } if (ianns != null) { ++attributeCount; size += 8 + ianns.getSize(); newUTF8("RuntimeInvisibleAnnotations"); } if (attrs != null) { attributeCount += attrs.getCount(); size += attrs.getSize(this, null, 0, -1, -1); } size += pool.length; // allocates a byte vector of this size, in order to avoid unnecessary // arraycopy operations in the ByteVector.enlarge() method ByteVector out = new ByteVector(size); out.putInt(0xCAFEBABE).putInt(version); out.putShort(index).putByteArray(pool.data, 0, pool.length); out.putShort(access).putShort(name).putShort(superName); out.putShort(interfaceCount); for (int i = 0; i < interfaceCount; ++i) { out.putShort(interfaces[i]); } out.putShort(nbFields); fb = firstField; while (fb != null) { fb.put(out); fb = fb.next; } out.putShort(nbMethods); mb = firstMethod; while (mb != null) { mb.put(out); mb = mb.next; } out.putShort(attributeCount); if (signature != 0) { out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); } if (sourceFile != 0) { out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); } if (sourceDebug != null) { int len = sourceDebug.length - 2; out.putShort(newUTF8("SourceDebugExtension")).putInt(len); out.putByteArray(sourceDebug.data, 2, len); } if (enclosingMethodOwner != 0) { out.putShort(newUTF8("EnclosingMethod")).putInt(4); out.putShort(enclosingMethodOwner).putShort(enclosingMethod); } if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(newUTF8("Deprecated")).putInt(0); } if ((access & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xffff) < Opcodes.V1_5) { out.putShort(newUTF8("Synthetic")).putInt(0); } if (innerClasses != null) { out.putShort(newUTF8("InnerClasses")); out.putInt(innerClasses.length + 2).putShort(innerClassesCount); out.putByteArray(innerClasses.data, 0, innerClasses.length); } if (anns != null) { out.putShort(newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } if (ianns != null) { out.putShort(newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } if (attrs != null) { attrs.put(this, null, 0, -1, -1, out); } if (invalidFrames) { ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES); return cw.toByteArray(); } return out.data; }
/** * Puts the content of this field into the given byte vector. * * @param out where the content of this field must be put. */ void put(final ByteVector out) { out.putShort(access).putShort(name).putShort(desc); int attributeCount = 0; if (value != 0) { ++attributeCount; } if ((access & Opcodes.ACC_SYNTHETIC) != 0 && (cw.version & 0xffff) < Opcodes.V1_5) { ++attributeCount; } if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; } if (cw.version == Opcodes.V1_4 && (access & Opcodes.ACC_ENUM) != 0) { ++attributeCount; } if (signature != 0) { ++attributeCount; } if (anns != null) { ++attributeCount; } if (ianns != null) { ++attributeCount; } if (attrs != null) { attributeCount += attrs.getCount(); } out.putShort(attributeCount); if (value != 0) { out.putShort(cw.newUTF8("ConstantValue")); out.putInt(2).putShort(value); } if ((access & Opcodes.ACC_SYNTHETIC) != 0 && (cw.version & 0xffff) < Opcodes.V1_5) { out.putShort(cw.newUTF8("Synthetic")).putInt(0); } if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); } if (cw.version == Opcodes.V1_4 && (access & Opcodes.ACC_ENUM) != 0) { out.putShort(cw.newUTF8("Enum")).putInt(0); } if (signature != 0) { out.putShort(cw.newUTF8("Signature")); out.putInt(2).putShort(signature); } if (anns != null) { out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } if (ianns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } if (attrs != null) { attrs.put(cw, null, 0, -1, -1, out); } }
/** * Puts one byte and two shorts into the constant pool. * * @param b a byte. * @param s1 a short. * @param s2 another short. */ private void put122(final int b, final int s1, final int s2) { pool.put12(b, s1).putShort(s2); }
/* @see Codec#decompress(RandomAccessInputStream, CodecOptions) */ public byte[] decompress(RandomAccessInputStream in, CodecOptions options) throws FormatException, IOException { if (in == null) throw new IllegalArgumentException("No data to decompress."); // Adapted from LZO for Java, available at // http://www.oberhumer.com/opensource/lzo/ ByteVector dst = new ByteVector(); int t = in.read() & 0xff; int mPos; if (t > 17) { t -= 17; // do dst[op++] = src[ip++]; while (--t > 0); byte[] b = new byte[t]; in.read(b); dst.add(b); t = in.read() & 0xff; // if (t < 16) return; if (t < 16) { return dst.toByteArray(); } } loop: for (; ; t = in.read() & 0xff) { if (t < 16) { if (t == 0) { byte f = in.readByte(); while (f == 0) { t += 255; f = in.readByte(); } t += 15 + (f & 0xff); } t += 3; // do dst[op++] = src[ip++]; while (--t > 0); byte[] b = new byte[t]; in.read(b); dst.add(b); t = in.read() & 0xff; if (t < 16) { mPos = dst.size() - 0x801 - (t >> 2) - ((in.read() & 0xff) << 2); if (mPos < 0) { t = LZO_OVERRUN; break loop; } t = 3; do { dst.add(dst.get(mPos++)); } while (--t > 0); // do dst[op++] = dst[mPos++]; while (--t > 0); in.seek(in.getFilePointer() - 2); t = in.read() & 3; in.skipBytes(1); if (t == 0) continue; // do dst[op++] = src[ip++]; while (--t > 0); b = new byte[t]; in.read(b); dst.add(b); t = in.read() & 0xff; } } for (; ; t = in.read() & 0xff) { if (t >= 64) { mPos = dst.size() - 1 - ((t >> 2) & 7) - ((in.read() & 0xff) << 3); t = (t >> 5) - 1; } else if (t >= 32) { t &= 31; if (t == 0) { byte f = in.readByte(); while (f == 0) { t += 255; f = in.readByte(); } t += 31 + (f & 0xff); } mPos = dst.size() - 1 - ((in.read() & 0xff) >> 2); mPos -= ((in.read() & 0xff) << 6); } else if (t >= 16) { mPos = dst.size() - ((t & 8) << 11); t &= 7; if (t == 0) { byte f = in.readByte(); while (f == 0) { t += 255; f = in.readByte(); } t += 7 + (f & 0xff); } mPos -= ((in.read() & 0xff) >> 2); mPos -= ((in.read() & 0xff) << 6); if (mPos == dst.size()) break loop; mPos -= 0x4000; } else { mPos = dst.size() - 1 - (t >> 2) - ((in.read() & 0xff) << 2); t = 0; } if (mPos < 0) { t = LZO_OVERRUN; break loop; } t += 2; // do dst[op++] = dst[mPos++]; while (--t > 0); do { dst.add(dst.get(mPos++)); } while (--t > 0); in.seek(in.getFilePointer() - 2); t = in.read() & 3; in.skipBytes(1); if (t == 0) break; // do dst[op++] = src[ip++]; while (--t > 0); byte[] b = new byte[t]; in.read(b); dst.add(b); t = 0; } } return dst.toByteArray(); }