|
|
|
|
|
|
|
*/ |
|
/* |
|
* 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 com.sun.org.apache.xerces.internal.impl.dtd.models; |
|
|
|
|
|
/** |
|
* This class is a very simple bitset class. The DFA content model code needs |
|
* to support a bit set, but the java BitSet class is way, way overkill. Our |
|
* bitset never needs to be expanded after creation, hash itself, etc... |
|
* |
|
* Since the vast majority of content models will never require more than 64 |
|
* bits, and since allocation of anything in Java is expensive, this class |
|
* provides a hybrid implementation that uses two ints for instances that use |
|
* 64 bits or fewer. It has a byte array reference member which will only be |
|
* used if more than 64 bits are required. |
|
* |
|
* Note that the code that uses this class will never perform operations |
|
* on sets of different sizes, so that check does not have to be made here. |
|
* |
|
* @xerces.internal |
|
* |
|
*/ |
|
// made this class public so it can be accessed by |
|
|
|
public class CMStateSet |
|
{ |
|
// ------------------------------------------------------------------- |
|
// Constructors |
|
|
|
public CMStateSet(int bitCount) |
|
{ |
|
|
|
fBitCount = bitCount; |
|
if (fBitCount < 0) |
|
throw new RuntimeException("ImplementationMessages.VAL_CMSI"); |
|
|
|
// |
|
// See if we need to allocate the byte array or whether we can live |
|
// within the 64 bit high performance scheme. |
|
|
|
if (fBitCount > 64) |
|
{ |
|
fByteCount = fBitCount / 8; |
|
if (fBitCount % 8 != 0) |
|
fByteCount++; |
|
fByteArray = new byte[fByteCount]; |
|
} |
|
|
|
|
|
zeroBits(); |
|
} |
|
|
|
|
|
// ------------------------------------------------------------------- |
|
// Public inherited methods |
|
|
|
public String toString() |
|
{ |
|
StringBuffer strRet = new StringBuffer(); |
|
try |
|
{ |
|
strRet.append("{"); |
|
for (int index = 0; index < fBitCount; index++) |
|
{ |
|
if (getBit(index)) |
|
strRet.append(" " + index); |
|
} |
|
strRet.append(" }"); |
|
} |
|
|
|
catch(RuntimeException exToCatch) |
|
{ |
|
// |
|
// We know this won't happen but we have to catch it to avoid it |
|
// having to be in our 'throws' list. |
|
// |
|
} |
|
return strRet.toString(); |
|
} |
|
|
|
|
|
// ------------------------------------------------------------------- |
|
// Package final methods |
|
// ------------------------------------------------------------------- |
|
|
|
public final void intersection(CMStateSet setToAnd) |
|
{ |
|
if (fBitCount < 65) |
|
{ |
|
fBits1 &= setToAnd.fBits1; |
|
fBits2 &= setToAnd.fBits2; |
|
} |
|
else |
|
{ |
|
for (int index = fByteCount - 1; index >= 0; index--) |
|
fByteArray[index] &= setToAnd.fByteArray[index]; |
|
} |
|
} |
|
|
|
public final boolean getBit(int bitToGet) |
|
{ |
|
if (bitToGet >= fBitCount) |
|
throw new RuntimeException("ImplementationMessages.VAL_CMSI"); |
|
|
|
if (fBitCount < 65) |
|
{ |
|
final int mask = (0x1 << (bitToGet % 32)); |
|
if (bitToGet < 32) |
|
return (fBits1 & mask) != 0; |
|
else |
|
return (fBits2 & mask) != 0; |
|
} |
|
else |
|
{ |
|
|
|
final byte mask = (byte)(0x1 << (bitToGet % 8)); |
|
final int ofs = bitToGet >> 3; |
|
|
|
|
|
return ((fByteArray[ofs] & mask) != 0); |
|
} |
|
} |
|
|
|
public final boolean isEmpty() |
|
{ |
|
if (fBitCount < 65) |
|
{ |
|
return ((fBits1 == 0) && (fBits2 == 0)); |
|
} |
|
else |
|
{ |
|
for (int index = fByteCount - 1; index >= 0; index--) |
|
{ |
|
if (fByteArray[index] != 0) |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
final boolean isSameSet(CMStateSet setToCompare) |
|
{ |
|
if (fBitCount != setToCompare.fBitCount) |
|
return false; |
|
|
|
if (fBitCount < 65) |
|
{ |
|
return ((fBits1 == setToCompare.fBits1) |
|
&& (fBits2 == setToCompare.fBits2)); |
|
} |
|
|
|
for (int index = fByteCount - 1; index >= 0; index--) |
|
{ |
|
if (fByteArray[index] != setToCompare.fByteArray[index]) |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
public final void union(CMStateSet setToOr) |
|
{ |
|
if (fBitCount < 65) |
|
{ |
|
fBits1 |= setToOr.fBits1; |
|
fBits2 |= setToOr.fBits2; |
|
} |
|
else |
|
{ |
|
for (int index = fByteCount - 1; index >= 0; index--) |
|
fByteArray[index] |= setToOr.fByteArray[index]; |
|
} |
|
} |
|
|
|
public final void setBit(int bitToSet) |
|
{ |
|
if (bitToSet >= fBitCount) |
|
throw new RuntimeException("ImplementationMessages.VAL_CMSI"); |
|
|
|
if (fBitCount < 65) |
|
{ |
|
final int mask = (0x1 << (bitToSet % 32)); |
|
if (bitToSet < 32) |
|
{ |
|
fBits1 &= ~mask; |
|
fBits1 |= mask; |
|
} |
|
else |
|
{ |
|
fBits2 &= ~mask; |
|
fBits2 |= mask; |
|
} |
|
} |
|
else |
|
{ |
|
|
|
final byte mask = (byte)(0x1 << (bitToSet % 8)); |
|
final int ofs = bitToSet >> 3; |
|
|
|
|
|
fByteArray[ofs] &= ~mask; |
|
fByteArray[ofs] |= mask; |
|
} |
|
} |
|
|
|
|
|
public final void setTo(CMStateSet srcSet) |
|
{ |
|
|
|
if (fBitCount != srcSet.fBitCount) |
|
throw new RuntimeException("ImplementationMessages.VAL_CMSI"); |
|
|
|
if (fBitCount < 65) |
|
{ |
|
fBits1 = srcSet.fBits1; |
|
fBits2 = srcSet.fBits2; |
|
} |
|
else |
|
{ |
|
for (int index = fByteCount - 1; index >= 0; index--) |
|
fByteArray[index] = srcSet.fByteArray[index]; |
|
} |
|
} |
|
|
|
// had to make this method public so it could be accessed from |
|
|
|
public final void zeroBits() |
|
{ |
|
if (fBitCount < 65) |
|
{ |
|
fBits1 = 0; |
|
fBits2 = 0; |
|
} |
|
else |
|
{ |
|
for (int index = fByteCount - 1; index >= 0; index--) |
|
fByteArray[index] = 0; |
|
} |
|
} |
|
|
|
|
|
// ------------------------------------------------------------------- |
|
// Private data members |
|
// |
|
// fBitCount |
|
// The count of bits that the outside world wants to support, |
|
// so its the max bit index plus one. |
|
// |
|
// fByteCount |
|
// If the bit count is > 64, then we use the fByteArray member to |
|
// store the bits, and this indicates its size in bytes. Otherwise |
|
// its value is meaningless. |
|
// |
|
// fBits1 |
|
// fBits2 |
|
// When the bit count is < 64 (very common), these hold the bits. |
|
// Otherwise, the fByteArray member holds htem. |
|
|
|
int fBitCount; |
|
int fByteCount; |
|
int fBits1; |
|
int fBits2; |
|
byte[] fByteArray; |
|
|
|
public boolean equals(Object o) { |
|
if (!(o instanceof CMStateSet)) return false; |
|
return isSameSet((CMStateSet)o); |
|
} |
|
|
|
public int hashCode() { |
|
if (fBitCount < 65) |
|
{ |
|
return fBits1+ fBits2 * 31; |
|
} |
|
else |
|
{ |
|
int hash = 0; |
|
for (int index = fByteCount - 1; index >= 0; index--) |
|
hash = fByteArray[index] + hash * 31; |
|
return hash; |
|
} |
|
} |
|
/* Optimization(Jan, 2001) */ |
|
}; |