Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Named Bits in a 32-bit integer

by RollyGuy (Chaplain)
on Jul 31, 2002 at 18:06 UTC ( #186551=perlquestion: print w/replies, xml ) Need Help??

RollyGuy has asked for the wisdom of the Perl Monks concerning the following question:

I'm using a SWIG interface to C++ on one of my projects at work. On the C++ side, we have a 32-bit integer where the different bits represent different (named) settings. We're using perl as the interface to C++ and would like an easy way to set (and unset) these bits using named constants. In C++ there are Enumerated values that give me that functionality. Is there anything like that in perl?

Is there a good way to do this?

Replies are listed 'Best First'.
Re: Named Bits in a 32-bit integer
by RMGir (Prior) on Jul 31, 2002 at 18:33 UTC
    Sure, the constant pragma.
    use constant BIT0 => 0; use constant BIT1 => 1; use constant BIT2 => 2; use constant BIT3 => 4; #...
    That's pretty verbose, though... You could just use a hash, and do
    my %bitNames = ( BIT0 => 0, BIT1 => 1, BIT2 => 2, BIT3 => 4, BIT4 => 8, #... );
    Of course, you can substitute your more meaningful names for BIT0..BITn...

    That handles naming the bits; you could use the vec built-in function to set them, like this:

    my $flag=0; # or value from your api vec($flag, $bitNames{BIT0}, 1)=$newBit; # you can also use vec to retrieve the old bit values: print "Value at position BIT3 is:",vec($flag, $bitNames{BIT3},1),"\n";

    --
    Mike
    EDIT: Added part about vec; I'd only covered naming the bits, and forgotten the other part...
Re: Named Bits in a 32-bit integer
by BronzeWing (Monk) on Jul 31, 2002 at 19:27 UTC

    I think the simplest way to do it is with the &, |, ^, and ~ operators. An example:

    #!/usr/bin/perl use warnings; use strict; use constant EXECUTE => 1; use constant WRITE => 2; use constant READ => 4; my $Permissions = 0; $Permissions |= READ; # Set READ to true $Permissions |= WRITE; # Set WRITE to true $Permissions &= ~READ; # Set READ to false $Permissions ^= EXECUTE; # Toggle EXECUTE print $Permissions, "\n";

    Prints "3" (that's WRITE and EXECUTE).
    Is this what you were looking for?

    -BronzeWing

    Update:
    Oops! I completely forgot getting the info back out again. To check the status of a bit:

    if ($Permissions & READ) { print "You can read.\n"; } else { print "You can't read.\n"; }

    Just like that.


    The Secret to Fortune Cookies in One Line
    print join("... in bed", `fortune fortunes` =~ m/^(.*)(\.|\?|\!)$/), "\n";

Re: Named Bits in a 32-bit integer
by fglock (Vicar) on Jul 31, 2002 at 19:40 UTC

    I'm still thinking about it, but I think this is more or less what you need (there might be a module that does this on CPAN; "enum" comes pretty close) :

    use strict; package Bit; use Tie::Scalar; sub TIESCALAR { my ($self) = bless {}, shift; $self->{ref} = shift; $self->{mask} = shift; $self->{bit} = 0; return $self unless $self->{mask}; # mask can't be zero my $tmp = $self->{mask}; while ( !($tmp & 1)) { $tmp >>= 1; $self->{bit} ++; } return $self; } sub FETCH { my $self = shift; return ( ${$self->{ref}} & $self->{mask} ) >> $self->{bit} ; } sub STORE { my $self = shift; my $value = shift; ${$self->{ref}} |= $self->{mask}; ${$self->{ref}} ^= $self->{mask}; ${$self->{ref}} |= $self->{mask} & ($value << $self->{bit}); } #--------------------- my $bits = 0; # a "n-bits" variable tie my $a, 'Bit', \$bits, 0x07; # bits 0..3 are $a tie my $b, 'Bit', \$bits, 0x70; # bits 4..7 are $b $a = 1; print "$bits\n"; # 1 $b = 1; print "$bits\n"; # 17 $a = 0; print "$bits\n"; # 16

    update: - The "bit" parameter is calculated by TIESCALAR.
    - Using "vec" instead of bitwise operations is a good idea.
    - Added "mask can't be zero" test.

Re: Named Bits in a 32-bit integer
by hiseldl (Priest) on Jul 31, 2002 at 18:40 UTC
    Assuming perl -P works on your system, you could define macros. Here is a short example:
    #!/usr/bin/perl -P # set this to the bit masks #define ONE 1 #define TWO 2 #define THREE 3 #define FOUR 4 print "bitwise AND (ONE & FOUR)=", ONE & FOUR, "\n"; print "bitwise AND (ONE & THREE)=", ONE & THREE, "\n";
    then running the script will produce:
    $ ./script.pl
    bitwise AND (ONE & FOUR)=0
    bitwise AND (ONE & THREE)=1
    

    If perl -P gives an error where it can't find cpp, you can probably copy the one from your gcc dist into a directory into your path.

    --
    hiseldl

Re: Named Bits in a 32-bit integer
by perrin (Chancellor) on Jul 31, 2002 at 18:42 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://186551]
Approved by jeffa
Front-paged by jeffa
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2022-08-09 01:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?