Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

How to easily convert the pack function from little endian to big endian

by semiconPERL (Initiate)
on Aug 10, 2012 at 09:18 UTC ( [id://986699]=perlquestion: print w/replies, xml ) Need Help??

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

hi masters of perl, is there a way to easily convert this code

read EP, $in, 2; $rec_len = unpack ("S", $in);
so that the output of $rec_len is the same for big endian and little endian machines?

Replies are listed 'Best First'.
Re: How to easily convert the pack function from little endian to big endian
by BrowserUk (Patriarch) on Aug 10, 2012 at 09:33 UTC

    Yes:

    read EP, $in, 2; $rec_len = unpack ("S>", $in);

    But whether that is the right output will depend upon what you got sent.

    This would also produce the same output on either type of machine:

    read EP, $in, 2; $rec_len = unpack ("S<", $in);

    But which of those would produce the correct output, depend entirely on whether the data was packed in little or big-endian order to start with.

    And that cannot be determined by the receiver; it can only be assumed.


    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.

    The start of some sanity?

Re: How to easily convert the pack function from little endian to big endian
by Marshall (Canon) on Aug 10, 2012 at 14:49 UTC
    You might find the wiki article Endianness interesting.

    Since you are using the term "$rec_len", the perhaps significant thing here is what is called Network order.

    The Internet Protocol defines big-endian as the standard network byte order used for all numeric values in the packet headers and by many higher level protocols and file formats that are designed for use over IP....other stuff about the socket API...

    The internet wouldn't work if there weren't some standards for this stuff. Often communicating over the internet requires conversion from the little endian format to big endian (Intel is a major force!). Local file storage is usually done in the native way the platform most naturally uses.

    This whole business gets really messy if you are transferring a file between different architectures -> you just have to know what it is that you are dealing with. Standards for floating point binary are problematic.

    But often you do know - example if it is say a Microsoft .WAV file - it is little endian and there is a detailed spec that defines all this.

    Anyway sorry there is no "one size fits all" that can be universally discovered on the "fly". I should note that if you are defining the protocol, converting to an ascii representation within a file is "thinkable" if the performance hit is not a problem.

Re: How to easily convert the pack function from little endian to big endian
by flexvault (Monsignor) on Aug 10, 2012 at 14:19 UTC

    Welcome semiconPERL,

    I'm going to guess that your problem is more about transferring data from big to little endian and vice-versa. One method I use is to convert the data to printable hex which is in network order. See the below code (tested):

    #!/usr/local/bin/perl -w my $data = ""; for (0..255) { $data .= chr($_); } ## All possible byte combinations open ( my $out, ">", "./testdata" ) or die "$!\n"; my $hdata = unpack("H*",$data); print $out "$hdata\n"; close $out; open ( my $in, "<", "./testdata" ) or die "$!\n"; my $sz = read( $in, my $new, 256 ); chomp( $new ); close $in; my $ndata = pack("H*",$new); # print "$hdata\n\n$new\n\n"; if ( $ndata eq $data ) { print "1. Okay\n"; } if ( $hdata eq $new ) { print "2. Okay\n"; } exit; 1;
    I verified on both little/bin endian machines that the file created is exactly the same. You can ftp the files back and forth and all information will be in network order. You can process the data in 4 characters (16 bits), 8 characters (32 bits), or 16 characters (64 bits) by using the 'substr' function on the the beginning of the data:
    my $S16bits = substr($new, 0, 4, "" ); ## 4 bytes printable hex or my $S16bits = substr($ndata, 0, 2, "" ); ## 2 bytes hex data
    If you need to have variable data, then use a separator between variables in the data. I usually use 'chr(254)' as a separator since my editor shows it as a special character, but you can use any non-printable character. Then use 'split' to separate the variables.

    Good Luck

    "Well done is better than well said." - Benjamin Franklin

Re: How to easily convert the pack function from little endian to big endian
by Tux (Canon) on Aug 13, 2012 at 06:30 UTC

    If you control both ends, either use the alread mentioned "S>" or "S<" or the network versions "n" and "v" (see perldoc -f pack).

    s A signed short (16-bit) value. S An unsigned short value. n An unsigned short (16-bit) in "network" (big-endian) order. v An unsigned short (16-bit) in "VAX" (little-endian) order.

    I made an overview of those pack results here for one of my talks.


    Enjoy, Have FUN! H.Merijn

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (3)
As of 2024-03-19 04:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found