1 21 package proguard.classfile.constant; 22 23 import proguard.classfile.*; 24 import proguard.classfile.constant.visitor.ConstantVisitor; 25 26 import java.io.*; 27 28 33 public class Utf8Constant extends Constant 34 { 35 private static final String ENCODING = "UTF-8"; 36 37 private static final char TWO_BYTE_LIMIT = 0x80; 38 private static final byte TWO_BYTE_CONSTANT1 = (byte)0xc0; 39 private static final byte TWO_BYTE_CONSTANT2 = (byte)0x80; 40 private static final int TWO_BYTE_SHIFT1 = 6; 41 private static final byte TWO_BYTE_MASK1 = (byte)0x1f; 42 private static final byte TWO_BYTE_MASK2 = (byte)0x3f; 43 44 private static final char THREE_BYTE_LIMIT = 0x800; 45 private static final byte THREE_BYTE_CONSTANT1 = (byte)0xe0; 46 private static final byte THREE_BYTE_CONSTANT2 = (byte)0x80; 47 private static final byte THREE_BYTE_CONSTANT3 = (byte)0x80; 48 private static final int THREE_BYTE_SHIFT1 = 12; 49 private static final int THREE_BYTE_SHIFT2 = 6; 50 private static final byte THREE_BYTE_MASK1 = (byte)0x0f; 51 private static final byte THREE_BYTE_MASK2 = (byte)0x3f; 52 private static final byte THREE_BYTE_MASK3 = (byte)0x3f; 53 54 55 60 private byte[] bytes; 62 63 private String utf8string; 64 65 66 70 public Utf8Constant() 71 { 72 } 73 74 75 78 public Utf8Constant(String utf8string) 79 { 80 this.bytes = null; 81 this.utf8string = utf8string; 82 } 83 84 85 88 public void setBytes(byte[] bytes) 89 { 90 this.bytes = bytes; 91 this.utf8string = null; 92 } 93 94 95 98 public byte[] getBytes() 99 { 100 try 101 { 102 return getByteArrayRepresentation(); 103 } 104 catch (UnsupportedEncodingException ex) 105 { 106 throw new RuntimeException (ex.getMessage()); 107 } 108 } 109 110 111 114 public void setString(String utf8String) 115 { 116 this.bytes = null; 117 this.utf8string = utf8String; 118 } 119 120 121 124 public String getString() 125 { 126 try 127 { 128 switchToStringRepresentation(); 129 } 130 catch (UnsupportedEncodingException ex) 131 { 132 throw new RuntimeException (ex.getMessage()); 133 } 134 135 return utf8string; 136 } 137 138 140 public int getTag() 141 { 142 return ClassConstants.CONSTANT_Utf8; 143 } 144 145 public void accept(Clazz clazz, ConstantVisitor constantVisitor) 146 { 147 constantVisitor.visitUtf8Constant(clazz, this); 148 } 149 150 151 154 private void switchToStringRepresentation() throws UnsupportedEncodingException 155 { 156 if (utf8string == null) 157 { 158 utf8string = new String (bytes, ENCODING); 159 bytes = null; 160 } 161 } 162 163 164 168 private byte[] getByteArrayRepresentation() throws UnsupportedEncodingException 169 { 170 if (bytes != null) 172 { 173 return bytes; 175 } 176 177 181 int byteLength = 0; 183 int stringLength = utf8string.length(); 184 for (int stringIndex = 0; stringIndex < stringLength; stringIndex++) 185 { 186 char c = utf8string.charAt(stringIndex); 187 188 byteLength += c == 0 ? 2 : 190 c < TWO_BYTE_LIMIT ? 1 : 191 c < THREE_BYTE_LIMIT ? 2 : 192 3; 193 } 194 195 byte[] bytes = new byte[byteLength]; 197 198 int byteIndex = 0; 200 for (int stringIndex = 0; stringIndex < stringLength; stringIndex++) 201 { 202 char c = utf8string.charAt(stringIndex); 203 if (c == 0) 204 { 205 bytes[byteIndex++] = TWO_BYTE_CONSTANT1; 207 bytes[byteIndex++] = TWO_BYTE_CONSTANT2; 208 } 209 else if (c < TWO_BYTE_LIMIT) 210 { 211 bytes[byteIndex++] = (byte)c; 213 } 214 else if (c < THREE_BYTE_LIMIT) 215 { 216 bytes[byteIndex++] = (byte)(TWO_BYTE_CONSTANT1 | ((c >>> TWO_BYTE_SHIFT1) & TWO_BYTE_MASK1)); 218 bytes[byteIndex++] = (byte)(TWO_BYTE_CONSTANT2 | ( c & TWO_BYTE_MASK2)); 219 } 220 else 221 { 222 bytes[byteIndex++] = (byte)(THREE_BYTE_CONSTANT1 | ((c >>> THREE_BYTE_SHIFT1) & THREE_BYTE_MASK1)); 224 bytes[byteIndex++] = (byte)(THREE_BYTE_CONSTANT2 | ((c >>> THREE_BYTE_SHIFT2) & THREE_BYTE_MASK2)); 225 bytes[byteIndex++] = (byte)(THREE_BYTE_CONSTANT3 | ( c & THREE_BYTE_MASK3)); 226 } 227 } 228 229 return bytes; 230 } 231 } 232 | Popular Tags |