public static ClassNode ParseClass(Stream stream) { var state = new ClassReaderState(); var result = new ClassNode(); state.ClassNode = result; if (Binary.BigEndian.ReadUInt32(stream) != Magic) { throw new IOException("Wrong magic in class"); } result.MinorVersion = Binary.BigEndian.ReadUInt16(stream); result.MajorVersion = (ClassVersion)Binary.BigEndian.ReadUInt16(stream); if (result.MajorVersion > ClassVersion.Java8) { throw new Exception($"Wrong Java version: {result.MajorVersion}"); } var constantPool = new ConstantPool(); constantPool.Read(stream); state.ConstantPool = constantPool; result.Access = (ClassAccessModifiers)Binary.BigEndian.ReadUInt16(stream); result.Name = new ClassName(constantPool.GetEntry <ClassEntry>(Binary.BigEndian.ReadUInt16(stream)).Name.String); result.SuperName = new ClassName(constantPool.GetEntry <ClassEntry>(Binary.BigEndian.ReadUInt16(stream)).Name.String); var interfacesCount = Binary.BigEndian.ReadUInt16(stream); result.Interfaces.Capacity = interfacesCount; for (var i = 0; i < interfacesCount; i++) { result.Interfaces.Add(new ClassName(constantPool.GetEntry <ClassEntry>(Binary.BigEndian.ReadUInt16(stream)).Name.String)); } var fieldsCount = Binary.BigEndian.ReadUInt16(stream); result.Fields.Capacity = fieldsCount; for (var i = 0; i < fieldsCount; i++) { result.Fields.Add(ParseField(stream, state)); } var methodsCount = Binary.BigEndian.ReadUInt16(stream); result.Methods.Capacity = methodsCount; for (var i = 0; i < methodsCount; i++) { result.Methods.Add(ParseMethod(stream, state)); } var attributesCount = Binary.BigEndian.ReadUInt16(stream); result.Attributes.Capacity = attributesCount; for (var i = 0; i < attributesCount; i++) { result.Attributes.Add(ParseAttribute(stream, state, AttributeScope.Class)); } result.Parse(state); return(result); }
public static void WriteClass(Stream stream, ClassNode classNode) { Binary.BigEndian.Write(stream, Magic); Binary.BigEndian.Write(stream, classNode.MinorVersion); Binary.BigEndian.Write(stream, (ushort)classNode.MajorVersion); var afterConstantPoolDataStream = new MemoryStream(); var constantPool = new ConstantPool(); var state = new ClassWriterState { ClassNode = classNode, ConstantPool = constantPool }; classNode.Save(state); Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Access); Binary.BigEndian.Write(afterConstantPoolDataStream, constantPool.Find(new ClassEntry(new Utf8Entry(classNode.Name.Name)))); Binary.BigEndian.Write(afterConstantPoolDataStream, constantPool.Find(new ClassEntry(new Utf8Entry(classNode.SuperName.Name)))); if (classNode.Interfaces.Count > ushort.MaxValue) { throw new ArgumentOutOfRangeException(nameof(classNode.Interfaces.Count), $"Too many interfaces: {classNode.Interfaces.Count} > {ushort.MaxValue}"); } Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Interfaces.Count); foreach (var interfaceClassName in classNode.Interfaces) { Binary.BigEndian.Write(afterConstantPoolDataStream, constantPool.Find(new ClassEntry(new Utf8Entry(interfaceClassName.Name)))); } if (classNode.Fields.Count > ushort.MaxValue) { throw new ArgumentOutOfRangeException(nameof(classNode.Fields.Count), $"Too many fields: {classNode.Fields.Count} > {ushort.MaxValue}"); } Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Fields.Count); foreach (var field in classNode.Fields) { WriteField(afterConstantPoolDataStream, field, state); } if (classNode.Methods.Count > ushort.MaxValue) { throw new ArgumentOutOfRangeException(nameof(classNode.Methods.Count), $"Too many methods: {classNode.Methods.Count} > {ushort.MaxValue}"); } Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Methods.Count); foreach (var method in classNode.Methods) { WriteMethod(afterConstantPoolDataStream, method, state); } if (classNode.Attributes.Count > ushort.MaxValue) { throw new ArgumentOutOfRangeException(nameof(classNode.Attributes.Count), $"Too many attributes: {classNode.Attributes.Count} > {ushort.MaxValue}"); } Binary.BigEndian.Write(afterConstantPoolDataStream, (ushort)classNode.Attributes.Count); foreach (var attriute in classNode.Attributes) { WriteAttribute(afterConstantPoolDataStream, attriute, state, AttributeScope.Class); } constantPool.Write(stream); stream.Write(afterConstantPoolDataStream.ToArray()); }