Java tutorial
/* * The MIT License (MIT) * * Copyright (c) 2015 The MsgCodec Authors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.cinnober.msgcodec.blink; import com.cinnober.msgcodec.GroupDef; import com.cinnober.msgcodec.Schema; import com.cinnober.msgcodec.TypeDef; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import static org.objectweb.asm.Opcodes.ACC_PRIVATE; import static org.objectweb.asm.Opcodes.ALOAD; import static org.objectweb.asm.Opcodes.ATHROW; import static org.objectweb.asm.Opcodes.DUP; import static org.objectweb.asm.Opcodes.ICONST_0; import static org.objectweb.asm.Opcodes.INVOKESPECIAL; import static org.objectweb.asm.Opcodes.INVOKESTATIC; import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; import static org.objectweb.asm.Opcodes.NEW; import static org.objectweb.asm.Opcodes.RETURN; /** * * @author mikael.brannstrom */ class NativeByteCodeGenerator extends BaseByteCodeGenerator { public NativeByteCodeGenerator() { super(GeneratedNativeCodec.class, NativeBlinkCodec.class, NativeBlinkInput.class, NativeBlinkOutput.class); } // --- GENERATE WRITE ---------------------------------------------------------------------------------------------- @Override protected void generateWriteStaticGroupForTypeWithId(Schema schema, ClassVisitor cv, String genClassInternalName, boolean javaClassCodec) { for (GroupDef group : schema.getGroups()) { Object groupType = group.getGroupType(); String groupDescriptor = getTypeDescriptor(groupType, javaClassCodec); MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "writeStaticGroupWithId_" + group.getName(), "(Lcom/cinnober/msgcodec/io/ByteSink;" + groupDescriptor + ")V", null, new String[] { "java/io/IOException" }); mv.visitCode(); int nextWriteidVar = 3; if (group.getId() != -1) { // write with id mv.visitVarInsn(ALOAD, 1); // out mv.visitLdcInsn(group.getId() & 0xffffffffL); mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeUInt64", "(Lcom/cinnober/msgcodec/io/ByteSink;J)V", false); // add extension offset (four zero bytes) mv.visitVarInsn(ALOAD, 1); // out mv.visitInsn(ICONST_0); generateEncodeUInt32Value(true, mv); mv.visitVarInsn(ALOAD, 0); // this mv.visitVarInsn(ALOAD, 1); // out mv.visitVarInsn(ALOAD, 2); // obj mv.visitMethodInsn(INVOKEVIRTUAL, genClassInternalName, "writeStaticGroup_" + group.getName(), "(Lcom/cinnober/msgcodec/io/ByteSink;" + groupDescriptor + ")V", false); mv.visitInsn(RETURN); } else { // write with id mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException"); mv.visitInsn(DUP); mv.visitLdcInsn("No group id"); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V", false); mv.visitInsn(ATHROW); } // end mv.visitMaxs(3, nextWriteidVar); mv.visitEnd(); } } // --- GENERATE ENCODE VALUE --------------------------------------------------------------------------------------- @Override protected void generateEncodeBinaryValue(TypeDef.Binary type, boolean required, MethodVisitor mv) { if (Integer.compareUnsigned(type.getMaxSize(), 255) <= 0) { // inline mv.visitLdcInsn(type.getMaxSize()); if (required) { mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeInlineBinary", "(Lcom/cinnober/msgcodec/io/ByteSink;[BI)V", false); } else { mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeInlineBinaryNull", "(Lcom/cinnober/msgcodec/io/ByteSink;[BI)V", false); } } else { // data area // cast bytesink to ByteBuf, set position to data area, etc throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } } @Override protected void generateEncodeStringValue(TypeDef.StringUnicode type, boolean required, MethodVisitor mv) { if (Integer.compareUnsigned(type.getMaxSize(), 255) <= 0) { // inline mv.visitLdcInsn(type.getMaxSize()); if (required) { mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeInlineStringUTF8", "(Lcom/cinnober/msgcodec/io/ByteSink;Ljava/lang/String;I)V", false); } else { mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeStringUTF8Null", "(Lcom/cinnober/msgcodec/io/ByteSink;Ljava/lang/String;I)V", false); } } else { // data area throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } } @Override protected void generateEncodeBigDecimalValue(boolean required, MethodVisitor mv) { throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } @Override protected void generateEncodeBigIntValue(boolean required, MethodVisitor mv) { throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } /** * Generate value encoding using the blink output. * * <p>Defaults to <code>writeDynamicGroup[Null]</code> in the generated codec. * * @param required true if the field is required, otherwise false. * @param mv the method visitor, not null. * @see #generateEncodeValue */ @Override protected void generateEncodeDynRefValue(LocalVariable nextVar, MethodVisitor mv, boolean required) { throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } @Override protected void generateEncodeSequenceValue(Class<?> javaClass, LocalVariable nextVar, MethodVisitor mv, boolean required, int outputStreamVar, Class<?> componentJavaClass, TypeDef type, Schema schema, String genClassInternalName, String fieldIdentifier, String debugValueLabel, boolean javaClassCodec) throws IllegalArgumentException { throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } // --- GENERATE DECODE VALUE --------------------------------------------------------------------------------------- /** * Generate value decoding using the blink input. * * <p>Defaults to <code>readBinary[Null].</code> * * @param required true if the field is required, otherwise false. * @param mv the method visitor, not null. * @see #generateDecodeValue */ @Override protected void generateDecodeBinaryValue(TypeDef.Binary type, MethodVisitor mv, boolean required) { if (Integer.compareUnsigned(type.getMaxSize(), 255) <= 0) { // inline mv.visitLdcInsn(type.getMaxSize()); if (required) { mv.visitMethodInsn(INVOKESTATIC, blinkInputIName, "readBinary", "(Lcom/cinnober/msgcodec/io/ByteSource;I)[B", false); } else { mv.visitMethodInsn(INVOKESTATIC, blinkInputIName, "readBinaryNull", "(Lcom/cinnober/msgcodec/io/ByteSource;I)[B", false); } } else { // data area throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } } /** * Generate value decoding using the blink input. * * <p>Defaults to <code>readStringUTF8[Null].</code> * * @param required true if the field is required, otherwise false. * @param mv the method visitor, not null. * @see #generateDecodeValue */ @Override protected void generateDecodeStringValue(TypeDef.StringUnicode type, MethodVisitor mv, boolean required) { if (Integer.compareUnsigned(type.getMaxSize(), 255) <= 0) { // inline mv.visitLdcInsn(type.getMaxSize()); if (required) { mv.visitMethodInsn(INVOKESTATIC, blinkInputIName, "readInlineStringUTF8", "(Lcom/cinnober/msgcodec/io/ByteSource;I)Ljava/lang/String;", false); } else { mv.visitMethodInsn(INVOKESTATIC, blinkInputIName, "readInlineStringUTF8Null", "(Lcom/cinnober/msgcodec/io/ByteSource;I)Ljava/lang/String;", false); } } else { // data area throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } } /** * Generate value decoding using the blink input. * * <p>Defaults to <code>readBigDecimal[Null].</code> * * @param required true if the field is required, otherwise false. * @param mv the method visitor, not null. * @see #generateDecodeValue */ @Override protected void generateDecodeBigDecimalValue(boolean required, MethodVisitor mv) { throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } /** * Generate value decoding using the blink input. * * <p>Defaults to <code>readBigInt[Null].</code> * * @param required true if the field is required, otherwise false. * @param mv the method visitor, not null. * @see #generateDecodeValue */ @Override protected void generateDecodeBigIntValue(boolean required, MethodVisitor mv) { throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } @Override protected void generateDecodeDynRefValue(MethodVisitor mv, boolean required, GroupDef refGroup, Class<?> javaClass) { throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } @Override protected void generateDecodeSequenceValue(Class<?> javaClass, LocalVariable nextVar, boolean required, MethodVisitor mv, Class<?> componentJavaClass, int byteSourceVar, TypeDef type, Schema schema, String genClassInternalName, String fieldIdentifier, String debugValueLabel, boolean javaClassCodec) throws IllegalArgumentException { throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area } }