$include (..\lib\compStch.ext) /* *============================================================================ * 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 * * Permission to use for any purpose, modify, copy, and make enhancements * and derivative works of the software is granted if attribution is given to * R.M. Gillmore, dba the ACME Software Deli, as the author * * While the ACME Software Deli does not work for money, there is nonetheless * a significant amount of work involved. The ACME Software Deli maintains the * rights to all code written, though it may be used and distributed as long as * the following conditions are maintained. * * 1. The copyright statement at the top of each code block is maintained in * your distribution. * 2. You do not identify yourself as the ACME Software Deli * 3. Any changes made to the software are sent to the ACME Software Deli *============================================================================ */ bitArrayModule: do; $if not noID declare IDString (*) byte data ( '@(#)bitArray.p86 $Author: rmgillmore $ $Date:: 2025-05-04 19:35:39#$:', 0 ); $endif $include (..\lib\comnDefs.ext) $include (..\lib\sysCalls.ext) $include (..\lib\mem.ext) $include (..\lib\string.ext) $set ( BITARRAY_IMPLEMENTATION ) $include (..\lib\bitArray.ext) declare NUMBER_SHIFTS_PER_BYTE literally '3', BITS_MASK literally '7', BITS_PER_BYTE literally '8'; declare bitArrayStruct literally 'structure ( bits pointer, numberBits integer, maximumBits integer )'; declare bitMasks (*) byte data ( 80h, 40h, 20h, 10h, 08h, 04h, 02h, 01h ); /* ************************************** * Constructors ************************************** */ createBitArray: procedure ( numberBits ) bitArray_t LOCAL_VARS public; declare numberBits integer; declare thisPtr bitArray_t, this based thisPtr bitArrayStruct; this.numberBits = 0; this.maximumBits = 0; thisPtr = malloc( size( this ) ); if ( thisPtr <> NULL ) then do; declare numberBytes word; numberBytes = shr( unsign( numberBits ) + BITS_PER_BYTE, NUMBER_SHIFTS_PER_BYTE ); this.bits = malloc( numberBytes ); if ( this.bits <> NULL ) then do; this.numberBits = numberBits; this.maximumBits = signed( shl( numberBytes, NUMBER_SHIFTS_PER_BYTE ) ); end; call setb( NUL, this.bits, numberBytes ); end; return ( thisPtr ); end createBitArray; deleteBitArray: procedure ( thisPtr ) LOCAL_VARS public; declare thisPtr bitArray_t, this based thisPtr bitArrayStruct; declare returnValue integer; if ( thisPtr <> NULL ) then do; if ( this.maximumBits > 0 ) then returnValue = free( this.bits ); returnValue = free( thisPtr ); end; end deleteBitArray; /* ************************************** * Accessors ************************************** */ bitArrayLength: procedure ( thisPtr ) integer LOCAL_VARS public; declare thisPtr bitArray_t, this based thisPtr bitArrayStruct; return ( this.numberBits ); end bitArrayLength; bitIsSet: procedure ( thisPtr, bitIndex ) boolean public; declare thisPtr bitArray_t, this based thisPtr bitArrayStruct, bitIndex integer; if ( ( bitIndex >= 0 ) and ( bitIndex < this.numberBits ) ) then do; declare whichByte word, whichBit word, arrayBase pointer, bitArray based arrayBase (*) byte; arrayBase = this.bits; whichByte = shr( unsign( bitIndex ), NUMBER_SHIFTS_PER_BYTE ); whichBit = unsign( bitIndex ) and BITS_MASK; return ( ( bitArray( whichByte ) and bitMasks( whichBit ) ) <> 0 ); end; end bitIsSet; bitIsClear: procedure ( thisPtr, bitIndex ) boolean LOCAL_VARS public; declare thisPtr bitArray_t, bitIndex integer; return ( not bitIsSet( thisPtr, bitIndex ) ); end bitIsClear; /* ************************************** * Manipulators ************************************** */ newBitArrayLength: procedure ( thisPtr, numberBits ) LOCAL_VARS public; declare thisPtr bitArray_t, this based thisPtr bitArrayStruct, numberBits integer; /* * this function will modify the length of the bit array. If the bit array * is to be shorter, all that we need to do is to reduce the number of bits * to the value in. * * the challenge is when the bit array is to get longer ... we will extend * the number of bits. if the new number of bits require more bytes than * the current bit array, then we will allocate a memory block with a sufficient * of bytes to hold the bits, copy the existing bytes to the new block, point * to the new bit array, then release the block from the current byte block */ if ( this.maximumBits = numberBits ) then do; /* * we need do nothing */ ; end; else if ( this.maximumBits > numberBits ) then do; /* * all we do is to reduce the maximum number of bits */ this.maximumBits = numberBits; end; else do; /* * the most complex of the cases is to allocate a memory block of sufficient * size to render a bit array of numberBits size */ declare localArrayPtr pointer, numberBytes word; numberBytes = shr( unsign( numberBits ) + BITS_PER_BYTE, NUMBER_SHIFTS_PER_BYTE ); localArrayPtr = malloc( numberBytes ); if ( localArrayPtr <> NULL ) then do; /* * we have a block of memory, so copy the existing block to the new * memory area, release the (now) outdated block and adjust the maximum * number of bits */ declare oldBlockSize word, returnValue integer; /* * initialize the new array location to all zeroes. */ call setb( NUL, localArrayPtr, numberBytes ); /* * we have a block of memory, so copy the existing block to the new * memory area, release the (now) outdated block and adjust the maximum * number of bits */ oldBlockSize = shr( unsign( this.numberBits ) + BITS_PER_BYTE, NUMBER_SHIFTS_PER_BYTE ); call memcpy( localArrayPtr, this.bits, oldBlockSize ); returnValue = free( this.bits ); this.bits = localArrayPtr; this.maximumBits = numberBits; end; else do; /* * we can do nothing because we have insufficient memory to adjust the block */ ; end; end; end newBitArrayLength; setBit: procedure ( thisPtr, bitIndex ) LOCAL_VARS public; declare thisPtr bitArray_t, this based thisPtr bitArrayStruct, bitIndex integer; if ( ( bitIndex >= 0 ) and ( bitIndex < this.numberBits ) ) then do; declare whichByte word, whichBit word, arrayBase pointer, bitArray based arrayBase (*) byte; arrayBase = this.bits; whichByte = shr( unsign( bitIndex ), NUMBER_SHIFTS_PER_BYTE ); whichBit = unsign( bitIndex ) and BITS_MASK; bitArray( whichByte ) = bitArray( whichByte ) or bitMasks( whichBit ); end; end setBit; clearBit: procedure ( thisPtr, bitIndex ) LOCAL_VARS public; declare thisPtr bitArray_t, this based thisPtr bitArrayStruct, bitIndex integer; if ( ( bitIndex >= 0 ) and ( bitIndex < this.numberBits ) ) then do; declare whichByte word, whichBit word, arrayBase pointer, bitArray based arrayBase (*) byte; arrayBase = this.bits; whichByte = shr( unsign( bitIndex ), NUMBER_SHIFTS_PER_BYTE ); whichBit = unsign( bitIndex ) and BITS_MASK; bitArray( whichByte ) = bitArray( whichByte ) and ( not bitMasks( whichBit ) ); end; end clearBit; end bitArrayModule;