private static Integer readNumber(int b0, DataInput input) throws IOException { if (b0 == 28) { int b1 = input.readUnsignedByte(); int b2 = input.readUnsignedByte(); return (int) (short) (b1 << 8 | b2); } else if (b0 >= 32 && b0 <= 246) { return b0 - 139; } else if (b0 >= 247 && b0 <= 250) { int b1 = input.readUnsignedByte(); return (b0 - 247) * 256 + b1 + 108; } else if (b0 >= 251 && b0 <= 254) { int b1 = input.readUnsignedByte(); return -(b0 - 251) * 256 - b1 - 108; } else if (b0 == 255) { int b1 = input.readUnsignedByte(); int b2 = input.readUnsignedByte(); // The lower bytes are representing the digits after // the decimal point and aren't needed in this context input.readUnsignedByte(); input.readUnsignedByte(); return (int) (short) (b1 << 8 | b2); } else { throw new IllegalArgumentException(); } }
private CharStringCommand readCommand(int b0, DataInput input) throws IOException { if (b0 == 1 || b0 == 18) { hstemCount += peekNumbers().size() / 2; } else if (b0 == 3 || b0 == 19 || b0 == 20 || b0 == 23) { vstemCount += peekNumbers().size() / 2; } // End if if (b0 == 12) { int b1 = input.readUnsignedByte(); return new CharStringCommand(b0, b1); } else if (b0 == 19 || b0 == 20) { int[] value = new int[1 + getMaskLength()]; value[0] = b0; for (int i = 1; i < value.length; i++) { value[i] = input.readUnsignedByte(); } return new CharStringCommand(value); } return new CharStringCommand(b0); }
/** * Read a long previously written by writeLong(). * * @exception IOException an exception was thrown by a method on in. */ public static final long readLong(DataInput in) throws IOException { int int_value = in.readUnsignedByte(); if ((int_value & ~0x3f) == 0) { // test for small case first - assuming this is usual case. // this is stored in 2 bytes. return ((int_value << 8) | in.readUnsignedByte()); } else if ((int_value & 0x80) == 0) { // value is stored in 4 bytes. only use low 6 bits from 1st byte. return (((int_value & 0x3f) << 24) | (in.readUnsignedByte() << 16) | (in.readUnsignedByte() << 8) | (in.readUnsignedByte())); } else { // value is stored in 8 bytes. only use low 7 bits from 1st byte. return ((((long) (int_value & 0x7f)) << 56) | (((long) in.readUnsignedByte()) << 48) | (((long) in.readUnsignedByte()) << 40) | (((long) in.readUnsignedByte()) << 32) | (((long) in.readUnsignedByte()) << 24) | (((long) in.readUnsignedByte()) << 16) | (((long) in.readUnsignedByte()) << 8) | (((long) in.readUnsignedByte()))); } }
private static Node deserializeNode(DataInput input) throws IOException { int level = input.readUnsignedByte(); long value = input.readLong(); double weight = input.readDouble(); return new Node(value, level, weight); }
private Object read( DataInput objBuffer, Type propertyType, boolean array, UnrealPackageReadOnly.ExportEntry arrayInner, String structName, UnrealPackageReadOnly up) throws IOException { switch (propertyType) { case NONE: return null; case BYTE: return objBuffer.readUnsignedByte(); case INT: return objBuffer.readInt(); case BOOL: return array; case FLOAT: return objBuffer.readFloat(); case OBJECT: return objBuffer.readCompactInt(); case NAME: return objBuffer.readCompactInt(); case ARRAY: int arraySize = objBuffer.readCompactInt(); List<Object> arrayList = new ArrayList<>(arraySize); String a = arrayInner.getObjectClass().getObjectName().getName(); Property f = unrealClassLoader.getProperty(arrayInner.getObjectFullName()); array = false; arrayInner = null; structName = null; propertyType = Type.valueOf(a.replace("Property", "").toUpperCase()); if (propertyType == Type.STRUCT) { StructProperty structProperty = (StructProperty) f; structName = structProperty.getStructType().getObjectFullName(); } if (propertyType == Type.ARRAY) { array = true; ArrayProperty arrayProperty = (ArrayProperty) f; arrayInner = (UnrealPackageReadOnly.ExportEntry) arrayProperty.getInner(); } for (int i = 0; i < arraySize; i++) { arrayList.add(read(objBuffer, propertyType, array, arrayInner, structName, up)); } return arrayList; case STRUCT: return readStruct(objBuffer, structName, up); /*case VECTOR: return readStruct(objBuffer, "Vector", up); case ROTATOR: return readStruct(objBuffer, "Rotator", up);*/ case STR: return objBuffer.readLine(); default: throw new IllegalStateException("Unk type(" + structName + "): " + propertyType); } }
/** * Read an integer previously written by writeInt(). * * @exception IOException an exception was thrown by a method on in. */ public static final int readInt(DataInput in) throws IOException { int value = in.readUnsignedByte(); if ((value & ~0x3f) == 0) { // length is stored in this byte, we also know that the 0x80 bit // was not set, so no need to mask off the sign extension from // the byte to int conversion. // account for 1 byte stored length of field + 1 for all returns return (value); } else if ((value & 0x80) == 0) { // length is stored in 2 bytes. only use low 6 bits from 1st byte. if (SanityManager.DEBUG) { SanityManager.ASSERT((value & 0x40) == 0x40); } // top 8 bits of 2 byte length is stored in this byte, we also // know that the 0x80 bit was not set, so no need to mask off the // sign extension from the 1st byte to int conversion. Need to // mask the byte in data[offset + 1] to account for possible sign // extension. return (((value & 0x3f) << 8) | in.readUnsignedByte()); } else { // length is stored in 4 bytes. only use low 7 bits from 1st byte. if (SanityManager.DEBUG) { SanityManager.ASSERT((value & 0x80) == 0x80); } // top 8 bits of 4 byte length is stored in this byte, we also // know that the 0x80 bit was set, so need to mask off the // sign extension from the 1st byte to int conversion. Need to // mask the bytes from the next 3 bytes data[offset + 1,2,3] to // account for possible sign extension. // return (((value & 0x7f) << 24) | (in.readUnsignedByte() << 16) | (in.readUnsignedByte() << 8) | (in.readUnsignedByte())); } }
public static RNASequence readRNASequence(DataInput in) throws IOException { int size = in.readInt(); char[] chars = new char[size]; int completed = 0; while (completed < size) { int value = in.readUnsignedByte(); chars[completed++] = getUnserializedRNABase((value >> 6)); if (completed < size) { chars[completed++] = getUnserializedRNABase(((value >> 4) - ((value >> 6) << 2))); } if (completed < size) { chars[completed++] = getUnserializedRNABase(((value >> 2) - ((value >> 4) << 2))); } if (completed < size) { chars[completed++] = getUnserializedRNABase(((value) - ((value >> 2) << 2))); } } return new RNASequence(new String(chars)); }
private static int readPropertySize(int sizeType, DataInput dataInput) throws IOException { switch (sizeType) { case 0: return 1; case 1: return 2; case 2: return 4; case 3: return 12; case 4: return 16; case 5: return dataInput.readUnsignedByte(); case 6: return dataInput.readUnsignedShort(); case 7: return dataInput.readInt(); default: throw new IllegalArgumentException(); } }
public List<L2Property> readProperties( DataInput dataInput, String objClass, UnrealPackageReadOnly up) throws UnrealException { List<L2Property> properties = new ArrayList<>(); List<Property> classTemplate = unrealClassLoader.getStructProperties(objClass); Collections.reverse(classTemplate); try { String name; while (!(name = up.getNameTable().get(dataInput.readCompactInt()).getName()).equals("None")) { int info = dataInput.readUnsignedByte(); Type propertyType = Type.values()[info & 0b1111]; // TODO int sizeType = (info >> 4) & 0b111; boolean array = info >> 7 == 1; String structName = propertyType.equals(Type.STRUCT) ? up.getNameTable().get(dataInput.readCompactInt()).getName() : null; int size = readPropertySize(sizeType, dataInput); int arrayIndex = array && !propertyType.equals(Type.BOOL) ? dataInput.readCompactInt() : 0; byte[] objBytes = new byte[size]; dataInput.readFully(objBytes); final String n = name; PropertiesUtil.getAt(properties, n); L2Property property = PropertiesUtil.getAt(properties, n); if (property == null) { Property template = classTemplate .stream() .filter(pt -> pt.getEntry().getObjectName().getName().equalsIgnoreCase((n))) .findAny() .orElse(null); if (template == null) throw new UnrealException(objClass + ": Property template not found: " + name); property = new L2Property(template, up); properties.add(property); } if (structName != null && !"Vector".equals(structName) && !"Rotator".equals(structName) && !"Color".equals(structName)) { StructProperty structProperty = (StructProperty) property.getTemplate(); structName = structProperty.getStructType().getObjectFullName(); } UnrealPackageReadOnly.ExportEntry arrayInner = null; if (propertyType.equals(Type.ARRAY)) { ArrayProperty arrayProperty = (ArrayProperty) property.getTemplate(); arrayInner = (UnrealPackageReadOnly.ExportEntry) arrayProperty.getInner(); } DataInput objBuffer = new DataInputStream(new ByteArrayInputStream(objBytes), dataInput.getCharset()); property.putAt( arrayIndex, read( objBuffer, propertyType, array, arrayInner, structName, up, objClass, property.getName())); property.setType(propertyType); } } catch (IOException e) { throw new UnrealException(e); } return properties; }
public List<L2Property> readStructBin( DataInput objBuffer, String structName, UnrealPackageReadOnly up) throws UnrealException { List<Property> properties = unrealClassLoader.getStructProperties(structName); try { switch (structName) { case "Core.Object.Vector": { L2Property x = new L2Property(properties.get(0), up); x.putAt(0, objBuffer.readFloat()); L2Property y = new L2Property(properties.get(1), up); y.putAt(0, objBuffer.readFloat()); L2Property z = new L2Property(properties.get(2), up); z.putAt(0, objBuffer.readFloat()); return Arrays.asList(x, y, z); } case "Core.Object.Rotator": { L2Property pitch = new L2Property(properties.get(0), up); pitch.putAt(0, objBuffer.readInt()); L2Property yaw = new L2Property(properties.get(1), up); yaw.putAt(0, objBuffer.readInt()); L2Property roll = new L2Property(properties.get(2), up); roll.putAt(0, objBuffer.readInt()); return Arrays.asList(pitch, yaw, roll); } case "Core.Object.Color": { L2Property b = new L2Property(properties.get(0), up); b.putAt(0, objBuffer.readUnsignedByte()); L2Property g = new L2Property(properties.get(1), up); g.putAt(0, objBuffer.readUnsignedByte()); L2Property r = new L2Property(properties.get(2), up); r.putAt(0, objBuffer.readUnsignedByte()); L2Property a = new L2Property(properties.get(3), up); a.putAt(0, objBuffer.readUnsignedByte()); return Arrays.asList(b, g, r, a); } case "Fire.FireTexture.Spark": { L2Property type = new L2Property(properties.get(0), up); type.putAt(0, objBuffer.readUnsignedByte()); L2Property heat = new L2Property(properties.get(1), up); heat.putAt(0, objBuffer.readUnsignedByte()); L2Property x = new L2Property(properties.get(2), up); x.putAt(0, objBuffer.readUnsignedByte()); L2Property y = new L2Property(properties.get(3), up); y.putAt(0, objBuffer.readUnsignedByte()); L2Property byteA = new L2Property(properties.get(4), up); byteA.putAt(0, objBuffer.readUnsignedByte()); L2Property byteB = new L2Property(properties.get(5), up); byteB.putAt(0, objBuffer.readUnsignedByte()); L2Property byteC = new L2Property(properties.get(6), up); byteC.putAt(0, objBuffer.readUnsignedByte()); L2Property byteD = new L2Property(properties.get(7), up); byteD.putAt(0, objBuffer.readUnsignedByte()); return Arrays.asList(type, heat, x, y, byteA, byteB, byteC, byteD); } default: throw new UnsupportedOperationException("Not implemented"); // TODO } } catch (IOException e) { throw new UnrealException(e); } }
private List<Object> parse( byte[] bytes, IndexData globalSubrIndex, IndexData localSubrIndex, boolean init) throws IOException { if (init) { hstemCount = 0; vstemCount = 0; sequence = new ArrayList<Object>(); } DataInput input = new DataInput(bytes); boolean localSubroutineIndexProvided = localSubrIndex != null && localSubrIndex.getCount() > 0; boolean globalSubroutineIndexProvided = globalSubrIndex != null && globalSubrIndex.getCount() > 0; while (input.hasRemaining()) { int b0 = input.readUnsignedByte(); if (b0 == 10 && localSubroutineIndexProvided) { // process subr command Integer operand = (Integer) sequence.remove(sequence.size() - 1); // get subrbias int bias = 0; int nSubrs = localSubrIndex.getCount(); if (nSubrs < 1240) { bias = 107; } else if (nSubrs < 33900) { bias = 1131; } else { bias = 32768; } int subrNumber = bias + operand; if (subrNumber < localSubrIndex.getCount()) { byte[] subrBytes = localSubrIndex.getBytes(subrNumber); parse(subrBytes, globalSubrIndex, localSubrIndex, false); Object lastItem = sequence.get(sequence.size() - 1); if (lastItem instanceof CharStringCommand && ((CharStringCommand) lastItem).getKey().getValue()[0] == 11) { sequence.remove(sequence.size() - 1); // remove "return" command } } } else if (b0 == 29 && globalSubroutineIndexProvided) { // process globalsubr command Integer operand = (Integer) sequence.remove(sequence.size() - 1); // get subrbias int bias = 0; int nSubrs = globalSubrIndex.getCount(); if (nSubrs < 1240) { bias = 107; } else if (nSubrs < 33900) { bias = 1131; } else { bias = 32768; } int subrNumber = bias + operand; if (subrNumber < globalSubrIndex.getCount()) { byte[] subrBytes = globalSubrIndex.getBytes(subrNumber); parse(subrBytes, globalSubrIndex, localSubrIndex, false); Object lastItem = sequence.get(sequence.size() - 1); if (lastItem instanceof CharStringCommand && ((CharStringCommand) lastItem).getKey().getValue()[0] == 11) { sequence.remove(sequence.size() - 1); // remove "return" command } } } else if (b0 >= 0 && b0 <= 27) { sequence.add(readCommand(b0, input)); } else if (b0 == 28) { sequence.add(readNumber(b0, input)); } else if (b0 >= 29 && b0 <= 31) { sequence.add(readCommand(b0, input)); } else if (b0 >= 32 && b0 <= 255) { sequence.add(readNumber(b0, input)); } else { throw new IllegalArgumentException(); } } return sequence; }