EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.iapi.services.io]

COVERAGE SUMMARY FOR SOURCE FILE [FormatableBitSet.java]

nameclass, %method, %block, %line, %
FormatableBitSet.java100% (1/1)88%  (35/40)70%  (1083/1558)63%  (218.3/344)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class FormatableBitSet100% (1/1)88%  (35/40)70%  (1083/1558)63%  (218.3/344)
<static initializer> 100% (1/1)100% (68/68)100% (1/1)
FormatableBitSet (): void 100% (1/1)100% (3/3)100% (2/2)
FormatableBitSet (FormatableBitSet): void 100% (1/1)97%  (35/36)100% (9/9)
FormatableBitSet (byte []): void 100% (1/1)100% (15/15)100% (5/5)
FormatableBitSet (byte [], int): void 0%   (0/1)0%   (0/33)0%   (0/9)
FormatableBitSet (int): void 100% (1/1)100% (6/6)100% (3/3)
and (FormatableBitSet): void 100% (1/1)55%  (51/92)59%  (10.7/18)
anySetBit (): int 100% (1/1)100% (93/93)100% (14/14)
anySetBit (int): int 100% (1/1)94%  (189/202)96%  (30.9/32)
calculateLength (int): int 100% (1/1)85%  (11/13)67%  (2/3)
clear (): void 100% (1/1)95%  (19/20)83%  (5/6)
clear (int): void 100% (1/1)68%  (32/47)75%  (6/8)
clone (): Object 100% (1/1)100% (5/5)100% (1/1)
compare (FormatableBitSet): int 100% (1/1)47%  (48/103)41%  (11/27)
concatenate (FormatableBitSet): FormatableBitSet 0%   (0/1)0%   (0/105)0%   (0/20)
equals (FormatableBitSet): boolean 100% (1/1)80%  (12/15)62%  (1.9/3)
get (int): boolean 100% (1/1)100% (4/4)100% (1/1)
getByteArray (): byte [] 100% (1/1)48%  (14/29)50%  (4/8)
getLength (): int 100% (1/1)100% (3/3)100% (1/1)
getLengthInBytes (): int 100% (1/1)78%  (7/9)67%  (2/3)
getNumBitsSet (): int 100% (1/1)100% (18/18)100% (5/5)
getTypeFormatId (): int 100% (1/1)100% (2/2)100% (1/1)
grow (int): void 100% (1/1)84%  (68/81)90%  (19/21)
hashCode (): int 100% (1/1)90%  (35/39)82%  (9/11)
hexCharToByte (char): byte 0%   (0/1)0%   (0/65)0%   (0/36)
initializeBits (int): void 100% (1/1)100% (15/15)100% (5/5)
isNull (): boolean 0%   (0/1)0%   (0/7)0%   (0/1)
isSet (int): boolean 100% (1/1)56%  (27/48)57%  (4/7)
maxBitsForSpace (int): int 100% (1/1)100% (6/6)100% (1/1)
numBitsInLastByte (int): short 100% (1/1)100% (15/15)100% (2/2)
numBytesFromBits (int): int 100% (1/1)100% (12/12)100% (1/1)
or (FormatableBitSet): void 100% (1/1)77%  (61/79)71%  (12/17)
readExternal (ObjectInput): void 100% (1/1)100% (22/22)100% (7/7)
readExternalFromArray (ArrayInputStream): void 0%   (0/1)0%   (0/22)0%   (0/7)
set (int): void 100% (1/1)67%  (30/45)75%  (6/8)
shrink (int): FormatableBitSet 100% (1/1)91%  (39/43)82%  (9/11)
size (): int 100% (1/1)100% (3/3)100% (1/1)
toString (): String 100% (1/1)96%  (52/54)92%  (12/13)
writeExternal (ObjectOutput): void 100% (1/1)96%  (22/23)99%  (5.9/6)
xor (FormatableBitSet): void 100% (1/1)71%  (41/58)89%  (8/9)

