001: // kelondroBitfield.java
002: // (C) 2006 by Michael Peter Christen; mc@anomic.de, Frankfurt a. M., Germany
003: // first published 22.22.2006 on http://www.anomic.de
004: //
005: // $LastChangedDate: 2006-04-02 22:40:07 +0200 (So, 02 Apr 2006) $
006: // $LastChangedRevision: 1986 $
007: // $LastChangedBy: orbiter $
008: //
009: // LICENSE
010: //
011: // This program is free software; you can redistribute it and/or modify
012: // it under the terms of the GNU General Public License as published by
013: // the Free Software Foundation; either version 2 of the License, or
014: // (at your option) any later version.
015: //
016: // This program is distributed in the hope that it will be useful,
017: // but WITHOUT ANY WARRANTY; without even the implied warranty of
018: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019: // GNU General Public License for more details.
020: //
021: // You should have received a copy of the GNU General Public License
022: // along with this program; if not, write to the Free Software
023: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: package de.anomic.kelondro;
026:
027: public class kelondroBitfield implements Cloneable {
028:
029: // the bitfield implements a binary array. Such arrays may be exported in a base64-String
030:
031: private byte[] bb;
032:
033: public kelondroBitfield() {
034: this (0);
035: }
036:
037: public kelondroBitfield(byte[] b) {
038: if (b == null)
039: this .bb = new byte[0];
040: else
041: this .bb = b;
042: }
043:
044: public kelondroBitfield(int bytelength) {
045: this .bb = new byte[bytelength];
046: for (int i = 0; i < bytelength; i++)
047: bb[i] = 0;
048: }
049:
050: public kelondroBitfield(int bytelength, String exported) {
051: // imports a b64-encoded bitfield
052: byte[] b = kelondroBase64Order.enhancedCoder
053: .decode(exported,
054: "de.anomic.kelondro.kelondroBitfield.kelondroBitfield(...)");
055: if (b.length == bytelength) {
056: bb = b;
057: } else {
058: bb = new byte[bytelength];
059: assert (b.length <= bytelength) : "exported = " + exported
060: + " has bytelength = " + b.length + " > "
061: + bytelength;
062: System.arraycopy(b, 0, bb, 0, Math
063: .min(b.length, bytelength));
064: }
065: }
066:
067: public Object clone() {
068: kelondroBitfield theClone = new kelondroBitfield(
069: new byte[this .bb.length]);
070: System.arraycopy(this .bb, 0, theClone.bb, 0, this .bb.length);
071: return theClone;
072: }
073:
074: public void set(int pos, boolean value) {
075: assert (pos >= 0);
076: int slot = pos >> 3; // /8
077: if (slot >= bb.length) {
078: // extend capacity
079: byte[] nb = new byte[slot + 1];
080: System.arraycopy(bb, 0, nb, 0, bb.length);
081: for (int i = bb.length; i < nb.length; i++)
082: nb[i] = 0;
083: bb = nb;
084: nb = null;
085: }
086: if (value) {
087: bb[slot] = (byte) (bb[slot] | (1 << (pos % 8)));
088: } else {
089: bb[slot] = (byte) (bb[slot] & (0xff ^ (1 << (pos % 8))));
090: }
091: }
092:
093: public boolean get(int pos) {
094: assert (pos >= 0);
095: int slot = pos >> 3; // /8
096: if (slot > bb.length)
097: return false;
098: return (bb[slot] & (1 << (pos % 8))) > 0;
099: }
100:
101: public int length() {
102: return bb.length << 3;
103: }
104:
105: public String exportB64() {
106: return kelondroBase64Order.enhancedCoder.encode(bb);
107: }
108:
109: public byte[] bytes() {
110: return bb;
111: }
112:
113: public String toString() {
114: StringBuffer sb = new StringBuffer(length());
115: for (int i = length() - 1; i >= 0; i--)
116: sb.append((this .get(i)) ? '1' : '0');
117: return new String(sb);
118: }
119:
120: public boolean equals(kelondroBitfield x) {
121: if (x.bb.length != bb.length)
122: return false;
123: for (int i = 0; i < bb.length; i++)
124: if (bb[i] != x.bb[i])
125: return false;
126: return true;
127: }
128:
129: public void and(kelondroBitfield x) {
130: int c = Math.min(x.length(), this .length());
131: for (int i = 0; i < c; i++)
132: set(i, this .get(i) && x.get(i));
133: }
134:
135: public void or(kelondroBitfield x) {
136: int c = Math.min(x.length(), this .length());
137: for (int i = 0; i < c; i++)
138: set(i, this .get(i) || x.get(i));
139: if (x.length() > c) {
140: for (int i = c; i < x.length(); i++)
141: set(i, x.get(i));
142: }
143: }
144:
145: public void xor(kelondroBitfield x) {
146: int c = Math.min(x.length(), this .length());
147: for (int i = 0; i < c; i++)
148: set(i, this .get(i) != x.get(i));
149: if (x.length() > c) {
150: for (int i = c; i < x.length(); i++)
151: set(i, x.get(i));
152: }
153: }
154:
155: public boolean anyOf(kelondroBitfield x) {
156: int c = Math.min(x.length(), this .length());
157: for (int i = 0; i < c; i++)
158: if ((x.get(i)) && (this .get(i)))
159: return true;
160: return false;
161: }
162:
163: public boolean allOf(kelondroBitfield x) {
164: int c = Math.min(x.length(), this .length());
165: for (int i = 0; i < c; i++)
166: if ((x.get(i)) && (!(this .get(i))))
167: return false;
168: if (x.length() > c) {
169: for (int i = c; i < x.length(); i++)
170: if (x.get(i))
171: return false;
172: }
173: return true;
174: }
175:
176: public static void main(String[] args) {
177: kelondroBitfield test = new kelondroBitfield(4);
178: int l = test.length();
179: System.out.println("available: " + l);
180: System.out.println("bevore: " + test.toString());
181: for (int i = 0; i < l / 2; i++) {
182: System.out.println(new String(test.exportB64()));
183: test.set(i, true);
184: System.out.println(i + ":" + test.toString());
185: }
186: for (int i = l / 2; i < l; i++) {
187: System.out.println(new String(test.exportB64()));
188: test = new kelondroBitfield(4, test.exportB64());
189: test.set(i, true);
190: System.out.println(i + ":" + test.toString());
191: }
192: System.out.println(new String(test.exportB64()));
193: for (int i = l - 1; i >= 0; i--) {
194: test.set(i, false);
195: System.out.println(i + ":" + test.toString());
196: }
197: System.out.println("after: " + test.toString());
198: }
199: }
|