001 package railo.transformer.bytecode.statement; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 006 import org.objectweb.asm.Label; 007 import org.objectweb.asm.commons.GeneratorAdapter; 008 009 import railo.transformer.bytecode.Body; 010 import railo.transformer.bytecode.BytecodeContext; 011 import railo.transformer.bytecode.BytecodeException; 012 import railo.transformer.bytecode.Statement; 013 import railo.transformer.bytecode.util.ExpressionUtil; 014 015 public final class NativeSwitch extends StatementBase implements FlowControl,HasBodies { 016 017 public static final short LOCAL_REF=0; 018 public static final short ARG_REF=1; 019 public static final short PRIMITIVE=1; 020 021 022 private int value; 023 private Label end; 024 private Statement defaultCase; 025 ArrayList cases=new ArrayList(); 026 private Label[] labels=new Label[0]; 027 private int[] values=new int[0]; 028 private short type; 029 030 public NativeSwitch(int value, short type, int startline,int endline) { 031 super(startline, endline); 032 this.value=value; 033 this.type=type; 034 } 035 036 public void _writeOut(BytecodeContext bc) throws BytecodeException { 037 end = new Label(); 038 GeneratorAdapter adapter = bc.getAdapter(); 039 040 if(type==LOCAL_REF) adapter.loadLocal(value); 041 else if(type==ARG_REF) adapter.loadArg(value); 042 else adapter.push(value); 043 044 Label beforeDefault = new Label(); 045 adapter.visitLookupSwitchInsn(beforeDefault, values, labels); 046 047 Iterator it = cases.iterator(); 048 Case c; 049 while(it.hasNext()) { 050 c=((Case) it.next()); 051 adapter.visitLabel(c.label); 052 ExpressionUtil.visitLine(bc, c.startline); 053 c.body.writeOut(bc); 054 ExpressionUtil.visitLine(bc, c.endline); 055 if(c.doBreak){ 056 adapter.goTo(end); 057 } 058 } 059 060 061 adapter.visitLabel(beforeDefault); 062 if(defaultCase!=null)defaultCase.writeOut(bc); 063 adapter.visitLabel(end); 064 065 } 066 067 public void addCase(int value, Statement body,int startline,int endline,boolean doBreak) { 068 069 Case nc = new Case(value,body,startline,endline,doBreak); 070 071 Label[] labelsTmp = new Label[cases.size()+1]; 072 int[] valuesTmp = new int[cases.size()+1]; 073 074 int count=0; 075 boolean hasAdd=false; 076 for(int i=0;i<labels.length;i++) { 077 if(!hasAdd && nc.value<values[i]) { 078 labelsTmp[count]=nc.label; 079 valuesTmp[count]=nc.value; 080 count++; 081 hasAdd=true; 082 } 083 labelsTmp[count]=labels[i]; 084 valuesTmp[count]=values[i]; 085 count++; 086 } 087 if(!hasAdd) { 088 labelsTmp[labels.length]=nc.label; 089 valuesTmp[values.length]=nc.value; 090 } 091 labels=labelsTmp; 092 values=valuesTmp; 093 094 095 cases.add(nc); 096 } 097 098 public void addDefaultCase(Statement defaultStatement) { 099 this.defaultCase=defaultStatement; 100 } 101 102 class Case { 103 104 public boolean doBreak; 105 private int value; 106 private Statement body; 107 private Label label=new Label(); 108 private int startline; 109 private int endline; 110 111 public Case(int value, Statement body,int startline,int endline, boolean doBreak) { 112 this.value=value; 113 this.body=body; 114 this.startline=startline; 115 this.endline=endline; 116 this.doBreak=doBreak; 117 } 118 119 } 120 121 /** 122 * 123 * @see railo.transformer.bytecode.statement.FlowControl#getBreakLabel() 124 */ 125 public Label getBreakLabel() { 126 return end; 127 } 128 129 /** 130 * 131 * @see railo.transformer.bytecode.statement.FlowControl#getContinueLabel() 132 */ 133 public Label getContinueLabel() { 134 return end; 135 } 136 137 /** 138 * @see railo.transformer.bytecode.statement.HasBodies#getBodies() 139 */ 140 public Body[] getBodies() { 141 if(cases==null) { 142 if(defaultCase!=null) return new Body[]{(Body) defaultCase}; 143 return new Body[]{}; 144 } 145 146 int len=cases.size(),count=0; 147 if(defaultCase!=null)len++; 148 Body[] bodies=new Body[len]; 149 Case c; 150 Iterator it = cases.iterator(); 151 while(it.hasNext()) { 152 c=(Case) it.next(); 153 bodies[count++]=(Body) c.body; 154 } 155 if(defaultCase!=null)bodies[count++]=(Body) defaultCase; 156 157 return bodies; 158 } 159 }