1/*
2 
3   Derby - Class org.apache.derby.iapi.services.io.FormatableBitSet
4 
5   Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11      http://www.apache.org/licenses/LICENSE-2.0
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 */
20 
21package org.apache.derby.iapi.services.io;
22 
23import org.apache.derby.iapi.services.sanity.SanityManager;
24 
25import java.io.InputStream;
26import java.io.ObjectOutput;
27import java.io.ObjectInput;
28import java.io.IOException;
29 
30/**
31 * FormatableBitSet is implemented as a packed array of bytes.
32 *
33 * @author Jamie -- originally coded by Jeff
34 */
35 
36public final class FormatableBitSet implements Formatable, Cloneable
37{
38 
39        /********************************************************
40        **
41        **        This class implements Formatable. That means that it
42        **        can write itself to and from a formatted stream. If
43        **        you add more fields to this class, make sure that you
44        **        also write/read them with the writeExternal()/readExternal()
45        **        methods.
46        **
47        **        If, inbetween releases, you add more fields to this class,
48        **        then you should bump the version number emitted by the getTypeFormatId()
49        **        method.
50        **
51        ********************************************************/
52 
53        /**
54        ** Bits are stored as an array of bytes.
55        ** Bits are numbered starting at 0.  Bits
56        ** 0..7 go in byte[0], 8..15 in byte[1] and so on.
57        ** The number of bytes is tracked as part
58        ** of the byte array.  The number of bits
59        ** being used is derived by the number of
60        ** bytes being used and the number of bits
61        ** being used by the last byte.  The partially
62        ** unused byte is always byte[byte.length] with the
63        ** lowest bits being unused.
64        **
65        ** Zero length bits are stored using a
66        ** zero length byte array, with all bits
67        ** marked as unused.
68        */
69        private byte[]        value;
70        private        short        bitsInLastByte;
71 
72        private transient int        lengthAsBits;
73 
74        /**
75         * Niladic Constructor
76         */
77        public FormatableBitSet()
78        {
79        }
80 
81        /**
82         * Constructs a Bit with the initial number of bits
83         */
84        public FormatableBitSet(int numBits)
85        {
86                initializeBits(numBits);
87        }
88 
89        private void initializeBits(int numBits)
90        {
91                int numBytes = numBytesFromBits(numBits);
92 
93                // the byte array is zero'ed out by the new operator
94                value = new byte[numBytes];
95                bitsInLastByte = numBitsInLastByte(numBits);
96                lengthAsBits = numBits;
97        }
98 
99        /**
100         * Constructs a Bit from an array of bytes.  Assume
101         * bytes are all being used.
102         *
103         * @param newValue        The array of bytes to make up the new Bit
104         */
105        public FormatableBitSet(byte[] newValue)
106        {
107                value = newValue;
108                bitsInLastByte = 8;
109                lengthAsBits = calculateLength(newValue.length);
110        }
111 
112        /**
113         * Constructs a Bit from an array of bytes.
114         *
115         * @param newValue        The array of bytes to make up the new Bit
116         * @param numBits        The number of bits
117         */
118        public FormatableBitSet(byte[] newValue, int numBits)
119        {
120                bitsInLastByte = numBitsInLastByte(numBits);
121                lengthAsBits = numBits;
122 
123                int lenInBytes = numBytesFromBits(numBits);
124 
125                if (lenInBytes == newValue.length) {
126                        value = newValue;
127                } else {
128                        value = new byte[lenInBytes];
129                        System.arraycopy(newValue, 0, value, 0, newValue.length);
130                }
131        }
132 
133        /**
134         * Copy constructor
135         *
136         * @param original the FormatableBitSet to make a copy from
137         */
138        public FormatableBitSet (FormatableBitSet original)
139        {
140                if (SanityManager.DEBUG)
141                        SanityManager.ASSERT(
142                original != null, "cannot make copy from a null FormatableBitSet");
143 
144                bitsInLastByte = original.bitsInLastByte;
145                lengthAsBits = original.lengthAsBits;
146 
147                int lenInBytes = FormatableBitSet.numBytesFromBits(original.lengthAsBits);
148                value = new byte[lenInBytes];
149                if (lenInBytes > 0)
150                        System.arraycopy(original.value, 0, value, 0, lenInBytes);
151        }
152                        
153        /*
154         * Cloneable
155         */
156        public Object clone()
157        {
158                return new FormatableBitSet(this);
159        }
160 
161 
162        /**
163         * Get the length in bytes of a Bit value
164         *
165         * @return        The length in bytes of this value
166         */
167        public int getLengthInBytes()
168        {
169                if (value == null)
170                {
171                        return 0;
172                }
173 
174                return FormatableBitSet.numBytesFromBits(lengthAsBits);
175        }
176 
177        /**
178        ** Get the length in bits
179        **
180        ** @return The length in bits for this value
181        **
182        ** NOTE: could possibly be changed to a long.  As is
183        ** we are restricted to 2^(31-3) -> 256meg instead
184        ** of 2^31 (Integer.MAX_VALUE) like other datatypes
185        ** (or 2 gig).  If it is ever changed to a long
186        ** be sure to change read/writeExternal which write
187        ** out the length in bits.
188        */
189        public int getLength() {
190                return lengthAsBits;
191        }
192 
193        private int calculateLength(int realByteLength)
194        {
195                if (realByteLength == 0)
196                {
197                        return 0;
198                }
199 
200                return ((realByteLength - 1) * 8) + bitsInLastByte;
201        }
202 
203        /**
204         * Get the length in bits -- alias for getLength()
205         *
206         * @return The length in bits for this value
207         */
208        public int size()
209        {
210                return getLength();
211        }
212 
213        /**
214         * Get the value of the byte array
215         *
216         * @return        The value of the byte array
217         */
218 
219        public byte[] getByteArray()
220        {
221                if (value == null)
222                        return null;
223 
224                // In some cases the array is bigger than the actual number
225                // of valid bytes.
226                int realByteLength = getLengthInBytes();
227 
228                // Currently the case is that the return from this
229                // call only includes the valid bytes.
230                if (value.length != realByteLength) {
231                        byte[] data = new byte[realByteLength];
232                        System.arraycopy(value, 0, data, 0, realByteLength);
233 
234                        value = data;
235                }
236 
237                return value;
238        }
239 
240        /**
241         * Set the value of the byte array
242         *
243         * @return        The value of the byte array
244         */
245        public boolean isNull()
246        {
247                return this.value == null;
248        }
249 
250        /**
251         * Grow (widen) a FormatableBitSet to N bis
252         *
253         * @param n        The number of bits you want.  The bits are
254         *                        always added as 0 and are appended to the
255         *                        least significant end of the bit array.
256         *
257         * ASSUMPTIONS: that all extra bits in the last byte
258         * are zero.
259         */
260        public void grow(int n)
261        {
262                if (n <= this.getLength())
263                        return;
264 
265                if (value == null)
266                {
267                        initializeBits(n);
268                        return;
269                }
270 
271                int delta = n - this.getLength();
272 
273 
274                int oldNumBytes = getLengthInBytes();
275 
276                /*
277                ** If we have enough space in the left over bits,
278                ** then all we need to do is change the modulo.
279                */
280                if ((oldNumBytes != 0) &&
281                    (8 - this.bitsInLastByte) >= delta)
282                {
283                        this.bitsInLastByte += delta;
284                        lengthAsBits = n;
285                        return;
286                }
287 
288                int newNumBytes = FormatableBitSet.numBytesFromBits(n);
289 
290                // is there enough room in the existing array
291                if (newNumBytes <= value.length) {
292                        // ensure the bits are zeroed
293                        for (int i = oldNumBytes; i <  newNumBytes; i++)
294                                value[i] = 0;
295                } else {
296 
297 
298                        /*
299                        ** We didn't have enough bytes in value, so we need
300                        ** to create a bigger byte array and use that.
301                        */
302                        byte[] newValue = new byte[newNumBytes];
303 
304                        System.arraycopy(value, 0, newValue, 0, oldNumBytes);
305 
306                        value = newValue;
307                }
308                bitsInLastByte = numBitsInLastByte(n);
309                lengthAsBits = n;
310        }
311 
312        /**
313         * Shrink (narrow) a FormatableBitSet to N bits
314         *
315         * @param n        The number of bits the caller wants.  The
316         *                         bits are always removed from the
317         *                        least significant end of the bit array.
318         */
319        public FormatableBitSet shrink(int n)
320        {
321                int                numBytes;
322                int                lastByteNum;
323 
324                /*
325                ** Sanity check: we shouldn't shrink down to
326                ** nothing.
327                */
328                if (SanityManager.DEBUG)
329                {
330                        if (value == null)
331                        {
332                                SanityManager.THROWASSERT("Attempt to shrink a null Bit"+
333                                                " -- caller should have known better probably");
334                                return null;
335                        }
336                }
337 
338                if (n >= this.getLength())
339                {
340                        return this;
341                }
342 
343 
344                lastByteNum = numBytesFromBits(n) - 1;
345                bitsInLastByte = numBitsInLastByte(n);
346                lengthAsBits = n;
347 
348                /*
349                ** Mask out any left over bits in the
350                ** last byte.  Retain the highest bits.
351                */
352                if (bitsInLastByte != 8)
353                {
354                        value[lastByteNum] &= 0xFF00 >> bitsInLastByte;
355                }
356 
357                return this;
358        }
359 
360        /*
361        ** Some of the operators required by SQL.  These could alternatively
362        ** be in SQLBit, but since they are so tightly bound to the implementation
363        ** rather than return something that undermines the encapsulation
364        ** of this type, i have chosen to put them in here.
365        */
366 
367        /**
368         * Bit equivalence.  Compare this with other.
369         * If the length is different, then cannot be
370         * equal so short circuit.  Otherwise, rely on
371         * compare().  Note that two zero length bits are
372         * considered equal.
373         *
374         * @param other        the other bit to compare to
375         *
376         * @return TRUE|FALSE
377         */
378        public boolean equals(FormatableBitSet other)
379        {
380                if (this.getLength() != other.getLength())
381                {
382                        return false;
383                }
384 
385                return (this.compare(other) == 0);
386        }
387 
388        /**
389         * Bit comparison.  Compare this with other.
390         * Will always do a byte by byte compare.
391         *
392         * Given 2 similar bits of unequal lengths (x and y),
393         * where x.getLength() < y.getLength() but where:
394         *
395         *         x[0..x.getLength()] == y[0..x.getLength()]
396         *
397         * then x < y.
398         *
399         *
400         * @param other the other bit to compare to
401         *
402         * @return -1        - if other <  this
403         *                        0        - if other == this
404         *                        1        - if other >  this
405         *
406         */
407        public int compare(FormatableBitSet other)
408        {
409 
410                int                otherCount, thisCount;
411                int                otherLen, thisLen;
412                byte[]        otherb;
413 
414                otherb = other.value;
415                /*
416                ** By convention, nulls sort low, and null == null
417                */
418                if (this.value == null || otherb == null)
419                {
420                        if (this.value != null)        // otherb == null
421                                return 1;
422                        if (otherb != null)                // this.value == null
423                                return -1;
424                        return 0;                                // both null
425                }
426 
427                otherLen = other.getLengthInBytes();
428                thisLen = getLengthInBytes();
429                for (otherCount = 0, thisCount = 0;
430                                otherCount < otherLen && thisCount < thisLen;
431                                otherCount++, thisCount++)
432                {
433                        if (otherb[otherCount] != this.value[thisCount])
434                                break;
435                }
436 
437                /*
438                ** '==' if byte by byte comparison is identical and
439                ** exact same length in bits (not bytes).
440                */
441                if ((otherCount == otherLen) && (thisCount == thisLen))
442                {
443                                if (this.getLength() == other.getLength())
444                                {
445                                        return 0;
446                                }
447 
448                                /*
449                                ** If subset of bits is identical, return 1
450                                ** if other.getLength() > this.getLength(); otherwise,
451                                ** -1
452                                */
453                                return (other.getLength() < this.getLength()) ? 1 : -1;
454                }
455 
456                if (otherCount == otherLen)
457                {
458                        return 1;
459                }
460                else if (thisCount == thisLen)
461                {
462                        return -1;
463                }
464                else
465                {
466                        /*
467                        ** Ok, we have a difference somewhere.  Now
468                        ** we have to go to the trouble of converting
469                        ** to a int and masking out the sign to get
470                        ** a valid comparision because bytes are signed.
471                        */
472                        int otherInt, thisInt;
473 
474                        otherInt = (int)otherb[otherCount];
475                        otherInt &= (0x100 - 1);
476 
477                        thisInt = (int)this.value[thisCount];
478                        thisInt &= (0x100 - 1);
479 
480                        return (thisInt > otherInt) ? 1 : -1;
481 
482                }
483        }
484 
485        /**
486         * Bit concatenation.
487         *
488         * @param other         the other bit to append to this
489         *
490         * @return Bit -- the newly concatenated bit
491         *
492         */
493        public FormatableBitSet concatenate(FormatableBitSet other)
494        {
495                int                newLen;
496                int                otherLen;
497                int                prevLen;
498                int                prevLenBytes;
499                int                newLenBytes;
500                int     otherLenBytes;
501                int                i, j;
502                byte[]        newValue;
503                byte[]        otherValue;
504                int                shiftBits;
505                int                inByte;
506 
507 
508                prevLen = this.getLength();
509                prevLenBytes = this.getLengthInBytes();
510                otherLen = other.getLength();
511                otherValue = other.getByteArray();
512                otherLenBytes = other.getLengthInBytes();
513                newLen = prevLen + otherLen;
514                newLenBytes = numBytesFromBits(newLen);
515                newValue = new byte[newLenBytes];
516 
517 
518                /*
519                ** Copy over the entire array in this.value
520                ** to newLenBytes.
521                */
522                for (i = 0; i < prevLenBytes; i++)
523                {
524                        newValue[i] = this.value[i];
525                }
526 
527                /*
528                ** Now if we have any bits left over
529                ** we need to shift them, and keep
530                ** shifting everything down.  Be careful
531                ** to handle the case where the bit
532                ** used to have length 0.
533                */
534                shiftBits = (prevLen == 0) ? 8 : this.bitsInLastByte;
535                for (j = 0; j < otherLenBytes; j++, i++)
536                {
537                        if (shiftBits == 8)
538                        {
539                                newValue[i] = otherValue[j];
540                        }
541                        else
542                        {
543                                /*
544                                ** Convert to an int because it will get converted
545                                ** on the shift anyway.
546                                */
547                                inByte = (int)otherValue[j];
548 
549                                /*
550                                ** Mask off the high bits in case they are now
551                                ** turned on if we had the sign bit on.
552                                */
553                                inByte &= (0x100 - 1);
554 
555                                /*
556                                ** Use the high order bits to finish off
557                                ** the last byte
558                                */
559                                newValue[i-1] |= (inByte >>> shiftBits);
560 
561                    /*
562                        ** Start the next one with whatever is left, unless
563                        ** there is nothing left.
564                    */
565                    if (i < newLenBytes)
566                                {
567                            newValue[i] |= (inByte << (8 - shiftBits));
568                                }
569                        }
570                }
571 
572                return new FormatableBitSet(newValue, newLen);
573        }
574 
575    /**
576     * Produce a hash code by putting the value bytes into an int, exclusive OR'ing
577     * if there are more than 4 bytes.
578     *
579     * @return the hash code
580     */
581    public int hashCode()
582    {
583        if( null == value)
584            return 0;
585        
586        int code = 0;
587        int i;
588        int shift = 0;
589 
590                int byteLength = getLengthInBytes();
591        for( i = 0; i < byteLength; i++)
592        {
593            code ^= (value[i] & 0xff)<<shift;
594            shift += 8;
595            if( 32 <= shift)
596                shift = 0;
597        }
598        return code;
599    }
600    
601        /**
602         * Bit isSet
603         *
604         * @param position        the bit to check
605         *
606         */
607        public final boolean isSet(int position)
608        {
609                if (SanityManager.DEBUG)
610                {
611                        if (position >= this.getLength())
612            {
613                SanityManager.THROWASSERT(
614                   "Attempt to get a bit position (" + position +
615                   ")" +
616                   "that exceeds the max length (" + this.getLength() + ")");
617            }
618                }
619 
620                try {
621 
622                        int bytepos = position / 8;
623                        int bitpos = 7 - (position % 8);
624 
625                        return ((value[bytepos] & (1 << bitpos)) != 0);
626 
627                } catch (ArrayIndexOutOfBoundsException e) {
628                        // Should not happen, handle it just in case not all cases are tested
629                        // by insane server.
630                        return false;
631                }
632        }
633 
634        /**
635         * Bit get -- alias for isSet()
636         *
637         * @param position        the bit to check
638         *
639         */
640        public final boolean get(int position)
641        {
642                return isSet(position);
643        }
644        
645        /**
646         * Bit set
647         *
648         * @param position        the bit to set
649         *
650         */
651        public void set(int position)
652        {
653 
654                if (SanityManager.DEBUG)
655                {
656            if (position >= this.getLength())
657            {
658                SanityManager.THROWASSERT(
659                                   "Attempt to set a bit position that exceeds the max length ("
660                   + this.getLength() + ")");
661            }
662                }
663 
664                // Should not happen, handle it just in case not all cases are tested
665                // by insane server.
666                if (position >= getLength())
667                        grow(position);
668 
669                int bytepos = position / 8;
670                int bitpos = 7 - (position % 8);
671 
672                value[bytepos] |= (1 << bitpos);
673        }
674 
675        /**
676         * Bit clear
677         *
678         * @param position        the bit to clear
679         *
680         */
681        public void clear(int position)
682        {
683                int        bytepos;
684                int        bitpos;
685 
686                if (SanityManager.DEBUG)
687                {
688            if (position >= this.getLength())
689            {
690                SanityManager.THROWASSERT(
691                   "Attempt to set a bit position that exceeds the max length ("
692                   + this.getLength() + ")");
693            }
694                }
695 
696                // Should not happen, handle it just in case not all cases are tested
697                // by insane server.
698                if (position >= getLength())
699                        grow(position);
700 
701                bytepos = position / 8;
702                bitpos = 7 - (position % 8);
703 
704                value[bytepos] &= ~(1 << bitpos);
705        }
706 
707        /**
708          Clear all the bits in this FormatableBitSet
709          */
710        public void clear()
711        {
712                if (value == null) 
713            return;
714 
715                int byteLength = getLengthInBytes();
716                for (int ix=0; ix < byteLength; ix++)
717            value[ix] = 0;
718        }
719 
720 
721        /**
722        * Figure out how many bytes are needed to
723        * store the input number of bits.
724        *
725        * @param bits        bits
726        *
727        * @return        the number of bytes
728        */
729        protected static int
730        numBytesFromBits(int bits)
731        {
732                return (bits == 0) ? 0 : ((bits - 1) / 8) + 1;
733        }
734 
735        /**
736        * Figure out how many bits are in the last
737        * byte from the total number of bits.
738        *
739        * @param        bits        bits
740        *
741        * @return        the number of bits
742        */
743        private static short
744        numBitsInLastByte(int bits)
745        {
746                int modulo = bits % 8;
747                return (short)((modulo == 0) ?
748                                ((bits == 0) ? 0 : 8) :
749                                modulo);
750        }
751 
752        /**
753         * Translate a hex character to a byte.
754         *
755         * @param hexChar        A character with the value [0-9a-fA-F].
756         *
757         * @return        A byte with the numeric value corresponding to the hex character
758         */
759        private static byte
760        hexCharToByte(char hexChar)
761        {
762                byte        byteValue;
763 
764                switch (hexChar)
765                {
766                  case '0':
767                        byteValue = 0;
768                        break;
769 
770                  case '1':
771                        byteValue = 1;
772                        break;
773 
774                  case '2':
775                        byteValue = 2;
776                        break;
777 
778                  case '3':
779                        byteValue = 3;
780                        break;
781 
782                  case '4':
783                        byteValue = 4;
784                        break;
785 
786                  case '5':
787                        byteValue = 5;
788                        break;
789 
790                  case '6':
791                        byteValue = 6;
792                        break;
793 
794                  case '7':
795                        byteValue = 7;
796                        break;
797 
798                  case '8':
799                        byteValue = 8;
800                        break;
801 
802                  case '9':
803                        byteValue = 9;
804                        break;
805 
806                  case 'a':
807                  case 'A':
808                        byteValue = 0xA;
809                        break;
810 
811                  case 'b':
812                  case 'B':
813                        byteValue = 0xB;
814                        break;
815 
816                  case 'c':
817                  case 'C':
818                        byteValue = 0xC;
819                        break;
820 
821                  case 'd':
822                  case 'D':
823                        byteValue = 0xD;
824                        break;
825 
826                  case 'e':
827                  case 'E':
828                        byteValue = 0xE;
829                        break;
830 
831                  case 'f':
832                  case 'F':
833                        byteValue = 0xF;
834                        break;
835 
836                  default:
837                          if (SanityManager.DEBUG)
838                          {
839                                  SanityManager.THROWASSERT("illegal char = " + hexChar);
840                          }
841                          throw new IllegalArgumentException();
842                }
843 
844                return byteValue;
845        }
846 
847private static char[] decodeArray = {'0', '1', '2', '3', '4', '5', '6', '7',
848                                                                '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
849 
850        /**
851         * Format the string into BitSet format: {0, 2, 4, 8} if bits 0, 2, 4, 8
852         * are set.
853         *
854         * @return A new String containing the formatted Bit value
855         */
856        public String toString()
857        {
858                char[]        outChars;
859                int                inPosition;
860                int                outPosition;
861                int         inByte;
862 
863                if (value == null)
864                {
865                        return null;
866                }
867                {
868                        // give it a reasonable size
869                        StringBuffer str = new StringBuffer(getLength()*8*3);
870                        str.append("{");
871                        boolean first = true;
872                        for (inPosition = 0; inPosition < getLength(); inPosition++)
873                        {
874                                if (isSet(inPosition))
875                                {
876                                        if (!first)
877                                                str.append(", ");
878                                        first = false;
879                                        str.append(inPosition);
880                                }
881                        }
882                        str.append("}");
883                        return new String(str);
884                }
885        }
886 
887 
888 
889        /**
890         * Statically calculates how many bits can fit into the number of
891         * bytes if this Bit object is externalized.  Only valid for this
892         * implementation of Bit.
893         */
894        public static int maxBitsForSpace(int numBytes)
895        {
896                return (numBytes - 4)*8;
897                
898        }
899 
900        /**
901         * If any bit is set, return the bit number of a bit that is set.
902         * If no bit is set, return -1; 
903         *
904         * @return the bit number of a bit that is set, or -1 if no bit is set
905         */
906        public int anySetBit()
907        {
908                int numbytes = getLengthInBytes();
909                int bitpos;
910 
911                for (int i = 0; i < numbytes-1; i++)
912                {
913                        if (value[i] != 0)
914                        {
915                                for (int j = 0; j < 8; j++)
916                                {
917                                        bitpos = 7-j;
918                                        if (((1 << bitpos) & value[i]) != 0)
919                                                return ((i*8)+j);
920                                }
921                        }
922                }
923 
924 
925                // only the top part of the last byte is relevant
926                byte mask = (byte)(0xFF << (8-bitsInLastByte));
927                if ((value[numbytes-1] & mask) != 0)
928                {
929                        for (int j = 0; j < bitsInLastByte; j++)
930                        {
931                                bitpos = 7-j;
932                                if (((1 << bitpos) & value[numbytes-1]) != 0)
933                                        return ((numbytes-1)*8)+j;
934                        }
935                }
936 
937                return -1;
938        }
939 
940        /**
941         * Like anySetBit(), but return any set bit whose number is bigger than
942         * beyondBit. If no bit is set after beyondBit, -1 is returned. 
943         * By using anySetBit() and anySetBit(beyondBit), one can quickly go
944         * thru the entire bit array to return all set bit.
945         *
946         * @param beyondBit only look at bit that is greater than this bit number
947         * @return the bit number of a bit that is set, or -1 if no bit after
948         * beyondBit is set
949         */
950        public int anySetBit(int beyondBit)
951        {
952                if (SanityManager.DEBUG)
953                {
954                        if (beyondBit >= this.getLength())
955                SanityManager.THROWASSERT(
956                   "Attempt to access bit position that exceeds the max length ("
957                    + this.getLength() + ")");
958                }
959 
960                int startingBit = (beyondBit+1);
961 
962                // we have seen the last bit.
963                if (startingBit >= this.getLength())
964                        return -1;
965 
966                int numbytes = getLengthInBytes();
967                int startingByte = startingBit / 8;
968                int startingBitpos = startingBit % 8;
969                int bitpos;
970                byte mask;
971 
972                // see if any bits in this byte is set, only the bottom part of the
973                // first byte is relevant
974                mask = (byte)(0xFF >> startingBitpos);
975 
976                if (startingByte == numbytes-1)        // starting byte == last byte 
977                        mask &= (byte)(0xFF << (8-bitsInLastByte));
978 
979                if ((value[startingByte] & mask ) != 0)
980                {
981                        // I know we will see the bit before bitsInLastByte even if we are
982                        // at the last byte, no harm in going up to 8 in the loop
983                        for (int j = startingBitpos; j < 8; j++)
984                        {
985                                if (SanityManager.DEBUG)
986                                {
987                                        if (startingByte == numbytes-1)
988                                                SanityManager.ASSERT(j < bitsInLastByte,
989                                                                 "going beyond the last bit");
990                                }
991                                bitpos = 7-j;
992                                if (((1 << bitpos) & value[startingByte]) != 0)
993                                {
994                                        return (startingByte*8+j);
995                                }
996                        }        
997                }
998 
999                for (int i = (startingByte+1); i < numbytes-1; i++)
1000                {                        
1001                        if (value[i] != 0)
1002                        {
1003                                for (int j = 0; j < 8; j++)
1004                                {
1005                                        bitpos = 7-j;
1006                                        if (((1 << bitpos) & value[i]) != 0)
1007                                        {
1008                                                return ((i*8)+j);
1009                                        }
1010                                }
1011                        }
1012                }
1013                
1014                // Last byte if there are more than one bytes.  Only the top part of
1015                // the last byte is relevant 
1016                if (startingByte != numbytes-1)
1017                {
1018                        mask = (byte)(0xFF << (8-bitsInLastByte));
1019 
1020                        if ((value[numbytes-1] & mask) != 0)
1021                        {
1022                                for (int j = 0; j < bitsInLastByte; j++)
1023                                {
1024                                        bitpos = 7-j;
1025                                        if (((1 << bitpos) & value[numbytes-1]) != 0)
1026                                        {
1027                                                return ((numbytes-1)*8)+j;        
1028                                        }
1029                                }
1030                        }
1031                }
1032 
1033                return -1;
1034 
1035        }
1036 
1037        /**
1038         * Bitwise OR this Bit with another Bit.
1039         *
1040         * @param otherBit the other Bit
1041         */
1042        public void or(FormatableBitSet otherBit)
1043        {
1044                if (otherBit == null || otherBit.getLength() == 0)
1045                        return;
1046 
1047                int otherLength = otherBit.getLength();
1048 
1049                if (otherLength > getLength())
1050                        grow(otherLength); // expand this bit 
1051 
1052                if (otherBit instanceof FormatableBitSet)
1053                {
1054                        // we know the bit ordering, optimize this 
1055                        FormatableBitSet ob = (FormatableBitSet)otherBit;
1056                        int obByteLen = ob.getLengthInBytes();
1057                        for (int i = 0; i < obByteLen-1; i++)
1058                                value[i] |= ob.value[i];
1059 
1060                        // do the last byte bit by bit
1061                        for (int i = (obByteLen-1)*8; i < otherLength; i++)
1062                                if (otherBit.isSet(i))
1063                                        set(i);
1064                }
1065                else
1066                {
1067                        // we don't know the bit ordering, call thru the interface and go
1068                        // thru bit by bit
1069                        // this bit impl's length >= other bit's length
1070 
1071                        for (int i = 0; i < otherLength; i++)
1072                        {
1073                                if (otherBit.isSet(i))
1074                                        set(i);
1075                        }
1076                }
1077        }
1078 
1079        /**
1080         * Bitwise AND this Bit with another Bit.
1081         *
1082         * @param otherBit the other Bit
1083         */
1084        public void and(FormatableBitSet otherBit)
1085        {
1086                if (SanityManager.DEBUG)
1087                        SanityManager.ASSERT(otherBit != null, "cannot AND null with a FormatableBitSet");
1088 
1089                int otherLength = otherBit.getLength();
1090 
1091                // Supposedly cannot happen, but handle it just in case.
1092                if (otherLength > getLength())
1093                        grow(otherLength); // expand this bit 
1094 
1095                if (otherLength < getLength())
1096                {
1097                        // clear all bits that are not in the other bit
1098                        int startingByte = (otherLength * 8) + 1;
1099                        int len = getLengthInBytes();
1100                        for (int i = startingByte; i < len; i++)
1101                                value[i] = 0;
1102 
1103                        for (int i = otherLength; i < startingByte*8; i++)
1104                        {
1105                                if (i < getLength())
1106                                        clear(i);
1107                                else
1108                                        break;
1109                        }
1110                }
1111 
1112                if (otherLength == 0)
1113                        return;
1114                        
1115                int length = otherBit.getLengthInBytes() < getLengthInBytes() ? 
1116                        otherBit.getLengthInBytes() : getLengthInBytes();
1117 
1118                for (int i = 0; i < length; i++)
1119                        value[i] &= otherBit.value[i];
1120        }
1121 
1122        /**
1123         * Logically XORs this FormatableBitSet with the specified FormatableBitSet.
1124         * @param set        The FormatableBitSet to be XORed with.
1125         */
1126        public void xor(FormatableBitSet set)
1127        {
1128                if (SanityManager.DEBUG)
1129                {
1130                        if (getLength() != set.getLength())
1131                        {
1132                                SanityManager.THROWASSERT("getLength() (" + getLength() +
1133                                        ") and set.getLength() (" +
1134                                        set.getLength() +
1135                                        ") expected to be the same");
1136                        }
1137                }
1138 
1139                int setLength = set.getLength();
1140                for (int i = setLength; i-- > 0; )
1141                {
1142                        if (isSet(i) && set.isSet(i))
1143                        {
1144                                clear(i);
1145                        }
1146                        else if (isSet(i) || set.isSet(i))
1147                        {
1148                                set(i);
1149                        }
1150                }
1151        }
1152 
1153        /**
1154         * Get a count of the number of bits that are set.
1155         *
1156         * @return The number of bits that are set.
1157         */
1158        public int getNumBitsSet()
1159        {
1160                int count = 0;
1161 
1162                for (int index = getLength() - 1; index >= 0; index--)
1163                {
1164                        if (isSet(index))
1165                        {
1166                                count++;
1167                        }
1168                }
1169 
1170                return count;
1171        }
1172 
1173        /////////////////////////////////////////////////////////
1174        //
1175        // EXTERNALIZABLE
1176        //
1177        /////////////////////////////////////////////////////////
1178        /**
1179         * Format: <UL>
1180         *                <LI>int                length in bits  </LI>
1181         *                <LI>byte[]                                        </LI></UL>
1182         *
1183         * @see java.io.Externalizable#writeExternal
1184        */
1185        public void writeExternal(ObjectOutput out) throws IOException
1186        {
1187                // never called when value is null
1188                if (SanityManager.DEBUG)
1189                        SanityManager.ASSERT(value != null);
1190 
1191                out.writeInt(getLength());
1192                int byteLen = getLengthInBytes();
1193                if (byteLen > 0)
1194                {
1195                        out.write(value, 0, byteLen);
1196                }
1197        }
1198 
1199        /** 
1200         * Note: gracefully handles zero length
1201         * bits -- will create a zero length array
1202         * with no bits being used.  Fortunately
1203         * in.read() is ok with a zero length array
1204         * so no special code.
1205         * <p>
1206         * WARNING: this method cannot be changed w/o
1207         * changing SQLBit because SQLBit calls this
1208         * directly w/o calling read/writeObject(), so
1209         * the format id is not stored in that case.
1210         *
1211         * @see java.io.Externalizable#readExternal
1212         */
1213        public void readExternal(ObjectInput in) throws IOException
1214        {
1215                int lenInBits;
1216                int lenInBytes;
1217 
1218                lenInBits = in.readInt();
1219 
1220                lenInBytes = FormatableBitSet.numBytesFromBits(lenInBits);
1221 
1222 
1223                /*
1224                ** How can lenInBytes be zero?  The implication is
1225                ** that lenInBits is zero.  Well, the reason this can
1226                ** happen is that the store will reset our stream
1227                ** out from underneath us if we are a Bit column that
1228                ** overflows onto another page because it assumes that
1229                ** we want to stream it in specially.  Because of this warped
1230                ** API, our readInt() will return 0 even though our
1231                ** writeExternal() did a writeInt(xxx).  The upshot
1232                ** is that you should leave the following alone.
1233                */
1234 
1235                        value = new byte[lenInBytes];
1236 
1237                        in.readFully(value);
1238 
1239                        bitsInLastByte = numBitsInLastByte(lenInBits);
1240 
1241                        lengthAsBits = lenInBits;
1242        }
1243 
1244        public void readExternalFromArray(ArrayInputStream in) throws IOException
1245        {
1246                int lenInBits = in.readInt();
1247 
1248                int lenInBytes = FormatableBitSet.numBytesFromBits(lenInBits);
1249 
1250                value = new byte[lenInBytes];
1251 
1252                in.readFully(value);
1253 
1254                bitsInLastByte = numBitsInLastByte(lenInBits);
1255 
1256                lengthAsBits = lenInBits;
1257        }
1258 
1259        /**
1260         * Get the formatID which corresponds to this class.
1261         *
1262         *        @return        the formatID of this class
1263         */
1264        public        int        getTypeFormatId()        { return StoredFormatIds.BITIMPL_V01_ID; }
1265}

[all classes][org.apache.derby.iapi.services.io]
EMMA 2.0.5312 (C) Vladimir Roubtsov