001/* ----------------------------------------------------------------------------
002   The Kiwi Toolkit - A Java Class Library
003   Copyright (C) 1998-2004 Mark A. Lindner
004
005   This library is free software; you can redistribute it and/or
006   modify it under the terms of the GNU General Public License as
007   published by the Free Software Foundation; either version 2 of the
008   License, or (at your option) any later version.
009
010   This library is distributed in the hope that it will be useful,
011   but WITHOUT ANY WARRANTY; without even the implied warranty of
012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013   General Public License for more details.
014
015   You should have received a copy of the GNU General Public License
016   along with this library; if not, write to the Free Software
017   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018   02111-1307, USA.
019 
020   The author may be contacted at: mark_a_lindner@yahoo.com
021   ----------------------------------------------------------------------------
022   $Log: BitString.java,v $
023   Revision 1.3  2004/05/05 21:22:45  markl
024   Comment header updates.
025
026   Revision 1.2  2004/03/20 06:53:36  markl
027   new class
028   ----------------------------------------------------------------------------
029*/
030
031package kiwi.util;
032
033/**
034 * A class representing a string of bits, useful for maintaining a set of flags
035 * in compact form.
036 * 
037 * @author Mark Lindner
038 * @since Kiwi 2.0
039 */
040
041public final class BitString
042  {
043  /** The bit string data. */
044  protected byte array[];
045  /** The length of the bit string, in bits. */
046  protected int length;
047
048  /** Construct a new <code>BitString</code> of the specified length.
049   *
050   * @param length The length.
051   */
052  
053  public BitString(int length)
054    {
055    if(length < 0)
056      throw(new IllegalArgumentException());
057    
058    this.length = length;
059    
060    int len = length / 8;
061    if((length % 8) > 0)
062      len++;
063
064    array = new byte[len];
065    
066    clearAll();
067    }
068
069  /** Construct a new <code>BitString</code> of the specified length, with the
070   * bits initialized to either the on or off position.
071   *
072   * @param length The length.
073   * @param setInitially A flag indicating whether all bits should be initially
074   * set or cleared.
075   */
076  
077  public BitString(int length, boolean setInitially)
078    {
079    this(length);
080
081    if(setInitially)
082      setAll();
083    }
084
085  /** Get the length of the <code>BitString</code>. */
086  
087  public int getLength()
088    {
089    return(length);
090    }
091
092  /** Clear all of the bits. */
093  
094  public void clearAll()
095    {
096    for(int i = 0; i < array.length; i++)
097      array[i] = 0;
098    }
099
100  /** Set all of the bits. */
101  
102  public void setAll()
103    {
104    for(int i = 0; i < array.length; i++)
105      array[i] = ~0;
106    }
107
108  /** Set the specified bit.
109   *
110   * @param bit The index of the bit to set.
111   * @throws java.lang.IllegalArgumentException If the bit index is out of
112   * range.
113   */
114  
115  public void set(int bit)
116    {
117    if(bit < 0)
118      throw(new IllegalArgumentException());
119    
120    int _byte = bit / 8;
121    int _bit =  bit % 8;
122
123    if(_byte >= array.length)
124      throw(new IllegalArgumentException());
125
126    array[_byte] |= (1 << _bit);
127    }
128
129  /** Test the specified bit.
130   *
131   * @param bit The index of the bit to test.
132   * @return <code>true</code> if the bit is set, <code>false</code>
133   * otherwise.
134   * @throws java.lang.IllegalArgumentException If the bit index is out of
135   * range.
136   */
137  
138  public boolean isSet(int bit)
139    {
140    if(bit < 0)
141      throw(new IllegalArgumentException());
142    
143    int _byte = bit / 8;
144    int _bit =  bit % 8;
145
146    if(_byte >= array.length)
147      throw(new IllegalArgumentException());
148
149    return((array[_byte] & (1 << _bit)) != 0);
150    }
151
152  /** Test the specified bit.
153   *
154   * @param bit The index of the bit to test.
155   * @return <code>true</code> if the bit is cleared, <code>false</code>
156   * otherwise.
157   * @throws java.lang.IllegalArgumentException If the bit index is out of
158   * range.
159   */
160  
161  public boolean isClear(int bit)
162    {
163    return(! isSet(bit));
164    }
165
166  /** Clear the specified bit.
167   *
168   * @param bit The index of the bit to clear.
169   * @throws java.lang.IllegalArgumentException If the bit index is out of
170   * range.
171   */
172  
173  public void clear(int bit)
174    {
175    if(bit < 0)
176      throw(new IllegalArgumentException());
177    
178    int _byte = bit / 8;
179    int _bit =  bit % 8;
180
181    if(_byte >= array.length)
182      throw(new IllegalArgumentException());
183
184    array[_byte] &= ~(1 << _bit);
185    }
186
187  /** Compare this <code>BitString</code> to another. The method
188   * returns <code>true</code> if the bits that are set in this
189   * <code>BitString</code> are also set in the other
190   * <code>BitString</code>. (This is not a test for equality; to test
191   * if two <code>BitStrings</code> have exactly the same bits set,
192   * use <code>equals()</code>.)
193   *
194   * @param other The <code>BitString</code> to compare against.
195   * @return <code>true</code> for a match, <code>false</code> otherwise.
196   */
197  
198  public boolean compareTo(BitString other)
199    {
200    if(length != other.length)
201      return(false);
202    
203    boolean r = false;
204
205    for(int i = 0; i < array.length; i++)
206      {
207      r |= ((array[i] & other.array[i]) != array[i]);
208      }
209
210    return(r);
211    }
212
213  /** Determine if this object is identical to another object. */
214
215  public boolean equals(Object other)
216    {
217    if(!(other instanceof BitString))
218      return(false);
219
220    BitString otherbs = (BitString)other;
221
222    if(otherbs.length != length)
223      return(false);
224
225    for(int i = 0; i < length; i++)
226      if(otherbs.array[i] != array[i])
227        return(false);
228
229    return(true);
230    }
231  
232  /** Produce a string representation of the object. */
233
234  public String toString()
235    {
236    StringBuffer sb = new StringBuffer();
237
238    int _byte = 0;
239    int _bit = 0;
240    
241    for(int i = 0; i < length; i++)
242      {
243      sb.append(((array[_byte] & (1 << _bit)) == 0) ? '0' : '1');
244      _bit++;
245      if(_bit == 8)
246        {
247        _byte++;
248        _bit = 0;
249        }
250      }
251    
252    return(sb.toString());
253    }
254  
255  }
256
257/* end of source file */