001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.transformer.bytecode.literal; 020 021import lucee.commons.io.CharsetUtil; 022import lucee.commons.lang.ExceptionUtil; 023import lucee.commons.lang.StringUtil; 024import lucee.runtime.config.ConfigImpl; 025import lucee.runtime.op.Caster; 026import lucee.transformer.bytecode.BytecodeContext; 027import lucee.transformer.bytecode.BytecodeException; 028import lucee.transformer.bytecode.Literal; 029import lucee.transformer.bytecode.Page; 030import lucee.transformer.bytecode.Position; 031import lucee.transformer.bytecode.expression.ExprString; 032import lucee.transformer.bytecode.expression.ExpressionBase; 033import lucee.transformer.bytecode.op.OpString; 034import lucee.transformer.bytecode.util.Types; 035 036import org.objectweb.asm.Opcodes; 037import org.objectweb.asm.Type; 038import org.objectweb.asm.commons.GeneratorAdapter; 039 040/** 041 * A Literal String 042 */ 043public class LitString extends ExpressionBase implements Literal,ExprString { 044 045 public static final int MAX_SIZE = 65535; 046 public static final int TYPE_ORIGINAL = 0; 047 public static final int TYPE_UPPER = 1; 048 public static final int TYPE_LOWER = 2; 049 public static final LitString EMPTY = new LitString("",null,null); 050 051 private String str; 052 private boolean fromBracket; 053 054 public static ExprString toExprString(String str, Position start,Position end) { 055 return new LitString(str,start,end); 056 } 057 058 public static ExprString toExprString(String str) { 059 return new LitString(str,null,null); 060 } 061 062 public static LitString toLitString(String str) { 063 return new LitString(str,null,null); 064 } 065 066 /** 067 * constructor of the class 068 * @param str 069 * @param line 070 */ 071 public LitString(String str, Position start,Position end) { 072 super(start,end); 073 this.str=str; 074 } 075 076 /** 077 * @see lucee.transformer.bytecode.Literal#getString() 078 */ 079 public String getString() { 080 return str; 081 } 082 083 /** 084 * @throws BytecodeException 085 * @see lucee.transformer.bytecode.expression.Expression#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int) 086 */ 087 private static Type _writeOut(BytecodeContext bc, int mode,String str) throws BytecodeException { 088 // write to a file instead to the bytecode 089 // str(0,10); 090 //print.ds(str); 091 int externalizeStringGTE=((ConfigImpl)bc.getPageSource().getMapping().getConfig()).getExternalizeStringGTE(); 092 093 if(externalizeStringGTE>-1 && str.length()>externalizeStringGTE && StringUtil.indexOfIgnoreCase(bc.getMethod().getName(),"call")!=-1) { 094 try{ 095 GeneratorAdapter ga = bc.getAdapter(); 096 Page page = bc.getPage(); 097 Range range= page.registerString(bc,str); 098 ga.visitVarInsn(Opcodes.ALOAD, 0); 099 ga.visitVarInsn(Opcodes.ALOAD, 1); 100 ga.push(range.from); 101 ga.push(range.to); 102 ga.visitMethodInsn(Opcodes.INVOKEVIRTUAL, bc.getClassName(), "str", "(Llucee/runtime/PageContext;II)Ljava/lang/String;"); 103 return Types.STRING; 104 } 105 catch(Throwable t){ 106 ExceptionUtil.rethrowIfNecessary(t); 107 } 108 } 109 110 if(toBig(str)) { 111 _toExpr(str).writeOut(bc, mode); 112 } 113 else { 114 bc.getAdapter().push(str); 115 } 116 return Types.STRING; 117 } 118 119 private static ExprString _toExpr(String str) { 120 int size=str.length()/2; 121 String l = str.substring(0,size); 122 String r = str.substring(size); 123 ExprString left =toBig(l)? _toExpr(l):toExprString(l); 124 ExprString right =toBig(r)? _toExpr(r):toExprString(r); 125 return OpString.toExprString(left, right, false); 126 } 127 128 129 private static boolean toBig(String str) { 130 if(str.length()<(MAX_SIZE/2)) return false; // a char is max 2 bytes 131 return str.getBytes(CharsetUtil.UTF8).length>MAX_SIZE; 132 } 133 134 public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException { 135 return _writeOut(bc, mode, str); 136 } 137 138 public Type writeOut(BytecodeContext bc, int mode, int caseType) throws BytecodeException { 139 if(TYPE_UPPER==caseType) return _writeOut(bc, mode, str.toUpperCase()); 140 if(TYPE_LOWER==caseType) return _writeOut(bc, mode, str.toLowerCase()); 141 return _writeOut(bc, mode, str); 142 } 143 144 145 146 /** 147 * @see lucee.transformer.bytecode.Literal#getDouble(java.lang.Double) 148 */ 149 public Double getDouble(Double defaultValue) { 150 return Caster.toDouble(getString(),defaultValue); 151 } 152 153 /** 154 * @see lucee.transformer.bytecode.Literal#getBoolean(java.lang.Boolean) 155 */ 156 public Boolean getBoolean(Boolean defaultValue) { 157 return Caster.toBoolean(getString(),defaultValue); 158 } 159 160 161 /** 162 * 163 * @see java.lang.Object#equals(java.lang.Object) 164 */ 165 public boolean equals(Object obj) { 166 if(this==obj) return true; 167 if(!(obj instanceof LitString)) return false; 168 return str.equals(((LitString)obj).str); 169 } 170 171 /** 172 * 173 * @see java.lang.Object#toString() 174 */ 175 public String toString() { 176 return str; 177 } 178 179 public void upperCase() { 180 str=str.toUpperCase(); 181 } 182 public void lowerCase() { 183 str=str.toLowerCase(); 184 } 185 186 public LitString duplicate() { 187 return new LitString(str,getStart(),getEnd()); 188 } 189 190 public void fromBracket(boolean fromBracket) { 191 this.fromBracket=fromBracket; 192 } 193 public boolean fromBracket() { 194 return fromBracket; 195 } 196 197 198 public static class Range { 199 200 public final int from; 201 public final int to; 202 203 public Range(int from, int to) { 204 this.from=from; 205 this.to=to; 206 } 207 public String toString(){ 208 return "from:"+from+";to:"+to+";"; 209 } 210 211 } 212 213 /* * 214 * @see lucee.transformer.bytecode.expression.Expression#getType() 215 * / 216 public int getType() { 217 return Types._STRING; 218 }*/ 219}