Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

How do I test if a bit has been set in a bitstring

by willk1980 (Novice)
on Apr 25, 2013 at 02:07 UTC ( #1030559=perlquestion: print w/ replies, xml ) Need Help??
willk1980 has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I've got a filename which contains some flags about the file stored as a bitstring. I can extract the bitstring from the filename, but I can't seem to work out how to test if a particular bit is set or not.

The files are stored as:
<filename>.<bitstring>
e.g. mymessage.1004

The definition for the different bits are:

FLAG_DELETED 0x0001 FLAG_DRAFT 0x0002 FLAG_SEEN 0x0004 FLAG_RECENT 0x0008 FLAG_FLAGGED 0x0010 FLAG_ANSWERED 0x0020 FLAG_SAVED 0x0040 FLAG_MDNSENT 0x0080 FLAG_STTPENDING 0x0100 FLAG_FAVOURITE 0x0200 FLAG_NOTIFY 0x0400 FLAG_STTPRESENT 0x0800 FLAG_STTCOMPLETE 0x1000

All integers are expressed in hex format. So if I have the following "1004", that means the SEEN flag and the STTCOMPLETE flag have been set.

I'm trying to test if the FAVOURITE flag has been set, but I don't really understand how to do it. I see posts online about unpacking the bits using the perl unpack function, but I'm not sure how to use it.

I'm sure this is trivial, but I'm still relatively new to perl and writing software, so please be kind.

Comment on How do I test if a bit has been set in a bitstring
Download Code
Re: How do I test if a bit has been set in a bitstring
by Athanasius (Monsignor) on Apr 25, 2013 at 02:55 UTC

    Extract the flag, convert it to hex, then bitwise-AND it with the flag you want to test:

    #! perl use strict; use warnings; use constant { FLAG_DELETED => 0x0001, FLAG_DRAFT => 0x0002, FLAG_SEEN => 0x0004, FLAG_RECENT => 0x0008, FLAG_FLAGGED => 0x0010, FLAG_ANSWERED => 0x0020, FLAG_SAVED => 0x0040, FLAG_MDNSENT => 0x0080, FLAG_STTPENDING => 0x0100, FLAG_FAVOURITE => 0x0200, FLAG_NOTIFY => 0x0400, FLAG_STTPRESENT => 0x0800, FLAG_STTCOMPLETE => 0x1000, }; my $filename = 'mymessage.1004'; my ($flags) = $filename =~ / \. ([0-9a-fA-F]+) $ /x; $flags = hex $flags; my $favourite = $flags & FLAG_FAVOURITE; print "\nIn file '$filename', the FAVOURITE flag is ", ($favourite ? 'SET' : 'NOT SET'), "\n";

    Output:

    12:53 >perl 610_SoPW.pl In file 'mymessage.1004', the FAVOURITE flag is NOT SET 12:57 >

    Update: Fixed the regular expression to handle all hexadecimal digits. Thanks to jwkrahn, below.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      my ($flags) = $filename =~ / \. (\d+) $ /x;

      That won't work correctly because it doesn't match the hexadecimal digits A, B, C, D, E and F.

      my ($flags) = $filename =~ / \. ([0-9a-fA-F]+) $ /x;

      [0-9a-fA-F] is also available (and, IMHO, preferable) as the  [[:xdigit:]] POSIX character class. See POSIX Character Classes in perlre for info on this and its many Unicode  \p{Property} cousins.

      Thanks for the quick responses. It was using hex EXPR I was missing from my tests. Many thanks for the help, especially Athanasius and BrowserUk.
Re: How do I test if a bit has been set in a bitstring
by BrowserUk (Pope) on Apr 25, 2013 at 02:58 UTC

    The ascii characters '1004' are not a "bitstring". They are the hex representation of an integer.

    Try this:

    #! perl -slw use strict; use constant FLAGS => { FLAG_DELETED => 0x0001, FLAG_DRAFT => 0x0002, FLAG_SEEN => 0x0004, FLAG_RECENT => 0x0008, FLAG_FLAGGED => 0x0010, FLAG_ANSWERED => 0x0020, FLAG_SAVED => 0x0040, FLAG_MDNSENT => 0x0080, FLAG_STTPENDING => 0x0100, FLAG_FAVOURITE => 0x0200, FLAG_NOTIFY => 0x0400, FLAG_STTPRESENT => 0x0800, FLAG_STTCOMPLETE => 0x1000, }; my( $text, $int ) = split '\.', <DATA>; chomp $int; $int = hex $int; printf "Flag '%s' (%u) %s set\n", $_, FLAGS->{ $_ }, $int & FLAGS->{ $_ } ? 'is' : 'is not' for keys %{ FLAGS() }; __DATA__ mymessage.1004

    Outputs:

    C:\test>1030559.pl Flag 'FLAG_RECENT' (8) is not set Flag 'FLAG_STTPRESENT' (2048) is not set Flag 'FLAG_STTPENDING' (256) is not set Flag 'FLAG_FAVOURITE' (512) is not set Flag 'FLAG_DELETED' (1) is not set Flag 'FLAG_NOTIFY' (1024) is not set Flag 'FLAG_DRAFT' (2) is not set Flag 'FLAG_FLAGGED' (16) is not set Flag 'FLAG_SEEN' (4) is set Flag 'FLAG_SAVED' (64) is not set Flag 'FLAG_ANSWERED' (32) is not set Flag 'FLAG_STTCOMPLETE' (4096) is set Flag 'FLAG_MDNSENT' (128) is not set

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: How do I test if a bit has been set in a bitstring
by Anonymous Monk on Apr 25, 2013 at 03:22 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1030559]
Approved by Athanasius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (9)
As of 2014-10-21 13:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (103 votes), past polls