PsyBitArray.java
package coneforest.psylla.core;
import coneforest.psylla.runtime.*;
import java.util.BitSet;
import java.util.Iterator;
/**
* The representation of {@code bitarray}.
*/
@Type("bitarray")
public class PsyBitArray
implements
PsyFormalArray<PsyBoolean>,
PsyBitwise<PsyBitArray>
{
/**
* Context action of the {@code bitarray} operator.
*/
@OperatorType("bitarray")
public static final ContextAction PSY_BITARRAY
=ContextAction.ofSupplier(PsyBitArray::new);
private final BitSet bitarray;
private int size;
/**
* Creates a new empty {@code bitarray}.
*/
public PsyBitArray()
{
this(new BitSet(), 0);
}
public PsyBitArray(final BitSet bitarray, final int size)
{
this.bitarray=bitarray;
this.size=size;
}
@Override
public PsyBoolean get(final int index)
throws PsyRangeCheckException
{
if(index>=size)
throw new PsyRangeCheckException();
try
{
return PsyBoolean.of(bitarray.get(index<0? index+length(): index));
}
catch(final IndexOutOfBoundsException ex)
{
throw new PsyRangeCheckException(ex);
}
}
@Override
public PsyBitArray psyGetInterval(final PsyInteger oIndex, final PsyInteger oCount)
throws PsyRangeCheckException
{
final var index=oIndex.intValue();
final var count=oCount.intValue();
if(index+count>size)
throw new PsyRangeCheckException();
try
{
final var newBitArray=new PsyBitArray(bitarray.get(index, index+count), count);
newBitArray.size=count;
return newBitArray;
}
catch(final IndexOutOfBoundsException ex)
{
throw new PsyRangeCheckException(ex);
}
}
@Override
public void put(final int index, final PsyBoolean oBoolean)
throws PsyRangeCheckException
{
if(index>=size)
throw new PsyRangeCheckException();
try
{
bitarray.set(index, oBoolean.booleanValue());
}
catch(final IndexOutOfBoundsException ex)
{
throw new PsyRangeCheckException(ex);
}
}
@Override
public void psyPutInterval(final PsyInteger oIndex, final PsyIterable<? extends PsyBoolean> oIterable)
throws PsyRangeCheckException
{
int index=oIndex.intValue();
if(index<0
||
oIterable instanceof PsyLengthy
&& index+((PsyLengthy)oIterable).length()>=size)
throw new PsyRangeCheckException();
for(final var oBoolean: oIterable)
{
bitarray.set(index++, oBoolean.booleanValue());
if(index==size)
break;
}
}
@Override
public void psyAppend(final PsyBoolean oBoolean)
throws PsyLimitCheckException, PsyRangeCheckException
{
if(size==Integer.MAX_VALUE)
throw new PsyLimitCheckException();
try
{
bitarray.set(size++, oBoolean.booleanValue());
}
catch(final IndexOutOfBoundsException e)
{
throw new PsyRangeCheckException();
}
}
@Override
public void insert(final int index, final PsyBoolean oBoolean)
{
size++;
for(int i=size-1; i>index; i--)
bitarray.set(i, bitarray.get(i-1));
bitarray.set(index, oBoolean.booleanValue());
}
@Override
public void delete(final int index)
throws PsyRangeCheckException
{
try
{
for(int i=index; i<size; i++)
bitarray.set(i-1, bitarray.get(i));
size--;
}
catch(final IndexOutOfBoundsException ex)
{
throw new PsyRangeCheckException(ex);
}
}
@Override
public PsyBoolean extract(final int indexValue)
throws PsyRangeCheckException
{
try
{
final var result=get(indexValue);
for(int i=indexValue; i<size; i++)
bitarray.set(i-1, bitarray.get(i));
size--;
return result;
}
catch(final IndexOutOfBoundsException ex)
{
throw new PsyRangeCheckException(ex);
}
}
@Override
public PsyBitArray psyExtractInterval(final PsyInteger oStart, final PsyInteger oCount)
throws PsyRangeCheckException
{
final var oResult=psyGetInterval(oStart, oCount);
final var start=oStart.intValue();
final var count=oCount.intValue();
for(int i=start+count; i<size; i++)
bitarray.set(i-count, bitarray.get(i));
size-=count;
return oResult;
}
@Override
public PsyBitArray psyNot()
{
final var result=(BitSet)bitarray.clone();
result.flip(0, size);
return new PsyBitArray(result, size);
}
@Override
public PsyBitArray psyOr(final PsyBitArray oBitArray)
{
final var result=(BitSet)bitarray.clone();
result.or(oBitArray.bitarray);
return new PsyBitArray(result, size>oBitArray.size? size: oBitArray.size);
}
@Override
public PsyBitArray psyAnd(final PsyBitArray oBitArray)
{
final var result=(BitSet)bitarray.clone();
result.and(oBitArray.bitarray);
return new PsyBitArray(result, size>oBitArray.size? size: oBitArray.size);
}
@Override
public PsyBitArray psyXor(final PsyBitArray oBitArray)
{
final var result=(BitSet)bitarray.clone();
result.xor(oBitArray.bitarray);
return new PsyBitArray(result, size>oBitArray.size? size: oBitArray.size);
}
@Override
public PsyBitArray psyBitShift(final PsyInteger oShift)
{
final var shift=oShift.intValue();
final var result=new BitSet();
if(shift>=0)
{
for(int i=size-1; i>=0; i--)
result.set(i+shift, bitarray.get(i));
}
else
{
for(int i=0+size; i<size; i++)
result.set(i+shift, bitarray.get(i));
}
return new PsyBitArray(result, size+shift);
}
@Override
public PsyBoolean psyTestBit(final PsyInteger oBit)
throws PsyRangeCheckException
{
final int bit=oBit.intValue();
if(bit<0)
throw new PsyRangeCheckException();
return PsyBoolean.of(bitarray.get(bit));
}
@Override
public PsyBitArray psySetBit(final PsyInteger oBit)
throws PsyRangeCheckException
{
final var bit=oBit.intValue();
final var result=(BitSet)bitarray.clone();
if(bit<0)
throw new PsyRangeCheckException();
result.set(bit, true);
return new PsyBitArray(result, bit<size? size: bit+1);
}
@Override
public PsyBitArray psyFlipBit(final PsyInteger oBit)
throws PsyRangeCheckException
{
final var bit=oBit.intValue();
final var result=(BitSet)bitarray.clone();
if(bit<0)
throw new PsyRangeCheckException();
result.set(bit, !result.get(bit));
return new PsyBitArray(result, size);
}
@Override
public PsyBitArray psyClearBit(final PsyInteger oBit)
throws PsyRangeCheckException
{
final var bit=oBit.intValue();
final var result=(BitSet)bitarray.clone();
if(bit<0)
throw new PsyRangeCheckException();
result.set(bit, false);
return new PsyBitArray(result, size);
}
@Override
public Iterator<PsyBoolean> iterator()
{
return new Iterator<PsyBoolean>()
{
private int index=0;
@Override
public boolean hasNext()
{
return index<size; // TODO ???
}
@Override
public PsyBoolean next()
{
return PsyBoolean.of(bitarray.get(index++));
}
};
}
@Override
public int length()
{
return size;
}
@Override
public PsyBitArray psySlice(final PsyIterable<PsyInteger> oIndices)
throws PsyRangeCheckException, PsyLimitCheckException
{
final var oResult=new PsyBitArray();
for(final var oIndex: oIndices)
oResult.psyAppend(psyGet(oIndex));
return oResult;
}
@Override
public void psySetLength(final PsyInteger oLength)
throws PsyLimitCheckException, PsyRangeCheckException
{
final var length=oLength.longValue();
if(length<0)
throw new PsyRangeCheckException();
if(length>Integer.MAX_VALUE)
throw new PsyLimitCheckException();
final var s=size;
if(length<s)
bitarray.clear((int)length, s);
else
bitarray.clear(s, (int)length);
size=(int)length;
}
@Override
public PsyBitArray psyClone()
{
return new PsyBitArray((BitSet)bitarray.clone(), size);
}
@Override
public void psyClear()
{
bitarray.clear();
}
@Override
public String toSyntaxString()
{
final var sb=new StringBuilder("%bitarray=");
int j=-1;
for(int i=bitarray.nextSetBit(0); i>=0; i=bitarray.nextSetBit(i+1))
{
for(int k=j+1; k<i; k++)
sb.append('0');
sb.append('1');
j=i;
}
sb.append('%');
return sb.toString();
}
}