PsyBitSet.java
package coneforest.psylla.core;
import coneforest.psylla.runtime.*;
import java.util.BitSet;
import java.util.Iterator;
/**
* The representation of {@code bitset}, a set of nonnegative {@code integer} objects.
*/
@Type("bitset")
public class PsyBitSet
implements PsyFormalSet<PsyInteger>
{
/**
* Context action of the {@code bitset} operator.
*/
@OperatorType("bitset")
public static final ContextAction PSY_BITSET
=ContextAction.ofSupplier(PsyBitSet::new);
private final BitSet bitset;
/**
* Instantiate an empty {@code bitset} object.
*/
public PsyBitSet()
{
this(new BitSet());
}
/**
* Instantiate a {@code bitset} object from a given {@link BitSet} object.
*
* @param bitset a bit set.
*/
public PsyBitSet(final BitSet bitset)
{
this.bitset=bitset;
}
@Override
public PsyBitSet psyClone()
{
return new PsyBitSet((BitSet)bitset.clone());
}
@Override
public String toSyntaxString()
{
final var sb=new StringBuilder("%bitset=");
int j=-1;
for(int i=bitset.nextSetBit(0); i>=0; i=bitset.nextSetBit(i+1))
{
for(int k=j+1; k<i; k++)
sb.append('0');
sb.append('1');
j=i;
}
sb.append('%');
return sb.toString();
}
/*public BitSet getBitSet()
{
return bitset;
}*/
@Override
public void psyAppend(final PsyInteger oIndex)
throws PsyLimitCheckException, PsyRangeCheckException
{
//if(length()==Integer.MAX_VALUE)
// throw new PsyLimitCheckException();
try
{
bitset.set(oIndex.intValue(), true);
}
catch(final IndexOutOfBoundsException ex)
{
throw new PsyRangeCheckException();
}
}
@Override
public void psyAppendAll(final PsyIterable<? extends PsyInteger> oIterable)
throws PsyLimitCheckException, PsyRangeCheckException
{
switch(oIterable)
{
case PsyBitSet oBitSet->bitset.or(oBitSet.bitset);
default->PsyFormalSet.super.psyAppendAll(oIterable);
}
}
@Override
public void psyRemove(final PsyInteger oIndex)
{
try
{
bitset.set(oIndex.intValue(), false);
}
catch(final IndexOutOfBoundsException ex)
{
// NOP
}
}
@Override
public void psyRemoveAll(final PsyIterable<? extends PsyInteger> oIterable)
{
switch(oIterable)
{
case PsyBitSet oBitSet->bitset.andNot(oBitSet.bitset);
default->PsyFormalSet.super.psyRemoveAll(oIterable);
}
}
@Override
public Iterator<PsyInteger> iterator()
{
return new Iterator<PsyInteger>()
{
private int index=bitset.nextSetBit(0);
@Override
public boolean hasNext()
{
return index>=0;
}
@Override
public PsyInteger next()
{
final var result=PsyInteger.of(index);
index=bitset.nextSetBit(index+1);
return result;
}
};
}
@Override
public void psyClear()
{
bitset.clear();
}
@Override
public int length()
{
return bitset.cardinality();
}
@Override
public PsyBoolean psyContains(final PsyObject oElement)
{
return PsyBoolean.of(oElement instanceof PsyInteger oInteger
&& bitset.get(oInteger.intValue()));
}
@Override
public PsyBoolean psyIntersects(final PsyFormalSet<? extends PsyInteger> oSet)
{
if(oSet instanceof PsyBitSet oBitSet)
return PsyBoolean.of(bitset.intersects(oBitSet.bitset));
else
return PsyFormalSet.super.psyIntersects(oSet);
}
/*@Override
public PsyBoolean psyEq(final PsyObject o)
{
return PsyBoolean.of(o instanceof PsyBitSet oBitSet
&& bitset.equals(oBitSet.bitset));
}*/
@Override
public PsyFormalStream<PsyInteger> psyStream()
{
return PsyFormalStream.<PsyInteger>of(
bitset.stream().<PsyInteger>mapToObj(PsyInteger::of));
}
@Override
public int hashCode()
{
return bitset.hashCode();
}
@Override
public boolean equals(final Object obj)
{
return switch(obj)
{
case PsyBitSet oBitSet->bitset.equals(oBitSet.bitset);
case PsyFormalSet<? extends PsyObject> oFormalSet->
{
if(length()!=oFormalSet.length())
yield false;
for(final var oInteger: this)
if(!oFormalSet.psyContains(oInteger).booleanValue())
yield false;
yield true;
}
default->false;
};
}
}