Acme-Bitfield

 view release on metacpan or  search on metacpan

lib/Acme/Bitfield.pm  view on Meta::CPAN

        # Bits set in self but NOT in other
        my $new = __CLASS__->new( size => $size );
        $new->set_data( $data&.~.$other->data );
        return $new;
    }

    method _clean () {

        # internal method to automatically handle data truncation, padding, and bit masking
        my $expected_len = int( ( $size + 7 ) / 8 );
        if ( length($data) > $expected_len ) {
            substr( $data, $expected_len ) = "";
        }
        elsif ( length($data) < $expected_len ) {
            $data .= "\0" x ( $expected_len - length($data) );
        }
        my $bits_in_last_byte = $size % 8;
        if ( $bits_in_last_byte != 0 && $expected_len > 0 ) {
            my $mask = ( 0xFF << ( 8 - $bits_in_last_byte ) ) & 0xFF;
            substr( $data, -1, 1 ) &.= chr($mask);
        }
    }

    method fill () {
        $data = "\xFF" x length($data);
        $self->_clean;
    }

    method find_missing () {
        my $index = index( unpack( 'B*', $data ), '0' );
        return ( $index >= 0 && $index < $size ) ? $index : ();
    }

    method inverse () {
        my $inverted = __CLASS__->new( size => $size );

t/basics.t  view on Meta::CPAN

subtest 'Edge Cases' => sub {
    subtest 'Zero Size' => sub {
        my $bf = Acme::Bitfield->new( size => 0 );
        is( $bf->data,  '', 'Data is empty string' );
        is( $bf->count, 0,  'Count is 0' );
        ok( $bf->is_full, 'Zero size is technically full' );
    };
    subtest 'Mismatched Data Length' => sub {
        my $bf = Acme::Bitfield->new( size => 8 );
        $bf->set_data("\xFF\xFF\xFF");
        is( length( $bf->data ), 1, 'Data truncated to 1 byte' );
        is( $bf->count,          8, 'Count is 8' );
        $bf->set_data("");
        is( length( $bf->data ), 1, 'Data padded to 1 byte' );
        is( ord( $bf->data ),    0, 'Padded with zeros' );
    };
    subtest 'Last Byte Masking' => sub {
        my $bf = Acme::Bitfield->new( size => 10 );

        # 10 bits = 2 bytes. Last byte should only have 2 bits.
        $bf->set_data("\xFF\xFF");
        is( ord( substr( $bf->data, 1, 1 ) ), 0xC0, 'Last byte masked to 0xC0' );
        is( $bf->count,                       10,   'Count is 10' );
    };



( run in 0.887 second using v1.01-cache-2.11-cpan-140bd7fdf52 )