package com.intellij.flex.uiDesigner.abc; import gnu.trove.TIntObjectHashMap; import static com.intellij.flex.uiDesigner.abc.ActionBlockConstants.*; class ConstantPool { final DataBuffer in; private int size; final int[][] positions = new int[7][]; final int[] ends = new int[7]; TIntObjectHashMap<byte[]> modifiedMethodBodies; int totalSize; public ConstantPool(DataBuffer in) { this.in = in; for (int i = 0; i < 7; i++) { switch (i) { case IndexHistory.INT: case IndexHistory.UINT: positions[i] = Scanner.scanIntConstants(in); break; case IndexHistory.DOUBLE: positions[i] = Scanner.scanDoubleConstants(in); break; case IndexHistory.STRING: positions[i] = Scanner.scanStrConstants(in); break; case IndexHistory.NS: positions[i] = Scanner.scanNsConstants(in); break; case IndexHistory.NS_SET: positions[i] = Scanner.scanNsSetConstants(in); break; case IndexHistory.MULTINAME: positions[i] = Scanner.scanMultinameConstants(in); break; } ends[i] = in.position(); size += positions[i].length == 0 ? 0 : positions[i].length - 1; } } public int size() { return size; } } final class NSPool extends PoolPart { NSPool(int poolPartLength) { super(poolPartLength); } @Override ByteArray createByteArray() { return new NS(); } } final class NS extends ByteArray { int nsKind = 0; int index = 0; @Override void init() { int originalPos = data.position(); data.seek(start); nsKind = data.readU8(); switch (nsKind) { case CONSTANT_PrivateNamespace: case CONSTANT_Namespace: case CONSTANT_PackageNamespace: case CONSTANT_PackageInternalNs: case CONSTANT_ProtectedNamespace: case CONSTANT_ExplicitNamespace: case CONSTANT_StaticProtectedNs: index = data.readU32(); break; default: assert false; // can't possibly happen... } data.seek(originalPos); long num = 1234 ^ nsKind ^ index; hash = (int)((num >> 32) ^ num); } @Override void clear() { super.clear(); nsKind = 0; index = 0; } public boolean equals(Object obj) { if (obj instanceof NS) { NS ns = (NS)obj; if (nsKind == CONSTANT_PrivateNamespace) { // Private namespaces are only equal if they are literally the same namespace, // the name is not important. return data == ns.data && start == ns.start && end == ns.end; } else { return ns.nsKind == nsKind && ns.index == index; } } return false; } } final class NSSPool extends PoolPart { NSSPool(int poolPartLength) { super(poolPartLength); } @Override ByteArray createByteArray() { return new NSS(); } private static final class NSS extends ByteArray { private int[] set; private int size; @Override void init() { int originalPos = data.position(); data.seek(start); int count = data.readU32(); if (set == null || count > set.length) { set = new int[count]; } size = count; for (int k = 0; k < count; k++) { set[k] = data.readU32(); } data.seek(originalPos); long num = 1234; for (int k = 0; k < count; k++) { num ^= set[k]; } hash = (int)((num >> 32) ^ num); } @Override void clear() { super.clear(); size = 0; } public boolean equals(Object obj) { if (obj instanceof NSS) { NSS nss = (NSS)obj; if (size == nss.size) { for (int i = 0; i < size; i++) { if (set[i] != nss.set[i]) { return false; } } return true; } else { return false; } } else { return false; } } } } final class MultiNamePool extends PoolPart { public MultiNamePool(int poolPartLength) { super(poolPartLength); } @Override ByteArray createByteArray() { return new MultinameByteArray(); } } final class MultinameByteArray extends ByteArray { int constKind = 0, index1 = 1, index2 = 1; @Override void init() { data.seek(start); constKind = data.readU8(); switch (constKind) { case CONSTANT_Qname: case CONSTANT_QnameA: { index1 = data.readU32(); index2 = data.readU32(); long num = 1234 ^ constKind ^ index1 ^ index2; hash = (int)((num >> 32) ^ num); break; } case CONSTANT_Multiname: case CONSTANT_MultinameA: { index1 = data.readU32(); index2 = data.readU32(); long num = 1234 ^ constKind ^ index1 ^ index2; hash = (int)((num >> 32) ^ num); break; } case CONSTANT_RTQname: case CONSTANT_RTQnameA: { index1 = data.readU32(); long num = 1234 ^ constKind ^ index1; hash = (int)((num >> 32) ^ num); break; } case CONSTANT_RTQnameL: case CONSTANT_RTQnameLA: { long num = 1234 ^ constKind; hash = (int)((num >> 32) ^ num); break; } case CONSTANT_MultinameL: case CONSTANT_MultinameLA: { index1 = data.readU32(); long num = 1234 ^ constKind ^ index1; hash = (int)((num >> 32) ^ num); break; } case CONSTANT_TypeName: { index1 = data.readU32(); data.readU32(); // Only 1 typeparam for now. index2 = data.readU32(); long num = 1234 ^ constKind ^ index1 ^ index2; hash = (int)((num >> 32) ^ num); break; } default: assert false; // can't possibly happen... } } @Override void clear() { super.clear(); constKind = 0; index1 = 0; index2 = 0; } public boolean equals(Object obj) { if (obj instanceof MultinameByteArray) { MultinameByteArray mn = (MultinameByteArray)obj; switch (constKind) { case CONSTANT_Qname: case CONSTANT_QnameA: case CONSTANT_Multiname: case CONSTANT_MultinameA: { return (constKind == mn.constKind) && (index1 == mn.index1) && (index2 == mn.index2); } case CONSTANT_RTQname: case CONSTANT_RTQnameA: { return (constKind == mn.constKind) && (index1 == mn.index1); } case CONSTANT_RTQnameL: case CONSTANT_RTQnameLA: return (constKind == mn.constKind); case CONSTANT_MultinameL: case CONSTANT_MultinameLA: { return (constKind == mn.constKind) && (index1 == mn.index1); } case CONSTANT_TypeName: { return (constKind == mn.constKind && index1 == mn.index1 && index2 == mn.index2); } default: return false; } } else { return false; } } }