/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package macromedia.abc;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_Decimal;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_Double;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_ExplicitNamespace;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_False;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_Integer;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_Multiname;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_MultinameA;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_MultinameL;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_MultinameLA;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_TypeName;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_Namespace;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_Namespace_Set;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_Null;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_PackageInternalNs;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_PackageNamespace;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_PrivateNamespace;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_ProtectedNamespace;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_Qname;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_QnameA;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_RTQname;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_RTQnameA;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_RTQnameL;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_RTQnameLA;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_StaticProtectedNs;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_True;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_UInteger;
import static macromedia.asc.embedding.avmplus.ActionBlockConstants.CONSTANT_Utf8;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import macromedia.asc.util.Decimal128;
import macromedia.asc.util.IntegerPool;
import macromedia.asc.util.IntList;
/**
* Constant {
* U8 kind
* union {
* kind=1 { // CONSTANT_utf8
* U16 length
* U8[length]
* }
* kind=2 { // CONSTANT_Decimal
* U8[16] value
* }
* kind=3 { // CONSTANT_Integer
* S32 value
* }
* kind=4 { // CONSTANT_UInteger
* U32 value
* }
* kind=6 { // CONSTANT_Double
* U64 doublebits (little endian)
* }
* kind=7,13 { // CONSTANT_Qname + CONSTANT_QnameA
* U16 namespace_index // CONSTANT_Namespace, 0=AnyNamespace wildcard
* U16 name_index // CONSTANT_Utf8, 0=AnyName wildcard
* }
* kind=8,5 { // CONSTANT_Namespace, CONSTANT_PrivateNamespace
* U16 name_index // CONSTANT_Utf8 uri (maybe 0)
* }
* kind=9,14 { // CONSTANT_Multiname, CONSTANT_MultinameA
* U16 name_index // CONSTANT_Utf8 simple name. 0=AnyName wildcard
* U16 namespaces_count // (256 may seem like enough, but 64K use to seem like a lot of memory)
* U16 namespaces[namespaces_count] // CONSTANT_Namespace (0 = error)
* }
* kind=10 // CONSTANT_False
* kind=11 // CONSTANT_True
* kind=12 // CONSTANT_Null
* kind=15,16 { // CONSTANT_RTQname + CONSTANT_RTQnameA
* U16 name_index // CONSTANT_utf8, 0=AnyName wildcard
* }
* kind=17,18 // CONSTANT_RTQnameL + CONSTANT_RTQnameLA
* }
* }
*
* @author Clement Wong
*/
public class ConstantPool
{
public static final Object NULL = new Object();
public boolean poolHasDecimal;
public static ConstantPool merge(ConstantPool[] pools)
{
// create a new ConstantPool big enough for the combined pools.
int preferredSize = 0;
boolean hasDecimal = false;
for (int i = 0, size = pools.length; i < size; i++)
{
if (pools[i].decimalpositions.length > 0)
hasDecimal = true;
preferredSize += pools[i].mnEnd;
}
ConstantPool newPool = new ConstantPool(hasDecimal); // make room for decimal in the one we create
newPool.in = new BytecodeBuffer(preferredSize);
newPool.history = new IndexHistory(pools, hasDecimal);
return newPool;
}
ConstantPool(boolean hasDecimal)
{
poolHasDecimal = hasDecimal;
}
public ConstantPool(BytecodeBuffer in, boolean hasDecimal) throws DecoderException
{
this.in = in;
poolHasDecimal = hasDecimal;
scan();
}
private void scan() throws DecoderException
{
intpositions = Scanner.scanIntConstants(in);
intEnd = in.pos();
uintpositions = Scanner.scanUIntConstants(in);
uintEnd = in.pos();
doublepositions = Scanner.scanDoubleConstants(in);
doubleEnd = in.pos();
if (poolHasDecimal) {
decimalpositions = Scanner.scanDecimalConstants(in);
decimalEnd = in.pos();
} else {
decimalpositions = new int[0];
decimalEnd = in.pos();
}
strpositions = Scanner.scanStrConstants(in);
strEnd = in.pos();
nspositions = Scanner.scanNsConstants(in);
nsEnd = in.pos();
nsspositions = Scanner.scanNsSetConstants(in);
nssEnd = in.pos();
mnpositions = Scanner.scanMultinameConstants(in);
mnEnd = in.pos();
size = ((intpositions.length == 0) ? 0 : (intpositions.length - 1)) +
((uintpositions.length == 0) ? 0: (uintpositions.length - 1)) +
((doublepositions.length == 0) ? 0 : (doublepositions.length - 1)) +
((decimalpositions.length == 0) ? 0 : (decimalpositions.length - 1)) +
((strpositions.length == 0) ? 0 : (strpositions.length - 1)) +
((nspositions.length == 0) ? 0 : (nspositions.length - 1)) +
((nsspositions.length == 0) ? 0 : (nsspositions.length - 1)) +
((mnpositions.length == 0) ? 0 : (mnpositions.length - 1));
}
BytecodeBuffer in;
IndexHistory history;
private int size;
int[] intpositions;
int[] uintpositions;
int[] doublepositions;
int[] decimalpositions;
int[] strpositions;
int[] nspositions;
int[] nsspositions;
int[] mnpositions;
int intEnd;
int uintEnd;
int doubleEnd;
int decimalEnd;
int strEnd;
int nsEnd;
int nssEnd;
int mnEnd;
public int size()
{
return size;
}
public int getInt(int index)
{
if (index == 0)
{
return 0;
}
int pos = intpositions[index];
int originalPos = in.pos();
in.seek(pos);
int value = in.readU32();
in.seek(originalPos);
return value;
}
public long getLong(int index)
{
if (index == 0)
{
return 0;
}
int pos = uintpositions[index];
int originalPos = in.pos();
in.seek(pos);
long value = in.readU32();
in.seek(originalPos);
return value;
}
public double getDouble(int index)
{
if (index == 0)
{
return 0;
}
int pos = doublepositions[index];
int originalPos = in.pos();
in.seek(pos);
double value = in.readDouble();
in.seek(originalPos);
return value;
}
public Decimal128 getDecimal(int index)
{
if (index == 0)
{
return Decimal128.ZERO;
}
int pos = decimalpositions[index];
int originalPos = in.pos();
in.seek(pos);
byte[] valbytes = in.readBytes(16);
in.seek(originalPos);
return new Decimal128(valbytes); // perhaps need to change endian
}
public String getString(int index) throws DecoderException
{
if (index == 0)
{
return null;
}
int pos = strpositions[index];
int originalPos = in.pos();
in.seek(pos);
String value = in.readString(in.readU32());
in.seek(originalPos);
if (value != null)
{
return value;
}
else
{
throw new DecoderException("abc Decoder Erro: problem reading UTF-8 encoded strings.");
}
}
public String getNamespaceName(int index) throws DecoderException
{
if( index == 0 )
{
return null;
}
int pos = nspositions[index];
int originalPos = in.pos();
in.seek(pos);
int kind = in.readU8();
String value = "";
switch(kind)
{
case CONSTANT_PrivateNamespace:
case CONSTANT_Namespace:
case CONSTANT_PackageNamespace:
case CONSTANT_PackageInternalNs:
case CONSTANT_ProtectedNamespace:
case CONSTANT_ExplicitNamespace:
case CONSTANT_StaticProtectedNs:
value = getString(in.readU32());
break;
default:
throw new DecoderException("abc Decoder Error: constant pool index '" + index + "' is not a Namespace type. The actual type is '" + kind + "'");
}
in.seek(originalPos);
return value;
}
public String[] getNamespaceSet(int index) throws DecoderException
{
if (index == 0)
{
return null;
}
int pos = nsspositions[index];
int originalPos = in.pos();
in.seek(pos);
int count = in.readU32();
String[] value = new String[count];
for (int j = 0; j < count; j++)
{
value[j] = getNamespaceName(in.readU32());
}
in.seek(originalPos);
if (value != null)
{
return value;
}
else
{
throw new DecoderException("abc Decoder Erro: problem reading namespace set.");
}
}
public int getNamespaceIndexForQName(int index) throws DecoderException {
if (index == 0)
{
return 0;
}
int pos = mnpositions[index];
int originalPos = in.pos();
in.seek(pos);
int kind = in.readU8();
switch (kind)
{
case CONSTANT_Qname:
case CONSTANT_QnameA:
int namespaceIndex = in.readU32();
in.seek(originalPos);
return namespaceIndex;
default:
in.seek(originalPos);
throw new DecoderException("abc Decoder Error: constant pool index '" + index + "' is not a QName type. The actual type is '" + kind + "'");
}
}
public int getNamespaceKind(int namespaceIndex) {
if(namespaceIndex == 0)
return -1;
int pos = nspositions[namespaceIndex];
int originalPos = in.pos();
in.seek(pos);
int kind = in.readU8();
in.seek(originalPos);
return kind;
}
public QName getQName(int index) throws DecoderException
{
if (index == 0)
{
return null;
}
int pos = mnpositions[index];
int originalPos = in.pos();
in.seek(pos);
int kind = in.readU8();
switch (kind)
{
case CONSTANT_Qname:
case CONSTANT_QnameA:
{
int namespaceIndex = in.readU32();
int nameIndex = in.readU32();
QName value = createQName(getNamespaceName(namespaceIndex), getString(nameIndex));
in.seek(originalPos);
return value;
}
case CONSTANT_TypeName:
{
int nameIndex = in.readU32();
int count = in.readU32();
String params = ".<";
QName base = getQName(nameIndex);
for(int i = 0; i < count; ++i)
{
params += (i>0?",":"") + getQName(in.readU32());
}
params+=">";
QName value = createQName(base.getNamespace(), base.getLocalPart()+params);
in.seek(originalPos);
return value;
}
default:
in.seek(originalPos);
throw new DecoderException("abc Decoder Error: constant pool index '" + index + "' is not a QName type. The actual type is '" + kind + "'");
}
}
public MultiName getMultiName(int index) throws DecoderException
{
if (index == 0)
{
return null;
}
int pos = mnpositions[index];
int originalPos = in.pos();
in.seek(pos);
int kind = in.readU8();
switch (kind)
{
case CONSTANT_Multiname:
case CONSTANT_MultinameA:
String name = getString(in.readU32());
int namespace_set = in.readU32();
String[] namespaces = getNamespaceSet(namespace_set);
MultiName value = createMultiName(name, namespaces);
in.seek(originalPos);
return value;
default:
in.seek(originalPos);
throw new DecoderException("abc Decoder Error: constant constantPool index '" + index + "' is not a MultiName type. The actual type is '" + kind + "'");
}
}
public Object getGeneralMultiname(int index) throws DecoderException
{
if (index == 0)
{
return null;
}
int pos = mnpositions[index];
int originalPos = in.pos();
in.seek(pos);
int kind = in.readU8();
switch (kind)
{
case CONSTANT_Qname:
case CONSTANT_QnameA:
{
int namespaceIndex = in.readU32();
int nameIndex = in.readU32();
QName value = createQName(getNamespaceName(namespaceIndex), getString(nameIndex));
in.seek(originalPos);
return value;
}
case CONSTANT_Multiname:
case CONSTANT_MultinameA:
{
String name = getString(in.readU32());
int namespace_set = in.readU32();
String[] namespaces = getNamespaceSet(namespace_set);
MultiName value = createMultiName(name, namespaces);
in.seek(originalPos);
return value;
}
case CONSTANT_RTQnameL:
in.seek(originalPos);
return "CONSTANT_RTQnameL"; // Boolean.FALSE;
case CONSTANT_RTQnameLA:
in.seek(originalPos);
return "CONSTANT_RTQnameLA"; // Boolean.TRUE;
case CONSTANT_MultinameL:
case CONSTANT_MultinameLA:
{
int namespacesetIndex = in.readU32();
String[] value = getNamespaceSet(namespacesetIndex);
ArrayList<String> a = new ArrayList<String>();
for (int k = 0; k < value.length; k++)
{
a.add(value[k]);
}
in.seek(originalPos);
return a;
}
case CONSTANT_RTQname:
case CONSTANT_RTQnameA:
{
int idx = in.readU32();
String s = getString(idx);
in.seek(originalPos);
return s;
}
default:
in.seek(originalPos);
throw new DecoderException("abc Decoder Error: constant pool index '" + index + "' is not a QName type. The actual type is '" + kind + "'");
}
}
public Object get(int index, int kind) throws DecoderException
{
if (index == 0)
{
return null;
}
Object value;
switch(kind)
{
case CONSTANT_Utf8:
value = getString(index);
return value;
case CONSTANT_Integer:
value = createInteger(getInt(index));
return value;
case CONSTANT_UInteger:
value = createLong(getLong(index));
return value;
case CONSTANT_Double:
value = createDouble(getDouble(index));
return value;
case CONSTANT_Decimal:
value = getDecimal(index);
return value;
case CONSTANT_Qname:
case CONSTANT_QnameA:
value = getQName(index);
return value;
case CONSTANT_Namespace:
case CONSTANT_PrivateNamespace:
case CONSTANT_PackageNamespace:
case CONSTANT_PackageInternalNs:
case CONSTANT_ProtectedNamespace:
case CONSTANT_ExplicitNamespace:
case CONSTANT_StaticProtectedNs:
value = getNamespaceName(index);
return value;
case CONSTANT_Multiname:
case CONSTANT_MultinameA:
value = getMultiName(index);
return value;
case CONSTANT_False:
value = Boolean.FALSE;
return value;
case CONSTANT_True:
value = Boolean.TRUE ;
return value;
case CONSTANT_Null:
value = NULL;
return value;
case CONSTANT_RTQname:
case CONSTANT_RTQnameA:
value = getGeneralMultiname(index);
return value;
case CONSTANT_RTQnameL:
value = "CONSTANT_RTQnameL"; // Boolean.FALSE;
return value;
case CONSTANT_RTQnameLA:
value = "CONSTANT_RTQnameLA"; // Boolean.TRUE;
return value;
case CONSTANT_MultinameL:
value = getNamespaceSet(getInt(index));
return value;
case CONSTANT_MultinameLA:
value = getNamespaceSet(getInt(index));
return value;
case CONSTANT_Namespace_Set:
value = getNamespaceSet(index);
return value;
default:
throw new DecoderException("Error: Unhandled constant type - " + kind);
}
}
private Integer createInteger(int number)
{
return IntegerPool.getNumber(number);
}
private Long createLong(long number)
{
return new Long(number);
}
private Double createDouble(double number)
{
return new Double(number);
}
private QName createQName(String ns, String name)
{
return new QName(ns, name);
}
private MultiName createMultiName(String name, String[] ns)
{
return new MultiName(name, ns);
}
public void writeTo(OutputStream out) throws IOException
{
history.writeTo(in);
in.writeTo(out);
}
}
final class IndexHistory
{
public static final int cp_int = 0;
public static final int cp_uint = 1;
public static final int cp_double = 2;
public static final int cp_decimal = 3;
public static final int cp_string = 4;
public static final int cp_ns = 5;
public static final int cp_nsset = 6;
public static final int cp_mn = 7;
IndexHistory(ConstantPool[] pools, boolean poolHasDecimal)
{
this.pools = pools;
poolSizes = new int[pools.length];
hasDecimal = poolHasDecimal;
int size = 0, preferredSize = 0;
for (int i = 0, length = pools.length; i < length; i++)
{
poolSizes[i] = (i == 0) ? 0 : size;
size += pools[i].size();
preferredSize += (pools[i].mnEnd - pools[i].strEnd);
}
map = new int[size];
in_ns = new BytecodeBuffer(preferredSize);
in_nsset = new BytecodeBuffer(preferredSize);
in_mn = new BytecodeBuffer(preferredSize);
intP = new ByteArrayPool();
uintP = new ByteArrayPool();
doubleP = new ByteArrayPool();
if (hasDecimal)
decimalP = new ByteArrayPool();
stringP = new ByteArrayPool();
nsP = new NSPool();
nssP = new NSSPool();
mnP = new MultiNamePool();
total = 0;
duplicate = 0;
totalBytes = 0;
duplicateBytes = 0;
// nss = new HashSet<Integer>();
}
public int total, duplicate, totalBytes, duplicateBytes;
private ConstantPool[] pools;
private int[] poolSizes;
private int[] map;
private boolean hasDecimal;
private ByteArrayPool intP, uintP, doubleP, decimalP, stringP, nsP, nssP, mnP;
private BytecodeBuffer in_ns, in_nsset, in_mn;
// private Set<Integer> nss;
// Needed so we can strip out the index for all CONSTANT_PrivateNamespace entries
// since the name for private namespaces is not important
private boolean disableDebuggingInfo = false;
void disableDebugging()
{
disableDebuggingInfo = true;
}
public int getIndex(int poolIndex, int kind, int index)
{
if (index == 0)
{
return 0;
}
else
{
int newIndex = calculateIndex(poolIndex, kind, index);
if (map[newIndex] == 0)
{
decodeOnDemand(poolIndex, kind, index, newIndex);
}
return map[newIndex];
}
}
public void writeTo(BytecodeBuffer b)
{
intP.writeTo(b);
uintP.writeTo(b);
doubleP.writeTo(b);
if (hasDecimal)
decimalP.writeTo(b);
stringP.writeTo(b);
nsP.writeTo(b);
nssP.writeTo(b);
mnP.writeTo(b);
}
/**
* @param poolIndex 0-based
* @param kind 0-based
* @param oldIndex 1-based
*/
private final int calculateIndex(final int poolIndex, final int kind, final int oldIndex)
{
int index = poolSizes[poolIndex];
if (kind > cp_int)
{
index += (pools[poolIndex].intpositions.length == 0) ? 0 : (pools[poolIndex].intpositions.length - 1);
}
if (kind > cp_uint)
{
index += (pools[poolIndex].uintpositions.length == 0) ? 0 : (pools[poolIndex].uintpositions.length - 1);
}
if (kind > cp_double)
{
index += (pools[poolIndex].doublepositions.length == 0) ? 0 : (pools[poolIndex].doublepositions.length - 1);
}
if (hasDecimal && (kind > cp_decimal))
{
index += (pools[poolIndex].decimalpositions.length == 0) ? 0 : (pools[poolIndex].decimalpositions.length - 1);
}
if (kind > cp_string)
{
index += (pools[poolIndex].strpositions.length == 0) ? 0 : (pools[poolIndex].strpositions.length - 1);
}
if (kind > cp_ns)
{
index += (pools[poolIndex].nspositions.length == 0) ? 0 : (pools[poolIndex].nspositions.length - 1);
}
if (kind > cp_nsset)
{
index += (pools[poolIndex].nsspositions.length == 0) ? 0 : (pools[poolIndex].nsspositions.length - 1);
}
if (kind > cp_mn)
{
index += (pools[poolIndex].mnpositions.length == 0) ? 0 : (pools[poolIndex].mnpositions.length - 1);
}
index += (oldIndex - 1);
return index;
}
private final void decodeOnDemand(final int poolIndex, final int kind, final int j, final int j2)
{
ConstantPool pool = pools[poolIndex];
ByteArrayPool baPool = null;
BytecodeBuffer poolIn = null;
int[] positions = null;
int length = 0, endPos = 0;
if (kind == cp_int)
{
positions = pool.intpositions;
length = positions.length;
endPos = pool.intEnd;
baPool = intP;
poolIn = pool.in;
}
else if (kind == cp_uint)
{
positions = pool.uintpositions;
length = positions.length;
endPos = pool.uintEnd;
baPool = uintP;
poolIn = pool.in;
}
else if (kind == cp_double)
{
positions = pool.doublepositions;
length = positions.length;
endPos = pool.doubleEnd;
baPool = doubleP;
poolIn = pool.in;
}
else if (kind == cp_decimal)
{
assert(hasDecimal);
positions = pool.decimalpositions;
length = positions.length;
endPos = pool.decimalEnd;
baPool = decimalP;
poolIn = pool.in;
}
else if (kind == cp_string)
{
positions = pool.strpositions;
length = positions.length;
endPos = pool.strEnd;
baPool = stringP;
poolIn = pool.in;
}
else if (kind == cp_ns)
{
positions = pool.nspositions;
length = positions.length;
endPos = pool.nsEnd;
baPool = nsP;
poolIn = pool.in;
}
else if (kind == cp_nsset)
{
positions = pool.nsspositions;
length = positions.length;
endPos = pool.nssEnd;
baPool = nssP;
poolIn = pool.in;
}
else if (kind == cp_mn)
{
positions = pool.mnpositions;
length = positions.length;
endPos = pool.mnEnd;
baPool = mnP;
poolIn = pool.in;
}
int start = positions[j];
int end = (j != length - 1) ? positions[j + 1] : endPos;
if (kind == cp_ns)
{
int pos = positions[j];
int originalPos = poolIn.pos();
poolIn.seek(pos);
start = in_ns.size();
int nsKind = poolIn.readU8();
in_ns.writeU8(nsKind);
switch (nsKind)
{
case CONSTANT_PrivateNamespace:
if( this.disableDebuggingInfo )
{
in_ns.writeU32(0); // name not important for private namespace
break;
}
// else fall through and treat like a normal namespace
case CONSTANT_Namespace:
case CONSTANT_PackageNamespace:
case CONSTANT_PackageInternalNs:
case CONSTANT_ProtectedNamespace:
case CONSTANT_ExplicitNamespace:
case CONSTANT_StaticProtectedNs:
int index = poolIn.readU32();
int newIndex = getIndex(poolIndex, cp_string, index);
in_ns.writeU32(newIndex);
break;
default:
assert false; // can't possibly happen...
}
poolIn.seek(originalPos);
end = in_ns.size();
poolIn = in_ns;
}
else if (kind == cp_nsset)
{
int pos = positions[j];
int originalPos = poolIn.pos();
poolIn.seek(pos);
start = in_nsset.size();
/*
nss.clear();
int count = (int) poolIn.readU32();
for (int k = 0; k < count; k++)
{
nss.add((int) poolIn.readU32());
}
count = nss.size();
in5.writeU32(count);
for (Iterator<Integer> k = nss.iterator(); k.hasNext();)
{
int index = k.next();
int newIndex = getIndex(poolIndex, 4, index);
in_nsset.writeU32(newIndex);
}
*/
int count = poolIn.readU32();
in_nsset.writeU32(count);
for (int k = 0; k < count; k++)
{
int index = poolIn.readU32();
int newIndex = getIndex(poolIndex, cp_ns, index);
in_nsset.writeU32(newIndex);
}
poolIn.seek(originalPos);
end = in_nsset.size();
poolIn = in_nsset;
}
else if (kind == cp_mn)
{
int pos = positions[j];
int originalPos = poolIn.pos();
poolIn.seek(pos);
start = in_mn.size();
int constKind = poolIn.readU8();
if( !(constKind==CONSTANT_TypeName))
in_mn.writeU8(constKind);
switch (constKind)
{
case CONSTANT_Qname:
case CONSTANT_QnameA:
{
int namespaceIndex = poolIn.readU32();
int newNamespaceIndex = getIndex(poolIndex, cp_ns, namespaceIndex);
in_mn.writeU32(newNamespaceIndex);
int nameIndex = poolIn.readU32();
int newNameIndex = getIndex(poolIndex, cp_string, nameIndex);
in_mn.writeU32(newNameIndex);
break;
}
case CONSTANT_Multiname:
case CONSTANT_MultinameA:
{
int nameIndex = poolIn.readU32();
int newNameIndex = getIndex(poolIndex, cp_string, nameIndex);
in_mn.writeU32(newNameIndex);
int namespace_set = poolIn.readU32();
int newNamespace_set = getIndex(poolIndex, cp_nsset, namespace_set);
in_mn.writeU32(newNamespace_set);
break;
}
case CONSTANT_RTQname:
case CONSTANT_RTQnameA:
{
int index = poolIn.readU32();
int newIndex = getIndex(poolIndex, cp_string, index);
in_mn.writeU32(newIndex);
break;
}
case CONSTANT_RTQnameL:
case CONSTANT_RTQnameLA:
break;
case CONSTANT_MultinameL:
case CONSTANT_MultinameLA:
{
int namespace_set = poolIn.readU32();
int newNamespace_set = getIndex(poolIndex, cp_nsset, namespace_set);
in_mn.writeU32(newNamespace_set);
break;
}
case CONSTANT_TypeName:
{
int nameIndex = poolIn.readU32();
int newNameIndex = getIndex(poolIndex, cp_mn, nameIndex);
int count = poolIn.readU32();
IntList newParams = new IntList();
for( int i = 0; i<count;++i) {
newParams.add(getIndex(poolIndex, cp_mn, poolIn.readU32()));
}
start = in_mn.size();
in_mn.writeU8(constKind);
in_mn.writeU32(newNameIndex);
in_mn.writeU32(count);
for( int i =0; i < count; ++i ) {
in_mn.writeU32(newParams.at(i));
}
break;
}
default:
assert false; // can't possibly happen...
}
poolIn.seek(originalPos);
end = in_mn.size();
poolIn = in_mn;
}
int newIndex = baPool.contains(poolIn, start, end);
if (newIndex == -1)
{
newIndex = baPool.store(poolIn, start, end);
}
else
{
duplicate++;
duplicateBytes += (end - start);
}
total++;
totalBytes += (end - start);
if (j != 0)
{
map[j2] = newIndex;
}
}
}
final class NSPool extends ByteArrayPool
{
NSPool()
{
super();
}
ByteArray newByteArray()
{
return new NS();
}
}
final class NS extends ByteArray
{
int nsKind = 0, index = 0;
void init()
{
super.init();
int originalPos = b.pos();
b.seek(start);
nsKind = b.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 = b.readU32();
break;
default:
assert false; // can't possibly happen...
}
b.seek(originalPos);
long num = 1234 ^ nsKind ^ index;
hash = (int) ((num >> 32) ^ num);
}
void clear()
{
super.clear();
nsKind = 0;
index = 0;
}
public boolean equals(Object obj)
{
boolean equal = false;
if (obj instanceof NS)
{
NS ns = (NS) obj;
if( this.nsKind == CONSTANT_PrivateNamespace )
{
// Private namespaces are only equal if they are literally the same namespace,
// the name is not important.
equal = (this.b == ns.b) && (this.start == ns.start) && (this.end == ns.end);
}
else
{
equal = (ns.nsKind == this.nsKind) && (ns.index == this.index);
}
}
return equal;
}
}
final class NSSPool extends ByteArrayPool
{
NSSPool()
{
super();
}
ByteArray newByteArray()
{
return new NSS();
}
}
final class NSS extends ByteArray
{
int[] set = null;
int size = 0;
void init()
{
super.init();
int originalPos = b.pos();
b.seek(start);
int count = b.readU32();
if (set == null || count > set.length)
{
set = new int[count];
}
size = count;
for (int k = 0; k < count; k++)
{
set[k] = b.readU32();
}
b.seek(originalPos);
long num = 1234;
for (int k = 0; k < count; k++)
{
num ^= set[k];
}
hash = (int) ((num >> 32) ^ num);
}
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 ByteArrayPool
{
MultiNamePool()
{
super();
}
ByteArray newByteArray()
{
return new MN();
}
}
final class MN extends ByteArray
{
int constKind = 0, index1 = 1, index2 = 1;
void init()
{
super.init();
int originalPos = b.pos();
b.seek(start);
constKind = b.readU8();
switch (constKind)
{
case CONSTANT_Qname:
case CONSTANT_QnameA:
{
index1 = b.readU32();
index2 = b.readU32();
long num = 1234 ^ constKind ^ index1 ^ index2;
hash = (int) ((num >> 32) ^ num);
break;
}
case CONSTANT_Multiname:
case CONSTANT_MultinameA:
{
index1 = b.readU32();
index2 = b.readU32();
long num = 1234 ^ constKind ^ index1 ^ index2;
hash = (int) ((num >> 32) ^ num);
break;
}
case CONSTANT_RTQname:
case CONSTANT_RTQnameA:
{
index1 = b.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 = b.readU32();
long num = 1234 ^ constKind ^ index1;
hash = (int) ((num >> 32) ^ num);
break;
}
case CONSTANT_TypeName:
{
index1 = b.readU32();
int count = b.readU32();
// Only 1 typeparam for now.
index2 = b.readU32();
long num = 1234 ^ constKind ^ index1 ^ index2;
hash = (int) ((num >> 32) ^ num);
break;
}
default:
assert false; // can't possibly happen...
}
b.seek(originalPos);
}
void clear()
{
super.clear();
constKind = 0;
index1 = 0;
index2 = 0;
}
public boolean equals(Object obj)
{
if (obj instanceof MN)
{
MN mn = (MN) 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;
}
}
}