BitField.java
/*
** Module :BitField.java
** Abstract :BitField, a subclass of BitSet which forbids dynamic set growth
**
** Copyright (c) 2005-2017, Golden Code Development Corporation.
**
** -#- -I- --Date-- -T- --JPRM-- ----------------Description-----------------
** 001 SIY 20050217 ADD @20015 Created initial implementation
** 002 SIY 20050310 CHG @20354 Organized imports and reordered methods.
** 003 SIY 20050323 CHG @20468 Fixed formatting.
** 004 SIY 20050328 CHG @20574 Fixed missing tags in comments.
** 005 SIY 20050421 ADD @21007 Added parsing for the LDAP bit string values.
** 006 SIY 20050515 CHG @21187 Extended and fixed comments.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.directory;
import java.util.BitSet;
/**
* BitField, a subclass of BitSet which forbids dynamic set growth.
* <p>
* The main purpose of this class is to provide Java representation of the
* <code>Bit Field</code> attribute type.
*
* @author SIY
* @version 1.0
*/
public class BitField extends BitSet
{
/** The "real" width of the bit field. */
private int width;
/**
* Construct a BitField of specified width with all bits set
* to <code>false</code>.
*
* @param width
* Number of bits in field, indexed from <code>0</code> to
* <code>width-1</code>.
* @throws NegativeArraySizeException if the specified width is negative.
*/
public BitField(int width)
{
super(width);
this.width = width;
}
/**
* Parse <code>String</code> like 00011000 and create an instance of
* <code>BitField</code>.
*
* @param str
* Source string.
* @return New <code>BitField</code> instance or <code>null</code> if
* source string does not contain properly formatted bit field.
*/
public static BitField valueOf(String str)
{
if (str == null || str.length() == 0)
return null;
str = str.trim();
if (str.charAt(0) == '\'')
{
str = str.substring(1);
int pos = str.indexOf('\'');
if (pos > 0)
str = str.substring(0, pos);
}
if (str.length() == 0)
return null;
char[] data = str.toCharArray();
BitField fld = new BitField(data.length);
for (int i = 0; i < data.length; i++)
{
if (data[i] == '1')
fld.set(data.length - i - 1);
else
if (data[i] != '0')
return null;
}
return fld;
}
/**
* Performs a logical AND of this bit field with the argument bit set.
*
* @param set
* A bit set to perform operation with.
* @throws IndexOutOfBoundsException
* if the specified set is too wide.
*/
public void and(BitSet set)
{
checkBitSet(set);
super.and(set);
}
/**
* Clears all of the bits whose corresponding bit is set in the specified
* BitSet.
*
* @param set
* A bit set to perform operation with.
* @throws IndexOutOfBoundsException
* if the specified set is too wide.
*/
public void andNot(BitSet set)
{
checkBitSet(set);
super.andNot(set);
}
/**
* Set specified bit into <code>false</code>.
*
* @param index
* The index of the bit to clear.
* @throws IndexOutOfBoundsException if the specified index is negative
* or exceeds BitField width.
*/
public void clear(int index)
{
checkIndex(index);
super.clear(index);
}
/**
* Set specified range of bits into <code>false</code>.
*
* @param from
* The index of the first bit in range.
* @param to
* The index of the last bit in range.
* @throws IndexOutOfBoundsException if the specified range does not fit
* into BitField width.
*/
public void clear(int from, int to)
{
//Note: there is no need to check low bound of range,
//remaining checks are done by base class.
checkIndex(to);
super.clear(from, to);
}
/**
* Set specified bit into opposite value.
*
* @param index
* The index of the bit to change.
* @throws IndexOutOfBoundsException if the specified index is negative
* or exceeds BitField width.
*/
public void flip(int index)
{
checkIndex(index);
super.flip(index);
}
/**
* Set specified range of bits into opposite value.
*
* @param from
* The index of the first bit in range.
* @param to
* The index of the last bit in range.
* @throws IndexOutOfBoundsException if the specified range does not fit
* into BitField width.
*/
public void flip(int from, int to)
{
//Note: there is no need to check low bound of range,
//remaining checks are done by base class.
checkIndex(to);
super.flip(from, to);
}
/**
* Get value of the specified bit.
*
* @param index
* The index of the bit to get.
* @throws IndexOutOfBoundsException
* if the specified index is negative or exceeds BitField width.
* @return <code>true</code> if specified bit is set.
*/
public boolean get(int index)
{
checkIndex(index);
return super.get(index);
}
/**
* Performs a logical OR of this bit field with the argument bit set.
*
* @param set
* A bit set to perform operation with.
* @throws IndexOutOfBoundsException if the specified set is too wide.
*/
public void or(BitSet set)
{
checkBitSet(set);
super.or(set);
}
/**
* Set specified bit into <code>true</code>.
*
* @param index
* The index of the bit to set.
* @throws IndexOutOfBoundsException if the specified index is negative
* or exceeds BitField width.
*/
public void set(int index)
{
checkIndex(index);
super.set(index);
}
/**
* Set specified bit into specified value.
*
* @param index
* The index of the bit to set
* @param val
* New bit value.
* @throws IndexOutOfBoundsException if the specified index is negative
* or exceeds BitField width.
*/
public void set(int index, boolean val)
{
checkIndex(index);
super.set(index, val);
}
/**
* Set specified range of bits into <code>true</code>.
*
* @param from
* The index of the first bit in range.
* @param to
* The index of the last bit in range.
* @throws IndexOutOfBoundsException if the specified range does not fit
* into BitField width.
*/
public void set(int from, int to)
{
checkIndex(to);
super.set(from, to);
}
/**
* Set specified range of bits into specified value.
*
* @param from
* The index of the first bit in range.
* @param to
* The index of the last bit in range.
* @param val
* New value for the bits in range.
* @throws IndexOutOfBoundsException if the specified range does not fit
* into BitField width.
*/
public void set(int from, int to, boolean val)
{
checkIndex(to);
super.set(from, to, val);
}
/**
* Return a field width as specified in the constructor. Note that this is
* not the same value as returned by the parent class.
*
* @return Bit field width as it was specified in the constructor.
*/
public int size()
{
return width;
}
/**
* Convert bit field into string representation. The result is a string
* consisting of '0's and '1's from most significant bit (with highest
* index) to least significant bit.
*
* @return <code>String</code> on '0's and '1's which represent state of
* the bit field.
*/
public String toString()
{
char[] field = new char[size()];
for (int i = 0; i < field.length; i++)
{
field[i] = get(field.length - i - 1) ? '1' : '0';
}
return new String(field);
}
/**
* Performs a logical XOR of this bit field with the argument bit set.
*
* @param set
* A bit set to perform operation with.
* @throws IndexOutOfBoundsException
* if the specified set is too wide.
*/
public void xor(BitSet set)
{
checkBitSet(set);
super.xor(set);
}
/**
* Check specified BitSet is narrow enough to be used for operation.
*
* @param set
* BitSet instance to check.
* @throws IndexOutOfBoundsException
* if specified bit set is too wide.
*/
private void checkBitSet(BitSet set)
{
if (set instanceof BitField)
{
if (size() < set.size())
throw new IndexOutOfBoundsException("Input set is too wide :"
+ set.size());
}
//Comparing with old version of size()
if (super.size() < set.size())
throw new IndexOutOfBoundsException("Input set is too wide :"
+ set.size());
}
/**
* Check specified index to fit into range.
*
* @param index
* index to check.
* @throws IndexOutOfBoundsException
* if index does not fit into range.
*/
private void checkIndex(int index)
{
if (index >= size())
throw new IndexOutOfBoundsException("No such bit in field: " + index);
}
}