Packing/Unpacking bit fields from a byte.

Discussion in 'Perl Misc' started by Shashank R Khanvilkar, Sep 25, 2005.

  1. Hi,
    All help appreciated.

    I have to parse a file which has a header. This header is say 4 bytes long
    and contains many fields which are not byte aligned. For example

    struct header {
    #fieldname: Size(bits)
    fld1: 12
    fld2: 1
    fld3: 2
    ....
    }

    I have already written a lengthy routing to unpack these fileds from the
    header (using shifts and masks). However i was wondering if the same could
    have been achieved using the pack and unpack functions?
    For example:

    @hdr = unpack("B12B1B2....", $header);

    I find that this does not work.
    Does anyone know how this can be done.

    To complicate the problem fursther, how can the same be achieved for any
    aribitary length header (say 15 bytes).

    Thanks
    Shashank
    Shashank R Khanvilkar, Sep 25, 2005
    #1
    1. Advertising

  2. Shashank R Khanvilkar <> wrote:

    > say 4 bytes long
    > and contains many fields which are not byte aligned.



    > I have already written a lengthy routing to unpack these fileds from the
    > header (using shifts and masks).



    perldoc -f vec


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Sep 25, 2005
    #2
    1. Advertising

  3. Shashank R Khanvilkar

    Bob Walton Guest

    Shashank R Khanvilkar wrote:

    ....
    > I have to parse a file which has a header. This header is say 4 bytes long
    > and contains many fields which are not byte aligned. For example
    >
    > struct header {
    > #fieldname: Size(bits)
    > fld1: 12
    > fld2: 1
    > fld3: 2
    > ...
    > }
    >
    > I have already written a lengthy routing to unpack these fileds from the
    > header (using shifts and masks). However i was wondering if the same could
    > have been achieved using the pack and unpack functions?
    > For example:
    >
    > @hdr = unpack("B12B1B2....", $header);
    >
    > I find that this does not work.


    Why do you think that doesn't work? It seems to work to me:

    C:>perl -MData::Dumper -e "print Dumper unpack 'B12B1B2','abcd'"
    $VAR1 = '011000010110';
    $VAR2 = '0';
    $VAR3 = '01';

    C:\Temp>
    ....
    > Shashank

    --
    Bob Walton
    Email: http://bwalton.com/cgi-bin/emailbob.pl
    Bob Walton, Sep 25, 2005
    #3
  4. On Sun, 25 Sep 2005, Bob Walton wrote:

    > Shashank R Khanvilkar wrote:
    >
    > ...
    > > I have to parse a file which has a header. This header is say 4 bytes long
    > > and contains many fields which are not byte aligned. For example
    > >
    > > struct header {
    > > #fieldname: Size(bits)
    > > fld1: 12
    > > fld2: 1
    > > fld3: 2
    > > ...
    > > }
    > >
    > > I have already written a lengthy routing to unpack these fileds from the
    > > header (using shifts and masks). However i was wondering if the same could
    > > have been achieved using the pack and unpack functions?
    > > For example:
    > >
    > > @hdr = unpack("B12B1B2....", $header);
    > >
    > > I find that this does not work.

    >
    > Why do you think that doesn't work? It seems to work to me:
    >
    > C:>perl -MData::Dumper -e "print Dumper unpack 'B12B1B2','abcd'"
    > $VAR1 = '011000010110';
    > $VAR2 = '0';
    > $VAR3 = '01';
    >

    Thanks.. I guess it is taking the ascii values of a(=61 = 0x01100001)..

    Thanks for your help
    Shank



    > C:\Temp>
    > ...
    > > Shashank

    > --
    > Bob Walton
    > Email: http://bwalton.com/cgi-bin/emailbob.pl
    >
    Shashank R Khanvilkar, Sep 25, 2005
    #4
  5. Hi,

    I just found that the below solution may not work for me. Here is a test
    case.

    for example:
    perl -MData::Dumper -e "print Dumper unpack 'B4B4B4B4B*','abcd'"
    $VAR1 = '0110';
    $VAR2 = '0110';
    $VAR3 = '0110';
    $VAR4 = '0110';
    $VAR5 = '';

    Here the string abcd corresponds to 4 ascii characters.
    a = 0x61 = 0110 0001
    b = 0x62 = 0110 0010
    c = 0x63 = 0110 0011
    d = 0x64 = 0110 0100

    So i want the output to print something like
    $VAR1 = '0110';
    $VAR2 = '0001';
    $VAR3 = '0110';
    $VAR4 = '0011';
    $VAR5 = '0110001101100100';

    I gues the unpack function seeks byte boundaries for every conversion.
    Will appreciate if someone can verify this.
    All alternate solutions are also welcome.
    Shank







    >> Shashank R Khanvilkar wrote:
    >>
    >> ...
    >>> I have to parse a file which has a header. This header is say 4 bytes long
    >>> and contains many fields which are not byte aligned. For example
    >>>
    >>> struct header {
    >>> #fieldname: Size(bits)
    >>> fld1: 12
    >>> fld2: 1
    >>> fld3: 2
    >>> ...
    >>> }
    >>>
    >>> I have already written a lengthy routing to unpack these fileds from the
    >>> header (using shifts and masks). However i was wondering if the same could
    >>> have been achieved using the pack and unpack functions?
    >>> For example:
    >>>
    >>> @hdr = unpack("B12B1B2....", $header);
    >>>
    >>> I find that this does not work.

    >>
    >> Why do you think that doesn't work? It seems to work to me:
    >>
    >> C:>perl -MData::Dumper -e "print Dumper unpack 'B12B1B2','abcd'"
    >> $VAR1 = '011000010110';
    >> $VAR2 = '0';
    >> $VAR3 = '01';
    >>

    > Thanks.. I guess it is taking the ascii values of a(=61 = 0x01100001)..
    >
    > Thanks for your help
    > Shank
    >
    >
    >
    >> C:\Temp>
    >> ...
    >>> Shashank

    >> --
    >> Bob Walton
    >> Email: http://bwalton.com/cgi-bin/emailbob.pl
    >>

    >
    Shashank Khanvilkar, Sep 25, 2005
    #5
  6. Thanks
    I have already checked out vector. It does not help.
    Howver I now found out that the following works.

    @headerFeilds = unpack("A12A1A2....", unpack("B*", $header));

    The innermost unpack first converts the header to a string of bits.
    the outer unpack just seperates out these bits into the fields.


    Let me know if there is anything better than this.
    Shashank


    On Sat, 24 Sep 2005, Tad McClellan wrote:

    > Shashank R Khanvilkar <> wrote:
    >
    >> say 4 bytes long
    >> and contains many fields which are not byte aligned.

    >
    >
    >> I have already written a lengthy routing to unpack these fileds from the
    >> header (using shifts and masks).

    >
    >
    > perldoc -f vec
    >
    >
    > --
    > Tad McClellan SGML consulting
    > Perl programming
    > Fort Worth, Texas
    >
    Shashank Khanvilkar, Sep 25, 2005
    #6
  7. Shashank R Khanvilkar

    Anno Siegel Guest

    Shashank Khanvilkar <> wrote in comp.lang.perl.misc:

    Ugh, top posting.

    > Thanks
    > I have already checked out vector. It does not help.


    Sure? vec() (not vector) gives you access to the individual bits of a
    bit string, which is what you want.

    > Howver I now found out that the following works.
    >
    > @headerFeilds = unpack("A12A1A2....", unpack("B*", $header));
    >
    > The innermost unpack first converts the header to a string of bits.
    > the outer unpack just seperates out these bits into the fields.


    Here is one way using vec():

    my $i = 0;
    my @fields = map join( '', map vec( $header, $i ++, 1), 1 .. $_),
    12, 1, 2;

    There is no programming-around the quirks of unpack(), it accesses
    each individual bit as directly as vec() allows. It's longer, but
    so would be the unpack()-solution if it had to build the pack format
    from parameters.

    Pack and unpack are powerful, but not easy to use. Many Perl programmers
    feel it's enough to know the possibilities but avoid them if there is
    an alternative.

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
    Anno Siegel, Sep 26, 2005
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Victor S. Miller

    Packing and unpacking bitvectors

    Victor S. Miller, Oct 9, 2003, in forum: Python
    Replies:
    0
    Views:
    283
    Victor S. Miller
    Oct 9, 2003
  2. Eelco
    Replies:
    121
    Views:
    1,647
    Eelco
    Jan 3, 2012
  3. Lucas L.
    Replies:
    12
    Views:
    179
    ara.t.howard
    Jun 16, 2008
  4. Aaron D. Gifford
    Replies:
    3
    Views:
    168
    Aaron D. Gifford
    Apr 7, 2011
  5. Replies:
    4
    Views:
    106
    Ned Batchelder
    Nov 13, 2013
Loading...

Share This Page